Passing string from one window to another using Signal - python

I am trying pass a string from First window to Second window using signal. I want the string to be shown after pressing the push button on the Second window. However, I am getting the following error:"TypeError: decorated slot has no signature compatible with clicked(bool)"
I am using Qt-designer to create First and Second window.
Below is the main code:
class First(QDialog):
signal = pyqtSignal(str)
def __init__(self, parent = None):
super(First, self).__init__(parent)
self.ui = Ui_First()
self.ui.setupUi(self)
self.ui.pushButton.clicked.connect(self.Send)
self.show()
def Send(self):
UserInput = self.ui.lineEdit.text()
foo = Second()
self.signal.connect(foo.Receive)
self.signal.emit(str(UserInput))
self.ui = Second()
class Second(QDialog):
def __init__(self, parent = None):
super(Second, self).__init__(parent)
self.ui = Ui_Second()
self.ui.setupUi(self)
self.ui.pushButton.clicked.connect(self.Receive)
self.show()
#pyqtSlot(str)
def Receive(self, strA):
self.ui.label.setText(strA)
Here is the First.py:
class Ui_First(object):
def setupUi(self, First):
First.setObjectName("First")
First.resize(195, 134)
self.pushButton = QtWidgets.QPushButton(First)
self.pushButton.setGeometry(QtCore.QRect(40, 80, 111, 28))
self.pushButton.setObjectName("pushButton")
self.lineEdit = QtWidgets.QLineEdit(First)
self.lineEdit.setGeometry(QtCore.QRect(40, 40, 113, 22))
self.lineEdit.setObjectName("lineEdit")
self.retranslateUi(First)
QtCore.QMetaObject.connectSlotsByName(First)
def retranslateUi(self, First):
_translate = QtCore.QCoreApplication.translate
First.setWindowTitle(_translate("First", "First"))
self.pushButton.setText(_translate("First", "Send to Second"))
Here is the Second.py:
class Ui_Second(object):
def setupUi(self, Second):
Second.setObjectName("Second")
Second.resize(195, 134)
self.pushButton = QtWidgets.QPushButton(Second)
self.pushButton.setGeometry(QtCore.QRect(40, 80, 111, 28))
self.pushButton.setObjectName("pushButton")
self.label = QtWidgets.QLabel(Second)
self.label.setGeometry(QtCore.QRect(60, 40, 55, 16))
self.label.setObjectName("label")
self.retranslateUi(Second)
QtCore.QMetaObject.connectSlotsByName(Second)
def retranslateUi(self, Second):
_translate = QtCore.QCoreApplication.translate
Second.setWindowTitle(_translate("Second", "Second"))
self.pushButton.setText(_translate("Second", "Show Input"))
self.label.setText(_translate("Second", "TextLabel"))

Try it:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class Ui_First(object):
def setupUi(self, First):
First.setObjectName("First")
First.resize(195, 134)
self.pushButton = QtWidgets.QPushButton(First)
self.pushButton.setGeometry(QtCore.QRect(40, 80, 111, 28))
self.pushButton.setObjectName("pushButton")
self.lineEdit = QtWidgets.QLineEdit(First)
self.lineEdit.setGeometry(QtCore.QRect(40, 40, 113, 22))
self.lineEdit.setObjectName("lineEdit")
self.retranslateUi(First)
QtCore.QMetaObject.connectSlotsByName(First)
def retranslateUi(self, First):
_translate = QtCore.QCoreApplication.translate
First.setWindowTitle(_translate("First", "First"))
self.pushButton.setText(_translate("First", "Send to Second"))
class Ui_Second(object):
def setupUi(self, Second):
Second.setObjectName("Second")
Second.resize(195, 134)
self.pushButton = QtWidgets.QPushButton(Second)
self.pushButton.setGeometry(QtCore.QRect(40, 80, 111, 28))
self.pushButton.setObjectName("pushButton")
self.label = QtWidgets.QLabel(Second)
self.label.setGeometry(QtCore.QRect(60, 40, 55, 16))
self.label.setObjectName("label")
self.retranslateUi(Second)
QtCore.QMetaObject.connectSlotsByName(Second)
def retranslateUi(self, Second):
_translate = QtCore.QCoreApplication.translate
Second.setWindowTitle(_translate("Second", "Second"))
self.pushButton.setText(_translate("Second", "Show Input"))
self.label.setText(_translate("Second", "TextLabel"))
class First(QDialog):
signal = pyqtSignal(str)
def __init__(self, parent = None):
super(First, self).__init__(parent)
self.ui = Ui_First()
self.ui.setupUi(self)
self.ui.lineEdit.setFocus() # +
self.ui.pushButton.clicked.connect(self.Send)
self.show()
def Send(self):
UserInput = self.ui.lineEdit.text()
foo = Second(self) # + self.
self.signal.emit(str(UserInput))
# self.signal.connect(foo.Receive)
# self.ui = Second()
class Second(QDialog):
def __init__(self, parent = None):
super(Second, self).__init__(parent)
self.ui = Ui_Second()
self.ui.setupUi(self)
self.ui.pushButton.clicked.connect(self.close) # - (self.Receive)
parent.signal.connect(self.Receive) # +++
self.show()
#pyqtSlot(str)
def Receive(self, strA):
self.ui.label.setText(strA)
self.ui.label.adjustSize() # +
if __name__ == '__main__':
app = QApplication(sys.argv)
gui = First()
gui.show()
sys.exit(app.exec_())

Related

PYQT5: Is it possible in python to send back a value from a QDialog without closing it?

Is it possible for a QDialog to send a value back to the application without also closing the dialog window? A common example would be the insert symbol dialog in Microsoft Word. (In fact, this is what I am trying to replicate.)
I have included some basic code for a main window with a label and a button. Pushing the button opens the dialog window. The dialog window contains a textLineEdit widget, an OK button, and a Cancel button. After pushing OK any text entered into the dialog's textLineEdit is set as the text in the main window's label. Would it be possible to return the entered text without closing the dialog? I know it would require some on_OK_clicked procedure in the Dialog class, but I cannot seem to return a value without also closing the dialog. Any ideas would be greatly appreciated.
import sys
from PyQt5 import QtCore, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(320, 86)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setObjectName("label")
self.verticalLayout.addWidget(self.label)
spacerItem = QtWidgets.QSpacerItem(20, 13, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setObjectName("pushButton")
self.verticalLayout.addWidget(self.pushButton)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "TextLabel"))
self.pushButton.setText(_translate("MainWindow", "Open Dialog"))
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(400, 94)
self.lineEdit = QtWidgets.QLineEdit(Dialog)
self.lineEdit.setGeometry(QtCore.QRect(20, 20, 361, 22))
self.lineEdit.setObjectName("lineEdit")
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
self.buttonBox.setGeometry(QtCore.QRect(40, 50, 341, 32))
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.retranslateUi(Dialog)
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
class Dialog(QtWidgets.QDialog, Ui_Dialog):
def __init__(self, parent=None):
QtWidgets.QDialog.__init__(self, parent)
self.setupUi(self)
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.pushButton.clicked.connect(self.onClicked)
def onClicked(self):
dlg = Dialog()
if dlg.exec_():
self.label.setText(dlg.lineEdit.text())
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Thanks to ekhumoro for the help I needed. The solution was to use an Apply button in the QDialogButtonBox and to connect the click action to a slot in the main window. In this case, I found I had to use a lambda function as the slot. (This is the last piece I was missing.) dlg.buttonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(lambda: self.label.setText(dlg.lineEdit.text()))
Here is the full working code.
import sys
from PyQt5 import QtCore, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(320, 86)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setObjectName("label")
self.verticalLayout.addWidget(self.label)
spacerItem = QtWidgets.QSpacerItem(20, 13, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setObjectName("pushButton")
self.verticalLayout.addWidget(self.pushButton)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "TextLabel"))
self.pushButton.setText(_translate("MainWindow", "Open Dialog"))
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(400, 94)
self.lineEdit = QtWidgets.QLineEdit(Dialog)
self.lineEdit.setGeometry(QtCore.QRect(20, 20, 361, 22))
self.lineEdit.setObjectName("lineEdit")
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
self.buttonBox.setGeometry(QtCore.QRect(40, 50, 341, 32))
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Close|QtWidgets.QDialogButtonBox.Apply)
self.buttonBox.button(QtWidgets.QDialogButtonBox.Apply).setText("Insert")
self.buttonBox.setObjectName("buttonBox")
self.retranslateUi(Dialog)
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
class Dialog(QtWidgets.QDialog, Ui_Dialog):
def __init__(self, parent=None):
QtWidgets.QDialog.__init__(self, parent)
self.setupUi(self)
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.pushButton.clicked.connect(self.onClicked)
def onClicked(self):
dlg = Dialog()
dlg.buttonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(lambda: self.label.setText(dlg.lineEdit.text()))
dlg.exec()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

How to stop a thread using a button

We are creating an object detection project using Object detection API. We are train the program making pyqt5 GUI application. Trying to run the training part using thread. We want to stop the running thread using a push button. Here the code sample
class stopClass(QtCore.QThread):
def __init__(self, parent=None):
super(stopClass, self).__init__(parent)
def startTrain(self):
#changing directory
os.chdir(r"c://tensorflow_1//models//research//object_detection")
args3 = shlex.split('python train.py --logtostderr --train_dir=training/ --
pipeline_config_path=training/faster_rcnn_inception_v2_pets.config')
subprocess.run(args3, shell = True)
return
def run(self):
self.startTrain()
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(701, 495)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.Annotation = QtWidgets.QPushButton(self.centralwidget)
self.Annotation.setGeometry(QtCore.QRect(480, 10, 181, 41))
self.Annotation.setToolTip("")
self.Annotation.setObjectName("Annotation")
self.Start_train = QtWidgets.QPushButton(self.centralwidget)
self.Start_train.setGeometry(QtCore.QRect(480, 110, 181, 41))
self.Start_train.setObjectName("Start_train")
self.Stop_train = QtWidgets.QPushButton(self.centralwidget)
self.Stop_train.setEnabled(False)
self.Stop_train.setGeometry(QtCore.QRect(480, 160, 181, 41))
self.Stop_train.setObjectName("Stop_train")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 701, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.Start_train.clicked.connect(self.starting)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.Start_train.setText(_translate("MainWindow", "start train"))
self.Stop_train.setText(_translate("MainWindow", "stop train"))
def starting(self):
self.stopThread = stopClass()
self.stopThread.start()
self.Stop_train.setEnabled(True)
self.Stop_train.clicked.connect(self.stopThread.exit)
self.Start_train.setEnabled(False)
In this case I do not see the need to use threads since it is enough to use QProcess that allows a simple handling of the execution of the script. On the other hand, do not modify the script generated by pyuic so my solution assumes that you must recreate that script that must be called gui.py:
import shlex
import sys
from PyQt5.QtCore import QObject, QProcess
from PyQt5.QtWidgets import QApplication, QMainWindow
from gui import Ui_MainWindow
class Manager(QObject):
def __init__(self, parent=None):
super().__init__(parent)
self._process = QProcess()
working_directory = r"c://tensorflow_1//models//research//object_detection"
self.process.setWorkingDirectory(working_directory)
self.process.setProgram(sys.executable)
args = shlex.split(
"train.py --logtostderr --train_dir=training/ --pipeline_config_path=training/faster_rcnn_inception_v2_pets.config"
)
self.process.setArguments(args)
#property
def process(self):
return self._process
def start(self):
if self.process.state() == QProcess.NotRunning:
self.process.start()
def stop(self):
if self.process.state() != QProcess.NotRunning:
self.process.kill()
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.manager = Manager()
self.Start_train.clicked.connect(self.manager.start)
self.Stop_train.clicked.connect(self.manager.stop)
self.manager.process.stateChanged.connect(self._handle_stateChanged)
def _handle_stateChanged(self, state):
self.Start_train.setEnabled(state != QProcess.Running)
self.Stop_train.setEnabled(state == QProcess.Running)
def main():
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()

how to detect a key release in pyqt

I want to create a PyQt5 window (Windows OS) which recognizes a button click with holding CTRL button. I successfully created a handler which recognizes CTRL key press but it couldn't find the pressing and releasing of a button which i need to call and dismiss button click event. I did a lot of search but the resources for PyQt5 seems pretty low. Any help is appreciated :)
import time
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.setupUi(self)
self.show()
self.signals()
self.bleahOK=True
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(392, 255)
self.unlockButton = QtWidgets.QPushButton(Dialog)
self.unlockButton.setGeometry(QtCore.QRect(10, 180, 171, 51))
self.unlockButton.setObjectName("unlockButton")
self.lockButton = QtWidgets.QPushButton(Dialog)
self.lockButton.setGeometry(QtCore.QRect(220, 180, 151, 51))
self.lockButton.setObjectName("lockButton")
self.label = QtWidgets.QLabel(Dialog)
self.label.setGeometry(QtCore.QRect(30, 30, 331, 71))
font = QtGui.QFont()
font.setPointSize(12)
self.label.setFont(font)
self.label.setObjectName("label")
self.lineEdit = QtWidgets.QLineEdit(Dialog)
self.lineEdit.setGeometry(QtCore.QRect(30, 120, 261, 31))
font = QtGui.QFont()
font.setPointSize(18)
self.lineEdit.setFont(font)
self.lineEdit.setObjectName("lineEdit")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.unlockButton.setText(_translate("Dialog", "OK"))
self.lockButton.setText(_translate("Dialog", "Lock"))
self.label.setText(_translate("Dialog", ""))
self.lineEdit.setText(_translate("Dialog", ""))
def signals(self):
self.unlockButton.clicked.connect(self.unlock)
def unlock(self):
if 1: print('ff')
def keyPressEvent(self, event):
if type(event) == QtGui.QKeyEvent: #Unable to find when the key was released
print (event.key())
event.accept()
else:
event.ignore()
def lock(self):
print("Test")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
# ui.signals()
# Dialog.show()
sys.exit(app.exec_())
I recommend you not to modify the code generated by Qt Designer, instead create a class that inherits the appropriate widget and use that class as an interface as I recommend PyQt. Going to the problem, you have to use the keyReleaseEvent method to listen when a key is released:
import time
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(392, 255)
self.unlockButton = QtWidgets.QPushButton(Dialog)
self.unlockButton.setGeometry(QtCore.QRect(10, 180, 171, 51))
self.unlockButton.setObjectName("unlockButton")
self.lockButton = QtWidgets.QPushButton(Dialog)
self.lockButton.setGeometry(QtCore.QRect(220, 180, 151, 51))
self.lockButton.setObjectName("lockButton")
self.label = QtWidgets.QLabel(Dialog)
self.label.setGeometry(QtCore.QRect(30, 30, 331, 71))
font = QtGui.QFont()
font.setPointSize(12)
self.label.setFont(font)
self.label.setObjectName("label")
self.lineEdit = QtWidgets.QLineEdit(Dialog)
self.lineEdit.setGeometry(QtCore.QRect(30, 120, 261, 31))
font = QtGui.QFont()
font.setPointSize(18)
self.lineEdit.setFont(font)
self.lineEdit.setObjectName("lineEdit")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.unlockButton.setText(_translate("Dialog", "OK"))
self.lockButton.setText(_translate("Dialog", "Lock"))
self.label.setText(_translate("Dialog", ""))
self.lineEdit.setText(_translate("Dialog", ""))
class Dialog(QtWidgets.QDialog, Ui_Dialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent)
self.setupUi(self)
self.is_key_ctrl_pressed = False
self.unlockButton.clicked.connect(self.unlock)
#QtCore.pyqtSlot()
def unlock(self):
if self.is_key_ctrl_pressed:
print("unlock")
def keyPressEvent(self, event):
if event.key() == QtCore.Qt.Key_Control:
self.is_key_ctrl_pressed = True
super(Dialog, self).keyPressEvent(event)
def keyReleaseEvent(self, event):
if event.key() == QtCore.Qt.Key_Control:
self.is_key_ctrl_pressed = False
super(Dialog, self).keyReleaseEvent(event)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Dialog()
w.show()
sys.exit(app.exec_())

PyQt5 Custom widget does not appear in GridLayout [duplicate]

This question already has answers here:
Simple python inheritance
(3 answers)
QtDesigner changes will be lost after redesign User Interface
(2 answers)
Closed 4 years ago.
I am trying to add a custom widget to a layout. I can successfully add many PushButtons to my GridLayout, but when I attempt to add the custom widget it does not show.
I have attempted to provide a minimal example:
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
class moduleForm(QtWidgets.QWidget):
def __init__(self, parent = None):
self.parent = parent
self.setObjectName("moduleForm")
self.resize(300, 400)
self.fModule = QtWidgets.QPushButton("Test")
self.fModule.setGeometry(QtCore.QRect(0, 0, 80, 20))
self.retranslateUi(self.parent)
QtCore.QMetaObject.connectSlotsByName(self)
def retranslateUi(self, moduleForm):
_translate = QtCore.QCoreApplication.translate
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("Rb Controller")
MainWindow.resize(900, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.loMainTab = QtWidgets.QHBoxLayout(self.centralwidget)
self.centralwidget.setLayout(self.loMainTab)
self.saChannels = QtWidgets.QScrollArea(self.centralwidget)
self.saChannels.setWidgetResizable(True)
self.saChannels.setGeometry(QtCore.QRect(10,10,10,10))
self.fButtons = QtWidgets.QFrame(self.centralwidget)
self.fButtons.setFrameShadow(QtWidgets.QFrame.Sunken)
self.pbAddModule = QtWidgets.QPushButton(self.fButtons)
self.pbAddModule.setGeometry(QtCore.QRect(10, 10, 80, 20))
self.pbAddModule.setObjectName("pbAddModule")
self.loButtons = QtWidgets.QHBoxLayout(self.fButtons)
self.loButtons.addWidget(self.pbAddModule)
self.loButtons.addStretch()
self.fButtons.setLayout(self.loButtons)
self.hlwChannelsContents = QtWidgets.QWidget()
self.hlwChannelsContents.setObjectName("hlwChannelsContents")
self.hloChannelsContents = QtWidgets.QHBoxLayout(self.hlwChannelsContents)
self.hloChannelsContents.setObjectName("hloChannelsContents")
self.gloChannelsContents = QtWidgets.QGridLayout()
self.hloChannelsContents.addLayout(self.gloChannelsContents)
self.saChannels.setWidget(self.hlwChannelsContents)
self.loMainTab.addWidget(self.fButtons)
self.loMainTab.addWidget(self.saChannels,1)
for ii in range(10):
for jj in range(10):
self.r_button = QtWidgets.QPushButton("Element %s,%s " % (ii, jj))
self.gloChannelsContents.addWidget(self.r_button,ii,jj)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
self.pbAddModule.clicked.connect(self.createModule)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Rb Controller"))
self.pbAddModule.setText(_translate("MainWindow", "Add Module"))
def createModule(self):
createModule = moduleForm()
self.gloChannelsContents.addWidget(createModule)
createModule.show()
class ApplicationWindow(QtWidgets.QMainWindow):
def __init__(self):
super(ApplicationWindow, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
def main():
app = QtWidgets.QApplication(sys.argv)
application = ApplicationWindow()
application.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
I have added the super().__init__ function but it is still not working. The PushButton in my custom widget gets displayed if I add it not the custom widget, so all the other code is fine.
If I have:
self.gloChannelsContents.addWidget(createModule.fModule,self.i,self.j)
in createModule then I get a dynamic PushButton, however, if I try to use the custom widget
self.gloChannelsContents.addWidget(createModule,self.i,self.j)
nothing appears.
Try it:
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
class moduleForm(QtWidgets.QWidget):
def __init__(self, row, parent = None): # + row
super().__init__()
self.parent = parent
self.setObjectName("moduleForm")
self.resize(300, 400)
self.fModule = QtWidgets.QPushButton("Test {}".format(row)) # + row
self.fModule.setGeometry(QtCore.QRect(0, 0, 80, 20))
self.retranslateUi(self.parent)
QtCore.QMetaObject.connectSlotsByName(self)
def retranslateUi(self, moduleForm):
_translate = QtCore.QCoreApplication.translate
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.i = 11 # + self.i
MainWindow.setObjectName("Rb Controller")
MainWindow.resize(900, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.loMainTab = QtWidgets.QHBoxLayout(self.centralwidget)
self.centralwidget.setLayout(self.loMainTab)
self.saChannels = QtWidgets.QScrollArea(self.centralwidget)
self.saChannels.setWidgetResizable(True)
self.saChannels.setGeometry(QtCore.QRect(10,10,10,10))
self.fButtons = QtWidgets.QFrame(self.centralwidget)
self.fButtons.setFrameShadow(QtWidgets.QFrame.Sunken)
self.pbAddModule = QtWidgets.QPushButton(self.fButtons)
self.pbAddModule.setGeometry(QtCore.QRect(10, 10, 80, 20))
self.pbAddModule.setObjectName("pbAddModule")
self.loButtons = QtWidgets.QHBoxLayout(self.fButtons)
self.loButtons.addWidget(self.pbAddModule)
self.loButtons.addStretch()
self.fButtons.setLayout(self.loButtons)
self.hlwChannelsContents = QtWidgets.QWidget()
self.hlwChannelsContents.setObjectName("hlwChannelsContents")
self.hloChannelsContents = QtWidgets.QHBoxLayout(self.hlwChannelsContents)
self.hloChannelsContents.setObjectName("hloChannelsContents")
self.gloChannelsContents = QtWidgets.QGridLayout()
self.hloChannelsContents.addLayout(self.gloChannelsContents)
self.saChannels.setWidget(self.hlwChannelsContents)
self.loMainTab.addWidget(self.fButtons)
self.loMainTab.addWidget(self.saChannels,1)
for ii in range(10):
for jj in range(10):
self.r_button = QtWidgets.QPushButton("Element %s,%s " % (ii, jj))
self.gloChannelsContents.addWidget(self.r_button, ii, jj)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
self.pbAddModule.clicked.connect(self.createModule)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Rb Controller"))
self.pbAddModule.setText(_translate("MainWindow", "Add Module"))
def createModule(self):
self.createModule = moduleForm(self.i) # +
self.gloChannelsContents.addWidget(self.createModule.fModule, self.i, 0) # +
self.i += 1 # +
# self.createModule.show() # ???
class ApplicationWindow(QtWidgets.QMainWindow):
def __init__(self):
super(ApplicationWindow, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
def main():
app = QtWidgets.QApplication(sys.argv)
application = ApplicationWindow()
application.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()

How to switch between two windows in python using PyQt

I am working on some app. I wanted to create a toolbar that after having been clicked will open Settings window. However I don't know how to do it exactly. The way it is now is that i have a Toolbar icon connected to ShowSettings function. This function creates a new instance of settings each time I click on the icon ( i know it shouldn't create new instances each time but only one in the beginning and then work on it. I don't know how to do it though) and then show the settings window associated with this instance. However in this way the settings window only flashes for a second and then disappears. I don't know what's wrong hope you can help me out :)
import sys
import time
from PyQt4 import QtCore, QtGui
from ui import Ui_MainWindow
from ui import Ui_SettingsWindow
#Aplikacja obslugujaca bramki LF
#zamiana pliku .ui na kod pythona
#pyuic4 untitled.ui -o output.py
class timerThread(QtCore.QThread):
timeElapsed = QtCore.pyqtSignal(float)
def __init__(self, parent=None):
super(timerThread, self).__init__(parent)
self.timeStart = None
def start(self, timeStart):
self.timeStart = timeStart
return super(timerThread, self).start()
def run(self):
while self.parent().isRunning():
self.timeElapsed.emit(time.time() - self.timeStart)
time.sleep(0.1)
class myThread(QtCore.QThread):
timeElapsed = QtCore.pyqtSignal(float)
def __init__(self, parent=None):
super(myThread, self).__init__(parent)
self.timerThread = timerThread(self)
self.timerThread.timeElapsed.connect(self.timeElapsed.emit)
def run(self):
self.timerThread.start(time.time())
iterations = 10000000000
while iterations:
print "Running {0}".format(self.__class__.__name__)
iterations -= 1
time.sleep(10)
class SettingsWindow(QtGui.QMainWindow):
#Constructor:
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui_settigns = Ui_SettingsWindow()
self.ui_settigns.setupUi(self)
class MainWindow(QtGui.QMainWindow):
#Constructor:
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.myThread = myThread(self)
self.myThread.timeElapsed.connect(self.on_myThread_timeElapsed)
self.myThread.finished.connect(self.on_myThread_finished)
#Nie wiem jak przerzucic to do pliku UI bez errorow
#Toolbar
settingsAction = QtGui.QAction(QtGui.QIcon('tools.jpg'), 'Ustawienia', self)
settingsAction.setShortcut('Ctrl+U')
settingsAction.triggered.connect(self.ShowSettings)
self.toolbar = self.addToolBar('Settings')
self.toolbar.addAction(settingsAction)
def UpdateList(self):
contest_name = self.ui.comboBox.currentText()
#jakis try-catch tutaj sie przyda gdyby nie plik nie istnial
#zczytuje z pliku liste robotow
with open('database\%s.txt' % contest_name) as f:
robots_list = f.read().splitlines()
self.ui.listWidget.clear()
self.ui.listWidget.addItems(robots_list)
def Search(self):
text = self.ui.lineEdit.text()
self.ui.lineEdit.clear()
item = self.ui.listWidget.findItems(text, QtCore.Qt.MatchExactly)
#jakiegos try-catcha trzeba tutaj walnac
self.ui.listWidget.setItemSelected(item[0], True)
def ShowSettings(self):
settings = SettingsWindow() #creates settings instance
settings.show()
#QtCore.pyqtSlot()
def on_button_clicked(self):
self.myThread.start()
#QtCore.pyqtSlot(int)
def on_myThread_timeElapsed(self, seconds):
self.ui.lcdNumber.display(seconds)
#QtCore.pyqtSlot()
def on_myThread_finished(self):
self.myThread.terminate()
print "Done"
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MainWindow()
settings = SettingsWindow()
myapp.show()
settings.show()
sys.exit(app.exec_())
And Here is the UI file
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'untitled.ui'
#
# Created: Fri Apr 24 08:04:20 2015
# by: PyQt4 UI code generator 4.11.3
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_SettingsWindow(object):
def setupUi(self, SettingsWindow):
SettingsWindow.setObjectName(_fromUtf8("Ustawienia"))
SettingsWindow.resize(686, 556)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(686, 556)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.groupBox = QtGui.QGroupBox(self.centralwidget)
self.groupBox.setGeometry(QtCore.QRect(10, 10, 341, 491))
self.groupBox.setObjectName(_fromUtf8("groupBox"))
self.pushButton = QtGui.QPushButton(self.groupBox)
self.pushButton.setGeometry(QtCore.QRect(10, 460, 231, 23))
self.pushButton.setObjectName(_fromUtf8("pushButton"))
self.label = QtGui.QLabel(self.groupBox)
self.label.setGeometry(QtCore.QRect(10, 80, 90, 16))
self.label.setObjectName(_fromUtf8("label"))
self.lineEdit = QtGui.QLineEdit(self.groupBox)
self.lineEdit.setGeometry(QtCore.QRect(130, 77, 191, 20))
self.lineEdit.setObjectName(_fromUtf8("lineEdit"))
self.listWidget = QtGui.QListWidget(self.groupBox)
self.listWidget.setGeometry(QtCore.QRect(10, 110, 321, 341))
self.listWidget.setObjectName(_fromUtf8("listWidget"))
item = QtGui.QListWidgetItem()
self.listWidget.addItem(item)
item = QtGui.QListWidgetItem()
self.listWidget.addItem(item)
item = QtGui.QListWidgetItem()
self.listWidget.addItem(item)
self.label_2 = QtGui.QLabel(self.groupBox)
self.label_2.setGeometry(QtCore.QRect(10, 50, 111, 16))
self.label_2.setObjectName(_fromUtf8("label_2"))
self.comboBox = QtGui.QComboBox(self.groupBox)
self.comboBox.setGeometry(QtCore.QRect(130, 50, 191, 22))
self.comboBox.setObjectName(_fromUtf8("comboBox"))
self.comboBox.addItem(_fromUtf8(""))
self.comboBox.addItem(_fromUtf8(""))
self.comboBox.addItem(_fromUtf8(""))
self.comboBox.addItem(_fromUtf8(""))
self.groupBox_2 = QtGui.QGroupBox(self.centralwidget)
self.groupBox_2.setGeometry(QtCore.QRect(360, 10, 311, 491))
self.groupBox_2.setObjectName(_fromUtf8("groupBox_2"))
self.lcdNumber = QtGui.QLCDNumber(self.groupBox_2)
self.lcdNumber.setGeometry(QtCore.QRect(10, 20, 281, 151))
self.lcdNumber.setSmallDecimalPoint(True)
self.lcdNumber.setObjectName(_fromUtf8("lcdNumber"))
self.pushButton_2 = QtGui.QPushButton(self.groupBox_2)
self.pushButton_2.setGeometry(QtCore.QRect(20, 340, 75, 23))
self.pushButton_2.setObjectName(_fromUtf8("pushButton_2"))
self.pushButton_3 = QtGui.QPushButton(self.groupBox_2)
self.pushButton_3.setGeometry(QtCore.QRect(200, 340, 75, 23))
self.pushButton_3.setObjectName(_fromUtf8("pushButton_3"))
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL(_fromUtf8("clicked()")), self.lineEdit.clear)
QtCore.QObject.connect(self.lineEdit, QtCore.SIGNAL("returnPressed()"), MainWindow.Search) #connected to Search method in class MainWindow
QtCore.QObject.connect(self.comboBox, QtCore.SIGNAL(_fromUtf8("currentIndexChanged(QString)")), MainWindow.UpdateList)
QtCore.QObject.connect(self.pushButton_2, QtCore.SIGNAL(_fromUtf8("clicked()")), MainWindow.on_button_clicked)
QtCore.QObject.connect(self.pushButton_3, QtCore.SIGNAL(_fromUtf8("clicked()")), MainWindow.on_myThread_finished)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "LF Timer", None))
self.groupBox.setTitle(_translate("MainWindow", "Wybierz robota", None))
self.pushButton.setText(_translate("MainWindow", "Uruchom AplikacjÄ™ Pomiaru Czasu", None))
self.label.setText(_translate("MainWindow", "Wyszukaj robota:", None))
self.lineEdit.setText(_translate("MainWindow", "cos tam", None))
__sortingEnabled = self.listWidget.isSortingEnabled()
self.listWidget.setSortingEnabled(False)
item = self.listWidget.item(0)
item.setText(_translate("MainWindow", "Robot 1", None))
item = self.listWidget.item(1)
item.setText(_translate("MainWindow", "Robot 2", None))
item = self.listWidget.item(2)
item.setText(_translate("MainWindow", "Robot 3", None))
self.listWidget.setSortingEnabled(__sortingEnabled)
self.label_2.setText(_translate("MainWindow", "Wybierz Konkurencje:", None))
self.comboBox.setItemText(0, _translate("MainWindow", "", None))
self.comboBox.setItemText(1, _translate("MainWindow", "LF", None))
self.comboBox.setItemText(2, _translate("MainWindow", "TURBO LF", None))
self.comboBox.setItemText(3, _translate("MainWindow", "LEGO LF", None))
self.groupBox_2.setTitle(_translate("MainWindow", "Pomiar Czasu", None))
self.pushButton_2.setText(_translate("MainWindow", "Start", None))
self.pushButton_3.setText(_translate("MainWindow", "Stop", None))
The instance of the settings window is local to the MainWindow.ShowSettings method. As such, it is quickly garbage collected because nothing keeps a reference to the window.
You can fix this in two ways. The first is to specify a parent of the settings window when it is instantiated. The second is to store it as an instance attribute of MainWindow (eg self.settings = ...).
Thank you three_pineapples for your help. I used the second way that you have described. It works like a dream :) Here's the code if anyone needs it.
import sys
import time
from PyQt4 import QtCore, QtGui
from ui import Ui_MainWindow
from ui import Ui_SettingsWindow
#Aplikacja obslugujaca bramki LF
#zamiana pliku .ui na kod pythona
#pyuic4 untitled.ui -o output.py
#py to exe
#python setup.py py2exe --includes sip
class timerThread(QtCore.QThread):
timeElapsed = QtCore.pyqtSignal(float)
def __init__(self, parent=None):
super(timerThread, self).__init__(parent)
self.timeStart = None
def start(self, timeStart):
self.timeStart = timeStart
return super(timerThread, self).start()
def run(self):
while self.parent().isRunning():
self.timeElapsed.emit(time.time() - self.timeStart)
time.sleep(0.1)
class myThread(QtCore.QThread):
timeElapsed = QtCore.pyqtSignal(float)
def __init__(self, parent=None):
super(myThread, self).__init__(parent)
self.timerThread = timerThread(self)
self.timerThread.timeElapsed.connect(self.timeElapsed.emit)
def run(self):
self.timerThread.start(time.time())
iterations = 10000000000
while iterations:
print "Running {0}".format(self.__class__.__name__)
iterations -= 1
time.sleep(10)
class SettingsWindow(QtGui.QMainWindow):
#Constructor:
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui_settigns = Ui_SettingsWindow()
self.ui_settigns.setupUi(self)
class MainWindow(QtGui.QMainWindow):
#Constructor:
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.settings = SettingsWindow()# Creates and stores SettingsWindow instance, MainWindow manages SettingsWindow
self.myThread = myThread(self)
self.myThread.timeElapsed.connect(self.on_myThread_timeElapsed)
self.myThread.finished.connect(self.on_myThread_finished)
#Nie wiem jak przerzucic to do pliku UI bez errorow
#Toolbar
settingsAction = QtGui.QAction(QtGui.QIcon('tools.jpg'), 'Ustawienia', self)
settingsAction.setShortcut('Ctrl+U')
settingsAction.triggered.connect(self.ShowSettings)
self.toolbar = self.addToolBar('Settings')
self.toolbar.addAction(settingsAction)
def UpdateList(self):
contest_name = self.ui.comboBox.currentText()
#jakis try-catch tutaj sie przyda gdyby nie plik nie istnial
#zczytuje z pliku liste robotow
with open('database\%s.txt' % contest_name) as f:
robots_list = f.read().splitlines()
self.ui.listWidget.clear()
self.ui.listWidget.addItems(robots_list)
def Search(self):
text = self.ui.lineEdit.text()
self.ui.lineEdit.clear()
item = self.ui.listWidget.findItems(text, QtCore.Qt.MatchExactly)
#jakiegos try-catcha trzeba tutaj walnac
self.ui.listWidget.setItemSelected(item[0], True)
def ShowSettings(self):
self.settings.show()
#QtCore.pyqtSlot()
def on_button_clicked(self):
self.myThread.start()
#QtCore.pyqtSlot(int)
def on_myThread_timeElapsed(self, seconds):
self.ui.lcdNumber.display(seconds)
#QtCore.pyqtSlot()
def on_myThread_finished(self):
self.myThread.terminate()
print "Done"
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MainWindow()
myapp.show()
sys.exit(app.exec_())

Categories

Resources