Button is not working on the second window of pyqt5 - python

I'm making a first come first served scheduler using pyqt5.
I have the main window which includes textbox asking the user for scheduler type, when button "GO" is clicked, the second window is opened which asks the user for more information about the scheduler like process numbers and burst time .
When button "GO" on the second window is clicked, a Gantt chart should appear after processing the information.
The problem is that the button on the second window is not working at all.
I have found a similar question, but I didn't quite got the solution, plus I'm not using JSON.
Code:
import sys
from PyQt5 import QtGui
from PyQt5.QtWidgets import QMainWindow,QApplication, QComboBox, QDialog,QDialogButtonBox, QFormLayout, QGridLayout, QGroupBox, QHBoxLayout,QLabel, QLineEdit, QMenu, QMenuBar, QPushButton, QSpinBox, QTextEdit,QVBoxLayoutQSpinBox, QTextEdit, QVBoxLayout
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot
import matplotlib.pyplot as plt
import numpy as np
import linked_list
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("My Program")
self.setWindowIcon(QtGui.QIcon("download.jpg"))
self.setGeometry(50,50,500,300)
self.home()
self.show()
def home(self):
self.label2=QLabel(self)
self.label2.setText("Type of Scheduler")
self.label2.move(10,50)
self.textbox2=QLineEdit(self)
self.textbox2.move(100,50)
self.button=QPushButton("Go",self)
self.button.move(0,200)
self.button.clicked.connect(self.runcode)
def runcode(self):
schedular_type=self.textbox2.text()
if(schedular_type=="FCFS"):
self.close()
self.fcfs=Window2(self)
Self.fcfs.__init__()
class Window2(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("My Program")
self.setWindowIcon(QtGui.QIcon("download.jpg"))
self.setGeometry(50,50,500,300)
self.home()
self.show()
def home(self):
self.label1=QLabel(self)
self.label1.setText("No of Processes")
self.label1.move(10,0) #col ,row
self.textbox=QLineEdit(self)
self.textbox.move(100,0)
self.label3=QLabel(self)
self.label3.setText("Processess Names")
self.label3.move(10,100)
self.label4=QLabel(self)
self.label4.setText("Burst Time")
self.label4.move(120,100)
self.label5=QLabel(self)
self.label5.setText("Arrival Time")
self.label5.move(200,100)
self.names=QLineEdit(self)
self.names.move(10,150)
# self.names.resize(100,160)
self.burst=QLineEdit(self)
self.burst.move(120,150)
#self.burst.resize(100,160)
self.arrival=QLineEdit(self)
self.arrival.move(250 ,150)
#self.arrival.resize(100,160)
#self.textEdit=QTextEdit(self)
#self.textEdit.move(20,250)
self.button=QPushButton("Go",self)
self.button.move(0,200)
self.button.clicked.connect(self.fcfs)
def fcfs(self):
//
def main():
app = QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

Set a parent to second window, also you are calling ____init____ method of Window2 twice.
Here is the fixed code :
import sys
from PyQt5 import QtGui
from PyQt5.QtWidgets import (QMainWindow, QApplication, QComboBox,
QDialog, QDialogButtonBox, QFormLayout, QGridLayout, QGroupBox,
QHBoxLayout, QLabel, QLineEdit, QMenu, QMenuBar, QPushButton, QSpinBox,
QTextEdit, QVBoxLayout)
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot
import matplotlib.pyplot as plt
import numpy as np
import linked_list
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("My Program")
self.setWindowIcon(QtGui.QIcon("download.jpg"))
self.setGeometry(50, 50, 500, 300)
self.home()
self.show()
def home(self):
self.label2 = QLabel(self)
self.label2.setText("Type of Scheduler")
self.label2.move(10, 50)
self.textbox2 = QLineEdit(self)
self.textbox2.move(100, 50)
self.button = QPushButton("Go", self)
self.button.move(0, 200)
self.button.clicked.connect(self.runcode)
def runcode(self):
schedular_type = self.textbox2.text()
if(schedular_type == "FCFS"):
self.close()
fcfs = Window2(self)
# Do not call __init__ explicitly below
# fcfs.__init__()
class Window2(QMainWindow):
def __init__(self,parent=None):
super().__init__(parent)
# always try to set a parent
self.setWindowTitle("My Program")
self.setWindowIcon(QtGui.QIcon("download.jpg"))
self.setGeometry(50, 50, 500, 300)
self.home()
self.show()
def home(self):
self.label1 = QLabel(self)
self.label1.setText("No of Processes")
self.label1.move(10, 0) # col ,row
self.textbox = QLineEdit(self)
self.textbox.move(100, 0)
self.label3 = QLabel(self)
self.label3.setText("Processess Names")
self.label3.move(10, 100)
self.label4 = QLabel(self)
self.label4.setText("Burst Time")
self.label4.move(120, 100)
self.label5 = QLabel(self)
self.label5.setText("Arrival Time")
self.label5.move(200, 100)
self.names = QLineEdit(self)
self.names.move(10, 150)
# self.names.resize(100,160)
self.burst = QLineEdit(self)
self.burst.move(120, 150)
# self.burst.resize(100,160)
self.arrival = QLineEdit(self)
self.arrival.move(250, 150)
# self.arrival.resize(100,160)
# self.textEdit=QTextEdit(self)
# self.textEdit.move(20,250)
self.button = QPushButton("Go", self)
self.button.move(0, 200)
self.button.clicked.connect(self.fcfs)
def fcfs(self):
no_of_process = self.textbox.text()
process_names = self.names.text()
burst_time = self.burst.text()
arrival_time = self.arrival.text()
names_list = process_names.split()
burst_list = burst_time.split()
arrival_list = arrival_time.split()
# integer conversion
burst_list = [int(i) for i in burst_list]
arrival_list = [int(i) for i in arrival_list]
no_of_process = int(no_of_process)
ls = LinkedList()
i = 0
while i < no_of_process:
ls.append(names_list[i], burst_list[i], arrival_list[i])
i = i + 1
time = arrival_list[0]
j = 0
start = []
end = []
name = []
while j < (ls.size()):
while(time < arrival_list[j]):
time = time + 1
start.append(time)
time = time + burst_list[j]
end.append(time)
name.append(names_list[j])
j = j + 1
waiting_time = 0
k = 0
average_waiting = 0
while k < (ls.size()):
waiting_time = waiting_time + \
end[k] - arrival_list[k] - burst_list[k]
average_waiting = waiting_time / ls.size()
k = k + 1
x = name
begin = np.array(start)
end = np.array(end)
plt.barh(range(len(begin)), end - begin, left=begin)
plt.yticks(range(len(begin)), x)
#plt.text(0.6,1.5,('average waiting is ',average_waiting))
plt.annotate(("average waiting is", average_waiting), xy=(0.5, 1.49))
plt.show()
def main():
app = QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
the crucial part is:
def __init__(self,parent=None):
super().__init__(parent)

Related

Disable Carriage Return (Enter Key Press) in QPlainTextEdit()

This is what my example looks like:
The text area is a QPlainTextEdit() object because I want the text to wrap to the second line. I think this is the best widget choice.
The user will only enter a maximum number of 90 characters in this box so I don't need a large text area.
I want to disable the key press Enter (carriage return). I got it to work but it seems hacky and I don't think it would work cross-platform (ex: Mac).
Surely, there's got to be a better way to prevent a carriage return key event in a QPlainTextEdit object?
My Current Solution Explained
Below, you can see I'm checking if an IndexError occurs because the last_value throws an IndexError when there's nothing in the QPlainTextEdit box. Then, I'm getting the last character and asking if it's equal to a new line. If it is, I'm re-setting the text without that new line and moving the cursor to the end.
def some_event(self):
try:
last_value = self.field.toPlainText()[-1]
if last_value == '\n':
print('You Pressed Enter!', repr(last_value))
self.field.setPlainText(self.field.toPlainText()[:-1])
self.field.moveCursor(QTextCursor.End)
except IndexError:
print('Index Error occurred')
pass
Full Code Minimal Working Example:
from PyQt5.QtWidgets import (QWidget, QMainWindow, QGridLayout, QPushButton,
QApplication, QPlainTextEdit, QLabel)
from PyQt5.QtGui import QTextCursor
class BasicWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initWindow()
def initWindow(self):
self.setGeometry(400, 300, 400, 100)
self.grid = QGridLayout()
self.label = QLabel('Description Line 1')
self.grid.addWidget(self.label, 0, 0)
self.field = QPlainTextEdit()
self.field.setMaximumHeight(40)
self.field.textChanged.connect(self.some_event)
#TODO how to disable enter/return key events in this field?
self.grid.addWidget(self.field, 1, 0)
self.button = QPushButton('Some Button')
self.grid.addWidget(self.button)
self.centralWidget = QWidget()
self.centralWidget.setLayout(self.grid)
self.setCentralWidget(self.centralWidget)
def some_event(self):
try:
last_value = self.field.toPlainText()[-1]
if last_value == '\n':
print('You Pressed Enter!', repr(last_value))
self.field.setPlainText(self.field.toPlainText()[:-1])
self.field.moveCursor(QTextCursor.End)
except IndexError:
print('Index Error occurred')
pass
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = BasicWindow()
window.show()
sys.exit(app.exec_())
One option is to override the keyPressEvent method of the QPlainTextEdit:
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QTextCursor
from PyQt5.QtWidgets import (QWidget, QMainWindow, QGridLayout, QPushButton,
QApplication, QPlainTextEdit, QLabel)
class PlainTextEdit(QPlainTextEdit):
def keyPressEvent(self, event):
if event.key() in (Qt.Key_Return, Qt.Key_Enter):
return
super().keyPressEvent(event)
class BasicWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initWindow()
def initWindow(self):
self.setGeometry(400, 300, 400, 100)
self.label = QLabel("Description Line 1")
self.field = PlainTextEdit()
self.field.setMaximumHeight(40)
self.button = QPushButton("Some Button")
self.centralWidget = QWidget()
grid = QGridLayout(self.centralWidget)
grid.addWidget(self.label, 0, 0)
grid.addWidget(self.field, 1, 0)
grid.addWidget(self.button)
self.setCentralWidget(self.centralWidget)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
window = BasicWindow()
window.show()
sys.exit(app.exec_())
Another option that implements the same logic is to use an eventFilter().
from PyQt5.QtCore import QEvent, Qt
from PyQt5.QtGui import QTextCursor
from PyQt5.QtWidgets import (QWidget, QMainWindow, QGridLayout, QPushButton,
QApplication, QPlainTextEdit, QLabel)
class BasicWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initWindow()
def initWindow(self):
self.setGeometry(400, 300, 400, 100)
self.label = QLabel("Description Line 1")
self.field = QPlainTextEdit()
self.field.setMaximumHeight(40)
self.button = QPushButton("Some Button")
self.field.installEventFilter(self)
self.centralWidget = QWidget()
grid = QGridLayout(self.centralWidget)
grid.addWidget(self.label, 0, 0)
grid.addWidget(self.field, 1, 0)
grid.addWidget(self.button)
self.setCentralWidget(self.centralWidget)
def eventFilter(self, obj, event):
if obj is self.field and event.type() == QEvent.KeyPress:
if event.key() in (Qt.Key_Return, Qt.Key_Enter):
return True
return super().eventFilter(obj, event)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
window = BasicWindow()
window.show()
sys.exit(app.exec_())

Import registration form as a selection in program list, and close form when finished; when I return to open form again, no response in same session [duplicate]

This question already has answers here:
Create object from class in separate file
(3 answers)
PyQT: how to open new window
(1 answer)
Closed 3 years ago.
I want to open a form that is represented in a register file that is opened by a click in register button in the login window (main.py) but when the registration form is closed, it can not be opened again in the same session.
But I have to close the whole program and then open it again so that I can get rid of the register only once... and so on.
As well as how to become the register form child of the main model.
If you need to register some users when you open the application then close the form and do some transactions in the same application. And then return to register another person by clicking on the register button to open its from, The problem occurs that the register file is not imported again and therefore do not open the registration form.
So how do I solve this problem so I can open the registration form or any other form I import several times (in the same session) without closing. The program and opens it again.
This file indicated into main.py:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton
from PyQt5.QtGui import QPixmap, QIcon
app = QApplication(sys.argv)
mainRoot = QWidget()
mainRoot.setWindowTitle('Login')
mainRoot.setWindowIcon(QIcon('image\icon2.png'))
lblBackground = QLabel(mainRoot)
pic = QPixmap('image\pic-1.jpg')
lblBackground.setPixmap(pic)
mainRoot.setGeometry(600, 300, 322, 220)
user = QLabel('user name', mainRoot)
user.move(50, 50)
password = QLabel('password', mainRoot)
password.move(50, 80)
username_edt = QLineEdit(mainRoot)
username_edt.move(110, 50)
password_edt = QLineEdit(mainRoot)
password_edt.setEchoMode(QLineEdit.Password)
password_edt.move(110, 75)
signin = QPushButton('sign in', mainRoot)
signin.move(20, 110)
registerBtn = QPushButton('register ', mainRoot)
registerBtn.move(120, 110)
qut_btn = QPushButton('Quit', mainRoot)
qut_btn.move(220, 110)
def registerUser():
import register
registerBtn.clicked.connect(registerUser)
qut_btn.clicked.connect(quit)
mainRoot.show()
sys.exit(app.exec_())
This file indicated into register.py:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QComboBox, QRadioButton
from PyQt5.QtGui import QPixmap
app = QApplication(sys.argv)
signRoot = QWidget()
signRoot.setWindowTitle('Registration')
lblBackground = QLabel(signRoot)
pix = QPixmap('image\pic-10.jpg')
lblBackground.setPixmap(pix)
signRoot.setGeometry(600, 300, 400, 300)
fullNameLbl = QLabel('Full Name', signRoot)
fullNameLbl.move(100, 50)
userNameLbl = QLabel('User Name', signRoot)
userNameLbl.move(100, 80)
passWord = QLabel('password', signRoot)
passWord.move(100, 110)
typeLbl = QLabel('Type', signRoot)
typeLbl.move(100, 140)
departmentLbl = QLabel('Department', signRoot)
departmentLbl.move(100, 180)
fullName = QLineEdit(signRoot)
fullName.move(200, 50)
userName = QLineEdit(signRoot)
userName.move(200, 80)
passWord = QLineEdit(signRoot)
passWord.setEchoMode(QLineEdit.Password)
passWord.move(200, 110)
maleType = QRadioButton('Male', signRoot)
maleType.move(200, 140)
femaleType = QRadioButton('Female', signRoot)
femaleType.move(270, 140)
department = QComboBox(signRoot)
department.move(200, 180)
submitted = QPushButton('Submit', signRoot)
submitted.move(150, 240)
qut_btn = QPushButton('Quit', signRoot)
qut_btn.move(250, 240)
def qutRegisterForm():
signRoot.close()
qut_btn.clicked.connect(qutRegisterForm)
signRoot.show()
After run menu form and appear then click on file and register
After register form appear and close it by clicked on exit button
Can't open register form again when I repeat clicked on file and register
Try it:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class window(QDialog):
def __init__(self):
super().__init__()
self.initWin()
def initWin(self):
self.gridLayoutCreation()
vBoxLayout = QVBoxLayout()
vBoxLayout.addWidget(self.groupBox)
self.setLayout(vBoxLayout)
# --- self.show()
def gridLayoutCreation(self):
self.groupBox = QGroupBox('')
gridLayout = QGridLayout()
qutBtn = QPushButton('Exit')
gridLayout.addWidget(qutBtn, 0, 0)
qutBtn.clicked.connect(self.qut)
self.groupBox.setLayout(gridLayout)
def qut(self):
self.close()
class MainWindow(QMainWindow):
count = 0
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.mdi = QMdiArea()
self.setCentralWidget(self.mdi)
bar = self.menuBar()
file = bar.addMenu("File")
file.addAction("New")
file.addAction("cascade")
file.addAction("Tiled")
file.triggered[QAction].connect(self.openRegister)
def openRegister(self, q):
print("triggered-> q ->", q.text())
if q.text() == "New":
MainWindow.count = MainWindow.count+1
sub = QMdiSubWindow()
sub.setAttribute(Qt.WA_DeleteOnClose)
sub.setWidget(window()) # <---
sub.setWindowTitle("subwindow"+str(MainWindow.count))
sub.setGeometry(100, 100, 400, 400)
self.mdi.addSubWindow(sub)
sub.show()
if q.text() == "cascade":
self.mdi.cascadeSubWindows()
if q.text() == "Tiled":
self.mdi.tileSubWindows()
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
ex = MainWindow()
ex.setWindowTitle("Menu")
ex.show()
sys.exit(app.exec_())
Update
main.py
import sys
from PyQt5.QtWidgets import QMainWindow, QMdiArea, QAction, QApplication
from register import window # +++
class MainWindow(QMainWindow):
count = 0
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.mdi = QMdiArea()
self.setCentralWidget(self.mdi)
bar = self.menuBar()
file = bar.addMenu("File")
open_action = QAction('Open', self) # +++
file.addAction(open_action) # +++
file.triggered[QAction].connect(self.openRegister)
self.setWindowTitle("Menu")
def openRegister(self):
# from register import window
self.win = window(self.mdi) # +++
def main():
app = QApplication(sys.argv)
ex = MainWindow()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
register.py
from PyQt5.QtWidgets import QPushButton, QGridLayout, QDialog,QGroupBox, QVBoxLayout, QApplication
class window(QDialog):
# def __init__(self):
# super().__init__()
def __init__(self, parent=None):
super(window, self).__init__(parent)
self.title = 'register'
self.initWin()
def initWin(self):
self.setWindowTitle(self.title)
self.gridLayoutCreation()
vBoxLayout = QVBoxLayout()
vBoxLayout.addWidget(self.groupBox)
self.setLayout(vBoxLayout)
self.show()
def gridLayoutCreation(self):
self.groupBox = QGroupBox('')
gridLayout = QGridLayout()
qutBtn = QPushButton('Exit')
gridLayout.addWidget(qutBtn, 0, 0)
qutBtn.clicked.connect(self.qut)
self.groupBox.setLayout(gridLayout)
def qut(self):
self.close()
# win = window()
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
ex = window()
ex.setWindowTitle("Menu")
ex.show()
sys.exit(app.exec_())
Update 2
main.py
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton
from PyQt5.QtGui import QPixmap, QIcon
app = QApplication(sys.argv)
mainRoot = QWidget()
mainRoot.setWindowTitle('Login')
mainRoot.setWindowIcon(QIcon('im.png'))
lblBackground = QLabel(mainRoot)
pic = QPixmap('Ok.png')
lblBackground.setPixmap(pic)
mainRoot.setGeometry(600, 300, 322, 220)
user = QLabel('user name', mainRoot)
user.move(50, 50)
password = QLabel('password', mainRoot)
password.move(50, 80)
username_edt = QLineEdit(mainRoot)
username_edt.move(110, 50)
password_edt = QLineEdit(mainRoot)
password_edt.setEchoMode(QLineEdit.Password)
password_edt.move(110, 75)
signin = QPushButton('sign in', mainRoot)
signin.move(20, 110)
registerBtn = QPushButton('register ', mainRoot)
registerBtn.move(120, 110)
qut_btn = QPushButton('Quit', mainRoot)
qut_btn.move(220, 110)
def registerUser():
# import register
from register import registerForm
form = registerForm()
form.show()
registerBtn.clicked.connect(registerUser)
qut_btn.clicked.connect(quit)
mainRoot.show()
sys.exit(app.exec_())
register.py
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QComboBox, QRadioButton
from PyQt5.QtGui import QPixmap
app = QApplication(sys.argv)
def registerForm(): # <=======
signRoot = QWidget()
signRoot.setWindowTitle('Registration')
lblBackground = QLabel(signRoot)
pix = QPixmap('image\pic-10.jpg')
lblBackground.setPixmap(pix)
signRoot.setGeometry(600, 300, 400, 300)
fullNameLbl = QLabel('Full Name', signRoot)
fullNameLbl.move(100, 50)
userNameLbl = QLabel('User Name', signRoot)
userNameLbl.move(100, 80)
passWord = QLabel('password', signRoot)
passWord.move(100, 110)
typeLbl = QLabel('Type', signRoot)
typeLbl.move(100, 140)
departmentLbl = QLabel('Department', signRoot)
departmentLbl.move(100, 180)
fullName = QLineEdit(signRoot)
fullName.move(200, 50)
userName = QLineEdit(signRoot)
userName.move(200, 80)
passWord = QLineEdit(signRoot)
passWord.setEchoMode(QLineEdit.Password)
passWord.move(200, 110)
maleType = QRadioButton('Male', signRoot)
maleType.move(200, 140)
femaleType = QRadioButton('Female', signRoot)
femaleType.move(270, 140)
department = QComboBox(signRoot)
department.move(200, 180)
submitted = QPushButton('Submit', signRoot)
submitted.move(150, 240)
qut_btn = QPushButton('Quit', signRoot)
qut_btn.move(250, 240)
def qutRegisterForm():
signRoot.close()
qut_btn.clicked.connect(qutRegisterForm)
# signRoot.show()
return signRoot # <=======

When executing thread, the first execution fails in try statement

from PyQt5.QtWidgets import QMainWindow, QApplication,QLineEdit, QPushButton, QWidget, QAction, QTabWidget,QVBoxLayout
from PyQt5.QtCore import (QCoreApplication, QObject, QRunnable, QThread,
QThreadPool, pyqtSignal)
import sys
import os
from shutil import copy2
import _thread
import time
class AThread(QThread):
def run(self):
count = 0
while count < 5:
time.sleep(1)
print("A Increasing")
count += 1
class Example(QWidget):
def __init__(self):
super().__init__()
self.setAcceptDrops(True)
self.setWindowTitle('Learn')
self.setGeometry(300, 300, 300, 150)
self.layout = QVBoxLayout(self)
# Initialize tab screen
self.tabs = QTabWidget()
self.tab1 = QWidget()
self.tab2 = QWidget()
self.tabs.resize(300,200)
# Add tabs
self.tabs.addTab(self.tab1,"Tab 1")
self.tabs.addTab(self.tab2,"Tab 2")
# Create first tab
self.tab1.layout = QVBoxLayout(self)
self.pushButton1 = QPushButton("PyQt5 button")
self.pushButton1.clicked.connect(self.ON_PRESS)
self.textbox = QLineEdit(self)
self.tab1.layout.addWidget(self.textbox )
self.tab1.layout.addWidget(self.pushButton1)
self.tab1.setLayout(self.tab1.layout)
#Create Textbox inputs
# Add tabs to widget
self.layout.addWidget(self.tabs)
self.setLayout(self.layout)
def using_q_thread(self):
app = Example()
thread = AThread()
thread.start()
sys.exit(app.exec_())
def ON_PRESS(self):
###Here is the Issue
try:
self.using_q_thread()
except:
print ("Error: unable to start thread")
###Drag and Drop files to directory
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
Hoping I am asking this correctly, but whenever using QThread there appears to be a bit of a hiccup. the first attempt to access the threaded function causes the try statement to fail, but then it immediately works. Im just curious if this is part of the functionality or if there is any issue with my code.
Avoid using try-except as you see hidden the error, in my personal case I avoid using it as far as I can for this type of problems.
I do not see it necessary to create another Example within using_q_thread, another problem is that thread is a local variable that will be eliminated, so thread must be a member of the class for its scope to increase.
import sys
import time
from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QTabWidget, QPushButton, QLineEdit
class AThread(QThread):
def run(self):
count = 0
while count < 5:
time.sleep(1)
print("A Increasing")
count += 1
class Example(QWidget):
def __init__(self):
super().__init__()
self.setAcceptDrops(True)
self.setWindowTitle('Learn')
self.setGeometry(300, 300, 300, 150)
self.layout = QVBoxLayout(self)
# Initialize tab screen
self.tabs = QTabWidget()
self.tab1 = QWidget()
self.tab2 = QWidget()
self.tabs.resize(300,200)
# Add tabs
self.tabs.addTab(self.tab1,"Tab 1")
self.tabs.addTab(self.tab2,"Tab 2")
# Create first tab
self.tab1.layout = QVBoxLayout()
self.pushButton1 = QPushButton("PyQt5 button")
self.pushButton1.clicked.connect(self.ON_PRESS)
self.textbox = QLineEdit(self)
self.tab1.layout.addWidget(self.textbox )
self.tab1.layout.addWidget(self.pushButton1)
self.tab1.setLayout(self.tab1.layout)
#Create Textbox inputs
# Add tabs to widget
self.layout.addWidget(self.tabs)
def using_q_thread(self):
self.thread = AThread()
self.thread.start()
def ON_PRESS(self):
self.using_q_thread()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())

Using a button to open and close a matplotlib widget

The aim of what I've written so far is to have a "Temperature" button in my GUI that when pressed opens up a matplotlib plot that I made separately (mplwidget.py).
However, when I run the code, both the app and the widget open up simultaneously, and the Temperature button appears to have no function (even if I close the widget, pressing the button doesn't open it again).
import sys
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QPushButton, QAction, QMessageBox
from PyQt5.uic.properties import QtGui
from mplwidget import animate #import animation widget
class window(QMainWindow):
def __init__(self):
super(window, self).__init__()
self.setGeometry(50, 50, 500, 300)
self.setWindowTitle('Temperature Control')
self.setWindowIcon(QIcon('adn.png'))
extractAction = QAction('&Quit', self)
extractAction.setShortcut('Ctrl+Q')
extractAction.setStatusTip('leave the app')
extractAction.triggered.connect(self.close_application)
self.statusBar()
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu('&File')
fileMenu.addAction(extractAction)
self.home()
def home(self):
btn = QPushButton('quit', self)
btn.clicked.connect(self.close_application)
btn.resize(btn.sizeHint())
btn.move(0, 100)
button = QPushButton('Temperature',self)
button.clicked.connect(self.opengraph)
button.move(50,200)
self.show()
def opengraph(self):
animate()
def close_application(self):
choice = QMessageBox.question(self, 'Message',
"Are you sure to quit?", QMessageBox.Yes |
QMessageBox.No, QMessageBox.No)
if choice == QMessageBox.Yes:
sys.exit()
else:
pass
if __name__ == "__main__":
def run():
app = QApplication(sys.argv)
Gui = window()
sys.exit(app.exec_())
run()
mplwidget is below
def GraphWidget():
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
Time = []
Temp = []
def animate(i):
x = datetime.datetime.now()
y = numpy.random.randint(48,52)
Time.append(x)
Temp.append(int(y))
# print (Temp)
ax1.plot(Time,Temp)
ani = animation.FuncAnimation(fig,animate, interval=1000)
plt.show()
The problem is that plt.show() cannot start an event loop itself because the event loop is already running due to the QT window being open. In such cases one would need to call fig.show() instead, where fig is the figure in use.
This in turn leads to the problem that the function from the mplwidget.py module actually returns. Once it returns the reference for the animation is lost and will be garbage collected; hence no animation shows up on screen.
The solution is to let the function return the animation and store it somewhere in the main program.
import sys
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QPushButton, QAction, QMessageBox
from PyQt5.uic.properties import QtGui
from mplwidget import showgraph
class window(QMainWindow):
def __init__(self):
super(window, self).__init__()
self.setGeometry(50, 50, 500, 300)
self.setWindowTitle('Temperature Control')
self.setWindowIcon(QIcon('adn.png'))
extractAction = QAction('&Quit', self)
extractAction.setShortcut('Ctrl+Q')
extractAction.setStatusTip('leave the app')
extractAction.triggered.connect(self.close_application)
self.statusBar()
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu('&File')
fileMenu.addAction(extractAction)
self.home()
def home(self):
btn = QPushButton('quit', self)
btn.clicked.connect(self.close_application)
btn.resize(btn.sizeHint())
btn.move(0, 100)
button = QPushButton('Temperature',self)
button.clicked.connect(self.opengraph)
button.move(50,200)
self.show()
def opengraph(self):
self.store = showgraph()
def close_application(self):
choice = QMessageBox.question(self, 'Message',
"Are you sure to quit?", QMessageBox.Yes |
QMessageBox.No, QMessageBox.No)
if choice == QMessageBox.Yes:
sys.exit()
else:
pass
if __name__ == "__main__":
def run():
app = QApplication(sys.argv)
Gui = window()
sys.exit(app.exec_())
run()
mplwidget.py:
import matplotlib.pyplot as plt
import datetime
import numpy
import matplotlib.animation as animation
def showgraph():
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
Time = []
Temp = []
def animate(i):
x = datetime.datetime.now()
y = numpy.random.randint(48,52)
Time.append(x)
Temp.append(int(y))
ax1.plot(Time,Temp)
ani = animation.FuncAnimation(fig,animate, interval=1000)
fig.show()
return fig, ani
Try it:
import sys
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QAction, QMessageBox
from mplwidget import MplWindow # +++
class window(QMainWindow):
def __init__(self):
super(window, self).__init__()
self.setGeometry(50, 50, 500, 300)
self.setWindowTitle('Temperature Control')
self.setWindowIcon(QIcon('adn.png'))
extractAction = QAction('&Quit', self)
extractAction.setShortcut('Ctrl+Q')
extractAction.setStatusTip('leave the app')
extractAction.triggered.connect(self.close_application)
self.statusBar()
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu('&File')
fileMenu.addAction(extractAction)
self.matplWindow = MplWindow() # +++
self.home()
def home(self):
btn = QPushButton('quit', self)
btn.clicked.connect(self.close_application)
btn.resize(btn.sizeHint())
btn.move(0, 100)
button = QPushButton('Temperature',self)
button.clicked.connect(self.opengraph)
button.move(50,200)
self.show()
def opengraph(self):
self.matplWindow.funAnimation() # +++
def close_application(self):
choice = QMessageBox.question(self, 'Message',
"Are you sure to quit?", QMessageBox.Yes |
QMessageBox.No, QMessageBox.No)
if choice == QMessageBox.Yes:
sys.exit()
else:
pass
if __name__ == "__main__":
app = QApplication(sys.argv)
Gui = window()
sys.exit(app.exec_())
mplwidget.py
import matplotlib.pyplot as plt
import numpy
import datetime
import matplotlib.animation as animation
from PyQt5.QtWidgets import QDialog, QApplication, QPushButton, QVBoxLayout
class MplWindow(QDialog):
Time = []
Temp = []
def __init__(self, parent=None):
super(MplWindow, self).__init__(parent)
def funAnimation(self):
self.fig = plt.figure()
self.ax1 = self.fig.add_subplot(1,1,1)
self.ani = animation.FuncAnimation(self.fig, self.animate, interval=1000)
plt.show()
def animate(self, i):
x = datetime.datetime.now()
y = numpy.random.randint(48,52)
self.Time.append(x)
self.Temp.append(int(y))
self.ax1.plot(self.Time, self.Temp)

PyQt4 using global variable from function in class

I understand that to use a global variable from a function, you Need to execute the function first:
def f():
global s
s = 'Hello'
f()
print(s)
But how do I use variable s globally in following example:
import sys
from PyQt4.QtGui import QApplication, QMainWindow, QPushButton, QLineEdit, QLabel, QComboBox, QProgressBar, QFileDialog
from PyQt4.QtCore import QSize, pyqtSlot
class App(QMainWindow):
def __init__(self):
super(App, self).__init__()
self.setGeometry(500, 300, 820, 350)
self.setWindowTitle("Widget")
self.initUI()
def initUI(self):
#Buttons
btnposx = 30
btnposy = 50
self.btn4 = QPushButton('GetValue', self)
self.btn4.move(btnposx,btnposy+220)
self.btn4.clicked.connect(self.cb_get)
self.cb = QComboBox(self)
self.cb.move(btnposx+120,btnposy+150)
self.cb.resize(80,22)
self.cb.setMaximumSize(QSize(80,1000000))
self.cb.addItem('A')
self.cb.addItem('B')
self.cb.addItem('C')
self.cb.addItem('D')
self.cb.addItem('E')
self.show()
#pyqtSlot()
def cb_get(self):
global s
cbtext = str(self.cb.currentText())
s = cbtext
print(s)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
This code shows a PyQt4 Widget. Function cb_get acquires the Value of a QcomboBox and can be used within the class App(). The Value is saved to variable s. How do I use variable s globally?
The only way I seem to get it to work is to write a new function for s and execute it on button click:
import sys
from PyQt4.QtGui import QApplication, QMainWindow, QPushButton, QLineEdit, QLabel, QComboBox, QProgressBar, QFileDialog
from PyQt4.QtCore import QSize, pyqtSlot
class App(QMainWindow):
def __init__(self):
super(App, self).__init__()
self.setGeometry(500, 300, 820, 350)
self.setWindowTitle("Widget")
self.initUI()
def initUI(self):
#Buttons
btnposx = 30
btnposy = 50
self.btn4 = QPushButton('GetValue', self)
self.btn4.move(btnposx,btnposy+220)
self.btn4.clicked.connect(self.cb_get)
self.btn4.clicked.connect(self.p)
self.cb = QComboBox(self)
self.cb.move(btnposx+120,btnposy+150)
self.cb.resize(80,22)
self.cb.setMaximumSize(QSize(80,1000000))
self.cb.addItem('A')
self.cb.addItem('B')
self.cb.addItem('C')
self.cb.addItem('D')
self.cb.addItem('E')
self.show()
#pyqtSlot()
def cb_get(self):
global s
s = str(self.cb.currentText())
def p(self):
print(s)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
Well, at least now it has ist own function and I can write code for it seperately.
def initUI(self):
#Buttons
btnposx = 30
btnposy = 50
self.btn4 = QPushButton('GetValue', self)
self.btn4.move(btnposx,btnposy+220)
self.btn4.clicked.connect(self.cb_get)
self.cb = QComboBox(self)
self.cb.move(btnposx+120,btnposy+150)
self.cb.resize(80,22)
self.cb.setMaximumSize(QSize(80,1000000))
self.cb.addItem('A')
self.cb.addItem('B')
self.cb.addItem('C')
self.cb.addItem('D')
self.cb.addItem('E')
self.s = None # initialize it here so you don't have to use global
self.show()
#pyqtSlot()
def cb_get(self):
cbtext = str(self.cb.currentText())
self.s = cbtext
def get_s(self):
return self.s
and
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
# print(ex.get_s) # this won't work since you have to click on btn4 first
sys.exit(app.exec_())

Categories