【问题标题】:Why does this PyQt5 Qlistwidget signal + slot not working?为什么这个 PyQt5 Qlistwidget 信号 + 插槽不起作用?
【发布时间】:2021-05-12 10:12:26
【问题描述】:

我一直在努力完成这项工作,但它只是没有。我没有错误,只是明显的不合规。它只是不想添加 QListWidget 项,或更改 QLabel。

我创建了一个 MainWindowClass。它是主要的小部件,我有一个布局和一个按钮。在它的码头小部件中,我有一个 QListWidget。 我从按钮发出一个信号并将其连接到dockwidget列表中的一个插槽。 连接就在那里。当我按下按钮时,dockwidgetcontents 类中的方法正在运行。 但它不会将项目添加到列表小部件。并且不会产生任何错误。

代码如下:

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys

class AppClass:

    def __init__(self):
        super().__init__()
        app = QApplication(sys.argv)
        window = MainWindowClass()
        window.show()
        sys.exit(app.exec_())


class MainWindowClass(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_UI()
        self.TheDockWidget()

    def init_UI(self):
        self.setGeometry(100, 100, 400, 200)
        self.setWindowTitle("Test App")
        self.setCentralWidget(MainWidgetClass())

    def TheDockWidget(self):
        self.dockWidget = QDockWidget('Status:')
        self.dockWidget.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable)
        self.addDockWidget(Qt.RightDockWidgetArea, self.dockWidget)
        self.dockWidget.setSizePolicy(QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum))
        self.dockWidget.setWidget(DockWidgetContents())


class DockWidgetContents(QWidget):

    def __init__(self):
        super().__init__()
        self.init_UI()

    def init_UI(self):
        layout = QVBoxLayout()
        self.setLayout(layout)
        self.button3 = QPushButton()
        self.button3.setText("button3")
        layout.addWidget(self.button3)
        self.listwidget = QListWidget()
        layout.addWidget(self.listwidget)
        self.listwidget.addItem("Ready.")
        self.label = QLabel("initial")
        layout.addWidget(self.label)

    @pyqtSlot(str, str, int)
    def _add_item(self, strA, strB, int1):
        self.label.setText("yes")           # why does this not work??
        self.listwidget.addItem(strA)       # why does this not work??
        self.listwidget.addItem(strB)       # why does this not work??
        self.listwidget.addItem(str(int1))  # why does this not work??
        print(strA, strB, int1)             # but this works fine.


class MainWidgetClass(QWidget):

    def __init__(self):
        super().__init__()
        self.init_UI()

    def init_UI(self):
        mainLayout = QGridLayout()
        self.setLayout(mainLayout)
        mainLayout.addWidget(TopLeftWidgetClass(), 0, 0)


class TopLeftWidgetClass(QWidget):
    signal = pyqtSignal(str, str, int)

    def __init__(self):
        super().__init__()
        self.init_UI()

    def init_UI(self):
        layout = QHBoxLayout()
        self.setLayout(layout)
        self.button1 = QPushButton("button1")
        layout.addWidget(self.button1)
        self.button1.clicked.connect(self.start)

    def start(self):
        otherClass = DockWidgetContents()
        self.signal.connect(otherClass._add_item)
        self.signal.emit("one", "two", 3)


if __name__ == '__main__':
    AppClass()

当我在表格中输入我的问题时,我还阅读了所有建议的问题,但我一定没有理解对此至关重要的或先决条件。

虽然我发现您对其他问题的所有答案都非常有价值,但如果答案能指出我缺少的参考资料,我将不胜感激,这样我就可以理解问题,而不仅仅是复制/粘贴固定代码.

【问题讨论】:

    标签: python pyqt5 signals slots


    【解决方案1】:

    主要问题是您正尝试连接到DockWidgetContents新实例,该实例也会在start() 返回后立即被删除。

    这个新实例显然没用,因为一个已经存在,但是您没有直接的方法来获取它,因为当您将小部件添加到布局和父级时,您会“即时”创建所有类。
    请记住,虽然创建“动态实例”在技术上不是问题,但它不允许您保留对这些实例的引用。

    您必须创建对小部件的适当引用并正确连接它们。

    在这里您可以看到所需的修改:

    class MainWindowClass(QMainWindow):
        def __init__(self):
            super().__init__()
            self.init_UI()
            self.TheDockWidget()
            self.mainWidget.topLeftWidget.signal.connect(
                self.dockWidgetContents._add_item)
    
        def init_UI(self):
            self.setGeometry(100, 100, 400, 200)
            self.setWindowTitle("Test App")
            self.mainWidget = MainWidgetClass()
            self.setCentralWidget(self.mainWidget)
    
        def TheDockWidget(self):
            self.dockWidget = QDockWidget('Status:')
            self.dockWidget.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable)
            self.addDockWidget(Qt.RightDockWidgetArea, self.dockWidget)
            self.dockWidget.setSizePolicy(QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum))
            self.dockWidgetContents = DockWidgetContents()
            self.dockWidget.setWidget(self.dockWidgetContents)
    
    
    class MainWidgetClass(QWidget):
    
        def __init__(self):
            super().__init__()
            self.init_UI()
    
        def init_UI(self):
            mainLayout = QGridLayout()
            self.setLayout(mainLayout)
            self.topLeftWidget = TopLeftWidgetClass()
            mainLayout.addWidget(self.topLeftWidget, 0, 0)
    

    【讨论】:

    • 谢谢,我明白了。而且我看到我也错过了主窗口类中停靠和按钮之间的连接。这是有道理的,因为它是所有类的父类,所以连接必须通过它。我很难把所有这些东西都包起来,因为我在开始学习 python 之前只使用过 bash。
    • @user122121 如果可以的话,有几个建议:不要在创建函数时夸大其词:虽然分离函数可以(有时)让您的代码更好地“可视化”和整洁,但最重要的好处是一个功能是它可以并且应该再次使用。在您的代码中,除了_add_itemstart 之外,所有其他函数都是无用的,因为它们只会在__init__ 中被调用一次,并且实际上不会提高可读性。只需将所有init_UI 移动到__init__
    • 那么,类就不需要“类”后缀了,因为它是多余的:你可以清楚地知道它们是类,因为它们的名称是大写的(事实上,@ 987654329@ 应该有一个小写的“T”,因为函数和变量不应该大写)。
    • 我从某人那里学到了这个init_UI。我看到它在功能上毫无用处。我这样做只是为了整洁。但如果这是不好的做法,我会放弃它。谢谢。 Class 后缀只是为了我自己的理智。不知何故,这让我更容易了。但是正如您所说,大写的名称已经足够好地表示一个类。谢谢你的建议。
    猜你喜欢
    • 2018-06-19
    • 1970-01-01
    • 1970-01-01
    • 2013-10-08
    • 2019-04-20
    • 1970-01-01
    • 1970-01-01
    • 2020-10-14
    • 1970-01-01
    相关资源
    最近更新 更多