PyQt4 信号和槽 - QToolButton

Posted

技术标签:

【中文标题】PyQt4 信号和槽 - QToolButton【英文标题】:PyQt4 signals and slots - QToolButton 【发布时间】:2015-01-06 12:04:15 【问题描述】:

在 PyQt4 中,我有一个主窗口,单击设置按钮时会打开设置对话框

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_()

上述方法有效,我的 SettingsDialog 已显示,但我无法让 setPageIndex 正常工作

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)

bookSettingsBtn 是一个 QToolButton

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

而 settingsStackedWidget 是一个 QStackedWidget

self.settingsStackedWidget = QtGui.QStackedWidget(SettingsDialog)

在这一点上,我对信号和插槽感到非常困惑,我读过的任何内容都没有解决这个问题 - 如果有人能指出我在上面做错了什么,并且还可能指导我找到一个好的(初学者)指南/关于信号的教程和插槽将不胜感激

我也想知道如何使 setPageIndex 工作如下:

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

【问题讨论】:

【参考方案1】:

我不确定您为什么要执行以下操作,但这就是问题所在:

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

SettingsDialog 本身就是一个正确的QDialog。您不需要实例化另一个QDialog

现在,您正在创建一个空的QDialog,然后使用与SettingsDialog(即setupUi(dialog))相同的用户界面填充它,然后显示此对话框。但是...信号连接是针对SettingsDialog的,而您显示的对话框没有。

基本上,您根本不需要额外的QDialog。以下内容就足够了:

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

【讨论】:

【参考方案2】:

好的。所以这是一个如何将参数传递给插槽的示例

从 functools 导入部分

# 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

在您的情况下,参数将是一个 int。当然,您必须从某个地方获得价值 然后将它作为参数放在部分部分(这里我只是使用了按钮的文本), 但您可以使用 int、bool 等。只需注意插槽签名即可。

这是一个帮助我的教程: http://zetcode.com/gui/pyqt4/

我希望这会有所帮助。

【讨论】:

谢谢,但这在我的程序中不起作用。不调用 setPageIndex 方法。我更改了连接线以在末尾包含一个额外的括号,我假设这就是您的意思?: self.bookSettingsBtn.clicked.connect(partial(self.setPageIndex, self.bookSettingsBtn.text())) 是的,我已经编辑过了。我忘了最后一个括号。为什么不调用 setPageIndex?它应该像那样工作。尝试另一个不带任何参数的插槽并测试它是否可以查看失败的位置(例如定义 @pyqtSlot() def bla(self): print 'bla'。本教程很有帮助。 我已经阅读了该教程,但我想我在其他地方遇到了问题,因为正如您指出的那样,它应该像这样工作!使用 self.bookSettingsBtn.clicked.connect(self.printBlah())。 'blah' 会在 settingsDialog 初始化而不是单击按钮时立即打印,然后我收到以下错误:self.bookSettingsBtn.clicked.connect(self.printBlah()) TypeError: connect() slot argument should be a callable or a signal ,而不是“无类型”。如果我像在主对话框中那样添加 lambda,那么单击按钮时什么也不会发生??? 错字!: .... .connect(self.printBla) 【参考方案3】:

嘿,我有一个完全运行的示例(只需将其复制粘贴到 python 文件中并运行它): 也许这对你有帮助。这是一个小例子,但在这里你可以看到它是如何工作的。

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_()

【讨论】:

这很清楚也很有帮助,谢谢。虽然它对我的程序并没有真正的帮助 - 问题可能是我如何从另一个模块导入我的按钮并调用 self.btn?这是我能看到的唯一区别。我也不明白为什么使用 init 函数而不是单击 btn 时调用连接信号 - lambda 使用 MainWindow 中的 settingsBtn 解决了这个问题,但在设置窗口中没有这样做 成功了吗?如果是,我帮助您接受答案。问题是我无法运行您的代码,因为我没有 ui_settings 等模块。 不,它仍然不起作用。我认为信号没有通过,因为当我在插槽 'blah' 打印上包含 () 时,我得到一个错误。没有 () 在 btn 点击时不会发生任何事情 这是你的全部代码吗?因为我不能那样运行它(ui_settings等我没有) @lorgan 您可以在 pastebin 或 Dropbox 上分享您的代码。你不应该发布任何作为答案的东西,除非它是对这篇文章问题的回答。干杯。【参考方案4】:

所以我真的不明白为什么,但是更改从 MainWindow 调用 settingsDialog 的方式解决了我的问题。我猜需要指定父窗口??:

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)

【讨论】:

好的。所以问题不在于插槽。所以我回答了你问的问题(部分,请接受我的回答:D),但是为什么它不起作用我无法弄清楚,因为缺少重要的代码。

以上是关于PyQt4 信号和槽 - QToolButton的主要内容,如果未能解决你的问题,请参考以下文章

PyQt4信号和槽

PyQt4信号与槽

PyQt4关闭窗口

QT信号和槽

初见QT---信号和槽

Qt信号和槽的问题