1
votes

In PyQt4 I have a main window which when the settings button is clicked opens the settings dialog

from PyQt4 import QtCore, QtGui
import ui_Design, ui_Settings_Design

class MainDialog(QtGui.QMainWindow, ui_Design.Ui_arbCrunchUI):
    def __init__(self, parent=None):
        super(MainDialog, self).__init__(parent)
        self.setupUi(self)
        self.settingsBtn.clicked.connect(lambda: self.showSettings())

    def showSettings(self):
        dialog = QtGui.QDialog()
        dialog.ui = SettingsDialog()
        dialog.ui.setupUi(dialog)
        dialog.exec_()

The above works and my SettingsDialog is displayed but I cant get the setPageIndex to work

class SettingsDialog(QtGui.QDialog, ui_Settings_Design.Ui_SettingsDialog):
    def __init__(self, parent=None):
        super(SettingsDialog, self).__init__(parent)
        self.setupUi(self)
        self.bookSettingsBtn.clicked.connect(self.setPageIndex)

   @QtCore.pyqtSlot()
   def setPageIndex(self):
       print 'selected'
       self.settingsStackedWidget.setCurrentIndex(0)

The bookSettingsBtn is a QToolButton

self.bookSettingsBtn = QtGui.QToolButton(self.navigationFrame)

And the settingsStackedWidget is a QStackedWidget

self.settingsStackedWidget = QtGui.QStackedWidget(SettingsDialog)

At this point I am pretty confused on signals and slots and nothing I have read clears this up - if anyone can point out what I am doing wrong above and also potentially direct me to a good (beginners) guide / tutorial on signals and slots it would be greatly appreciated

I would also like to know how to make setPageIndex work as follows:

def setPageIndex(self, selection):
     self.settingsStackedWidget.setCurrentIndex(selection)
4

4 Answers

1
votes

I'm not sure why you're doing the following, but that's the issue:

def showSettings(self):
    dialog = QtGui.QDialog()
    dialog.ui = SettingsDialog()
    dialog.ui.setupUi(dialog)
    dialog.exec_()

SettingsDialog itself is a proper QDialog. You don't need to instantiate another QDialog.

Right now, you're creating an empty QDialog and then populate it with the same ui as SettingsDialog (i.e. setupUi(dialog)), then you show this dialog. But... The signal connection is for SettingsDialog, and the dialog you're showing doesn't have that.

Basically, you don't need that extra QDialog at all. The following should be enough:

def showSettings(self):
    dialog = SettingsDialog()
    dialog.exec_()
0
votes

Ok. So here is an example how you pass an argument to a slot

from functools import partial

# here you have a button bookSettingsBtn:
self.bookSettingsBtn = QtGui.QPushButton("settings")
self.bookSettingsBtn.clicked.connect(partial(self.setPageIndex, self.bookSettingsBtn.text()))

@pyqtSlot(str) # this means the function expects 1 string parameter (str, str) 2 string parameters etc.
def setPageIndex(self, selection):
    print "you pressed button " + selection

In your case the argument would be an int. Of course you have to get the value from somewhere and then put it in the partial part as the argument (here I just used the text of the button), but you can use int, bool etc. Just watch the slot signature.

Here is a tutorial that helped me: http://zetcode.com/gui/pyqt4/

I hope this helps.

0
votes

Hey here I have a fully running example (just copy paste it in a python file and run it): Maybe this helps you. It's a small example but here you see how it works.

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from functools import partial

class MyForm(QMainWindow):
    def __init__(self, parent=None):
        super(MyForm, self).__init__(parent)
        button1 = QPushButton('Button 1')
        button2 = QPushButton('Button 2')
        button1.clicked.connect(partial(self.on_button, button1.text()))
        button2.clicked.connect(partial(self.on_button, button1.text()))

        layout = QHBoxLayout()
        layout.addWidget(button1)
        layout.addWidget(button2)

        main_frame = QWidget()
        main_frame.setLayout(layout)

        self.setCentralWidget(main_frame)

    @pyqtSlot(str)
    def on_button(self, n):
        print "Text of button is: " + str(n)

if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    form = MyForm()
    form.show()
    app.exec_()
0
votes

So I dont really understand why but changing the way the settingsDialog is called from the MainWindow has fixed my problem. I guess the parent window needed to be specified??:

class MainDialog(QtGui.QMainWindow, ui_Design.Ui_arbCrunchUI):
....
    def showSettings(self):
        self.settingsDialog = QtGui.QDialog(self)
        self.settingsDialog.ui = SettingsDialog(self)
        self.settingsDialog.ui.show()

class SettingsDialog(QtGui.QDialog, ui_Settings_Design.Ui_SettingsDialog):
    def __init__(self, parent=None):
        super(SettingsDialog, self).__init__(parent)
        self.setupUi(self)
        self.bookSettingsBtn.clicked.connect(partial(self.setPageIndex, 1))

    @QtCore.pyqtSlot(int)
    def setPageIndex(self, selection):
        self.settingsStackedWidget.setCurrentIndex(selection)