当前位置: 首页 > 面试题库 >

PyQt正确使用emit()和pyqtSignal()

越骏俊
2023-03-14
问题内容

我正在阅读有关PyQt5的一些文档,以提出一种简单的信号插槽机制。由于设计方面的考虑,我停了下来。

考虑以下代码:

import sys
from PyQt5.QtCore import (Qt, pyqtSignal)
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
    QVBoxLayout, QApplication)


class Example(QWidget):

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

        self.initUI()

    def printLabel(self, str):
        print(str)

    def logLabel(self, str):
        '''log to a file'''
        pass

    def initUI(self):

        lcd = QLCDNumber(self)
        sld = QSlider(Qt.Horizontal, self)

        vbox = QVBoxLayout()
        vbox.addWidget(lcd)
        vbox.addWidget(sld)

        self.setLayout(vbox)

        #redundant connections
        sld.valueChanged.connect(lcd.display)
        sld.valueChanged.connect(self.printLabel)
        sld.valueChanged.connect(self.logLabel)

        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Signal & slot')
        self.show()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

为了跟踪对滑块所做的更改,我仅打印并记录所做的更改。我对代码不满意的是,我需要调用sld.valueChanged三次插槽以将相同的信息发送到3个不同的插槽。

是否可以创建自己的pyqtSignal将整数发送到单个插槽的函数。插槽功能又会发出需要进行的更改吗?

  • 也许我不完全了解它的目的,emit()因为在PyQt Signal-Slot文档中没有很好的例子。我们仅给出了一个如何实现不emit带参数的示例。

我想做的是创建一个处理emit函数的函数。考虑以下:

import sys
from PyQt5.QtCore import (Qt, pyqtSignal)
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
    QVBoxLayout, QApplication)


class Example(QWidget):

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

        #create signal
        self.val_Changed = pyqtSignal(int, name='valChanged')

        self.initUI()

    def initUI(self):

        lcd = QLCDNumber(self)
        sld = QSlider(Qt.Horizontal, self)

        vbox = QVBoxLayout()
        vbox.addWidget(lcd)
        vbox.addWidget(sld)

        self.setLayout(vbox)

        sld.val_Changed.connect(self.handle_LCD)
        self.val_Changed.emit()

        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Signal & slot')
        self.show()

    def handle_LCD(self, text):
        '''log'''
        print(text)
        '''connect val_Changed to lcd.display'''

if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

这里显然存在一些严重的设计缺陷。我无法绕过函数调用的顺序。而且我执行不pyqtSignal
正确。但是,我确实相信正确说明以下3点将有助于我制作出合适的html" target="_blank">应用程序:

  1. 对于预定义的信号:将信号发送到插槽功能。可以重新实现插槽以使用信号值。
  2. pyqtSignal用一些参数产生对象。尚不清楚这些参数的目的是什么以及它们与“发射”参数有何不同。
  3. emit可以重新实现以将特定的信号值发送到插槽功能。还不清楚我为什么需要从以前存在的信号方法中发送不同的值。

随意为我要尝试的代码完全更改代码,因为我还没有弄清楚它是否属于好的样式。


问题答案:

您可以定义自己的插槽(任何可调用的python)并将其连接到信号,然后从该插槽中调用其他插槽。

class Example(QWidget):

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

    def printLabel(self, str):
        print(str)

    def logLabel(self, str):
        '''log to a file'''
        pass

    @QtCore.pyqtSlot(int)
    def on_sld_valueChanged(self, value):
        self.lcd.display(value)
        self.printLabel(value)
        self.logLabel(value)

    def initUI(self):

        self.lcd = QLCDNumber(self)
        self.sld = QSlider(Qt.Horizontal, self)

        vbox = QVBoxLayout()
        vbox.addWidget(self.lcd)
        vbox.addWidget(self.sld)

        self.setLayout(vbox)
        self.sld.valueChanged.connect(self.on_sld_valueChanged)


        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Signal & slot')

另外,如果要定义自己的信号,则必须将它们定义为类变量

class Example(QWidget):
    my_signal = pyqtSignal(int)

用于pyqtSignal定义将emit在该信号上显示的对象类型的参数,因此在这种情况下,您可以执行

self.my_signal.emit(1)

可以重新实现发射,以将特定的信号值发送到插槽功能。还不清楚我为什么需要从以前存在的信号方法中发送不同的值。

通常,您不应该发出内置信号。您只需要发出定义的信号即可。定义信号时,可以定义具有不同类型的不同签名,插槽可以选择它们要连接到的签名。例如,您可以这样做

my_signal = pyqtSignal([int], [str])

这将定义一个具有两个不同签名的信号,并且一个插槽可以连接到任何一个

@pyqtSlot(int)
def on_my_signal_int(self, value):
    assert isinstance(value, int)

@pyqtSlot(str)
def on_my_signal_str(self, value):
    assert isinstance(value, str)

实际上,我很少过载信号签名。通常,我只创建两个具有不同签名的单独信号,而不是使同一信号过载。但它的存在和PyQt的支持,因为Qt拥有被重载这样的信号(如QComboBox.currentIndexChanged



 类似资料:
  • 问题内容: 我读了这篇文章《如何真正地,真正地使用QThreads》。完整说明,它说而不是子类qthread和重新实现run(),应使用moveToThread(QThread *)使用moveToThread将QObject推送到QThread实例上 这是C ++示例,但我不知道如何将其转换为python代码。 我一直在使用这种方法来生成qthread,但是如您所见,它使用的是不推荐的方式。我如

  • 问题内容: 我的应用程序具有以下结构: 我有一个包含一些脚本的功能文件夹,以及一个在ui.py文件上包含PyQt生成的代码的ui文件夹。 还有一个main.py文件,该文件加载ui.py以显示界面,并且ui.py从根目录的“ images”文件夹中加载一些图像。 如果我直接在python上执行脚本(main.py文件中为double clic),则图像不会显示。 但是,如果将终端与“ python

  • 如何使用和方法将对象从一个控制器发送到另一个控制器? 它的工作方式并不像我想的那样。和如何工作?

  • 问题内容: 我正在尝试学习如何在PyQt Gui应用程序中使用QThreads。我有一些可以运行一段时间的东西,(通常)可以在其中更新Gui的点,但是我想将主要工作拆分为自己的线程(有时东西会卡住,最终有一个取消/重试按钮,如果Gui被冻结(因为主循环被阻塞),则该按钮显然不起作用)。 我已阅读https://mayaposch.wordpress.com/2011/11/01/how-to-re

  • 问题内容: 如何使用和方法将对象从一个控制器发送到另一个控制器? 它不按我认为的方式工作。如何做和工作? 问题答案: 首先,父子范围关系确实很重要。你有两种可能性发出某些事件: -将事件向下分发到所有子范围, -通过范围层次结构向上调度事件。 我对你的控制器(作用域)关系一无所知,但是有几种选择: 如果scope of 是作用域的父级,则你的代码应通过替换为来工作: 如果你的范围之间没有父子关系,

  • 我用PHPass散列密码已经很久了。我承认仍然有一些我不完全理解(或忽略)的东西来正确地散列密码,所以今天我查看了所有我能找到的关于它的信息。 回顾PHPass文档,我已经进入了这个: 除了实际的哈希之外,phpass 在对新密码或密码进行哈希处理时会透明地生成随机 salt,并将哈希类型、salt 和密码拉伸迭代计数编码到它返回的“hash 编码字符串”中。当phpass根据存储的哈希对密码或密