PyQt6 自定义信号与槽连接

1 投票
1 回答
55 浏览
提问于 2025-04-14 15:51

我有一个按钮,它是一个单独的类,还有一个主窗口类。在主窗口里,有两个输入框(QLineEdit)。我想在点击按钮时获取这两个输入框里的文本,并对它们进行处理。处理的逻辑应该放在按钮的类里,因为我想尝试使用信号和槽的连接。按钮类会接收来自输入框的文本,并以某种方式返回处理后的文本。返回的文本会显示在一个标签(QLabel)上。目前文本没有变化,尽管文本已经发出了处理的信号。然后它应该再发回去,但现在不工作。

import sys
from PyQt6.QtWidgets import QApplication, QPushButton, QVBoxLayout, QLabel, QLineEdit, QWidget
from PyQt6.QtCore import pyqtSignal as Signal, pyqtSlot as Slot


class ButtonWidget(QPushButton):
    accepted_text = Signal(str, str)

    def __init__(self):
        super().__init__()
        self.setText("Accept Text")

    @Slot(str, str)
    def accept_text(self, text1, text2):
        text1 = text1.upper()
        text2 = text2.title()
        self.accepted_text.emit(text1, text2)


class MainWindow(QWidget):
    pushed_text = Signal(str, str)

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

        layout = QVBoxLayout()
        self.setLayout(layout)

        self.line1 = QLineEdit(placeholderText="enter text")
        self.line2 = QLineEdit(placeholderText="enter text")

        self.button_widget = ButtonWidget()

        self.label = QLabel("")

        layout.addWidget(self.line1)
        layout.addWidget(self.line2)
        layout.addWidget(self.button_widget)
        layout.addWidget(self.label)

        self.pushed_text.connect(self.button_widget.accept_text)
        self.button_widget.clicked.connect(self.change_label)

        self.show()

    def change_label(self):
        text1 = self.line1.text()
        text2 = self.line2.text()
        self.pushed_text.emit(text1, text2)
        self.label.setText(text1 + " " + text2)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec())

我尝试将按钮类中的 accept_text() 函数与主窗口类中输入框的 pushed_text 信号连接起来。accept_text() 函数应该以某种方式返回处理后的文本。

结果窗口

它应该是 STACK Overflow,而不是 stack overflow。有没有什么方法可以正确地在类之间连接信号和槽?

1 个回答

0

我想我大概弄明白了,但过程有点乱。也许有更好的方法。这个事情真的很让人困惑,如果你知道更好的方法,请告诉我。我做了以下更改:

class ButtonWidget(QPushButton):
    accepted_text = Signal(str, str)
    returned_text = Signal(str, str)

    def __init__(self):
        super().__init__()
        self.setText("Accept Text")

        self.accepted_text.connect(self.accept_text)

    @Slot(str, str)
    def accept_text(self, text1, text2):
        text1 = text1.upper()
        text2 = text2.title()
        self.returned_text.emit(text1, text2)

我给 ButtonWidget 添加了一个新的信号 returned_text。我把 accepted_text 信号和 accept_text 这个函数连接起来。现在这个函数会发出 returned_text 信号。

在 MainWindow 窗口里,我删除了 pushed_text 信号,并添加了以下代码:

    self.button_widget.returned_text.connect(self.update_label)
    self.button_widget.clicked.connect(self.change_label)

    self.show()

def update_label(self, text1, text2):
    self.label.setText(text1 + " " + text2)

def change_label(self):
    text1 = self.line1.text()
    text2 = self.line2.text()
    self.button_widget.accepted_text.emit(text1, text2)

我把 returned_text 信号和 update_label 函数连接起来。按钮点击事件仍然连接着 change_label 函数。在这个函数里,我们获取想要更改的元素,并发出 accepted_text 信号,这个信号又连接着 ButtonWidget 里的 accept_text 函数。

现在它的工作方式正是我想要的那样。

结果

这是完整的代码:

import sys
from PyQt6.QtWidgets import QApplication, QPushButton, QVBoxLayout, QLabel, QLineEdit, QWidget
from PyQt6.QtCore import pyqtSignal as Signal, pyqtSlot as Slot


class ButtonWidget(QPushButton):
    accepted_text = Signal(str, str)
    returned_text = Signal(str, str)

    def __init__(self):
        super().__init__()
        self.setText("Accept Text")

        self.accepted_text.connect(self.accept_text)

    @Slot(str, str)
    def accept_text(self, text1, text2):
        text1 = text1.upper()
        text2 = text2.title()
        self.returned_text.emit(text1, text2)


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()

        layout = QVBoxLayout()
        self.setLayout(layout)

        self.line1 = QLineEdit(placeholderText="enter text")
        self.line2 = QLineEdit(placeholderText="enter text")

        self.button_widget = ButtonWidget()

        self.label = QLabel("")

        layout.addWidget(self.line1)
        layout.addWidget(self.line2)
        layout.addWidget(self.button_widget)
        layout.addWidget(self.label)

        self.button_widget.returned_text.connect(self.update_label)
        self.button_widget.clicked.connect(self.change_label)

        self.show()

   def update_label(self, text1, text2):
        self.label.setText(text1 + " " + text2)

   def change_label(self):
        text1 = self.line1.text()
        text2 = self.line2.text()
        self.button_widget.accepted_text.emit(text1, text2)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec())

撰写回答