显示当前小部件类之外的小部件

Posted

技术标签:

【中文标题】显示当前小部件类之外的小部件【英文标题】:Showing widget that is outside the current widgets class 【发布时间】:2021-01-22 23:12:31 【问题描述】:

示例:

假设我有一个 MainWindow 小部件,在该类中,我实例化了另外两个小部件(小部件一和小部件二)。每个小部件将有一个按钮:小部件一和小部件二的 next 和 back 分别。第一个小部件是可见的,第二个是隐藏的。

我想在第一个小部件中调用一个函数,该函数将自身隐藏并显示第二个小部件。然后对第二个小部件进行同样的操作。

如果我在主窗口中放置函数并连接按钮,我可以这样做,但我想避免这种情况。我对信号和插槽没有很好的了解,不知道怎么做或任何其他策略,然后将所有逻辑放在主窗口中。

import sys
from PyQt5 import QtWidgets as qtw


class WidgetOne(qtw.QWidget):
    def __init__(self):
        super().__init__()
        ########
        # initialization
        ########
        self.layout = qtw.QVBoxLayout()
        self.setLayout(self.layout)
        ########
        # Buttons
        ########
        self.next_button = qtw.QPushButton('Next')
        self.next_button.clicked.connect(self.next_widget)
        ########
        # Layout
        ########
        self.layout.addWidget(self.next_button)

    def next_widget(self):
        self.hide()
        # widget_two.show() # <--- This part won't work


class WidgetTwo(qtw.QWidget):
    def __init__(self):
        super().__init__()
        ########
        # initialization
        ########
        self.layout = qtw.QVBoxLayout()
        self.setLayout(self.layout)
        ########
        # Buttons
        ########
        self.back_button = qtw.QPushButton('Back')
        self.back_button.clicked.connect(self.back_to_first_widget)
        ########
        # Layout
        ########
        self.layout.addWidget(self.back_button)
        self.hide()

    def back_to_first_widget(self):
        self.hide()
        # widget_one.show()  # This part won't work


class MainWindow(qtw.QWidget):
    def __init__(self):
        super().__init__()
        ########
        # initialization
        ########
        self.layout = qtw.QVBoxLayout()
        self.setLayout(self.layout)
        self.widget_one = WidgetOne()
        self.widget_two = WidgetTwo()

        ########
        # Layout
        ########
        self.layout.addWidget(self.widget_one)
        self.layout.addWidget(self.widget_two)
        self.setWindowTitle("Title")
        self.show()


if __name__ == '__main__':
    app = qtw.QApplication(sys.argv)
    mw = MainWindow()
    sys.exit(app.exec())

【问题讨论】:

你已经看过QStackedWidget了吗?它是一个始终显示一个小部件的容器,将其隐藏在子级之上。它还具有确保适合所有小部件的布局的好处。 @ypnos 我认为 QStackedWidget 非常适合我想做的事情。谢谢 【参考方案1】:

您必须建立可以访问两个对象(发送方和接收方)的连接。

import sys
from PyQt5 import QtWidgets as qtw


class WidgetOne(qtw.QWidget):
    def __init__(self):
        super().__init__()

        self.next_button = qtw.QPushButton("Next")
        self.next_button.clicked.connect(self.hide)

        layout = qtw.QVBoxLayout(self)
        layout.addWidget(self.next_button)


class WidgetTwo(qtw.QWidget):
    def __init__(self):
        super().__init__()
        self.back_button = qtw.QPushButton("Back")
        self.back_button.clicked.connect(self.hide)

        layout = qtw.QVBoxLayout(self)
        layout.addWidget(self.back_button)
        self.hide()


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

        self.widget_one = WidgetOne()
        self.widget_two = WidgetTwo()

        self.widget_one.next_button.clicked.connect(self.widget_two.show)
        self.widget_two.back_button.clicked.connect(self.widget_one.show)

        layout = qtw.QVBoxLayout(self)
        layout.addWidget(self.widget_one)
        layout.addWidget(self.widget_two)
        self.setWindowTitle("Title")


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

【讨论】:

不知道您可以将两种方法连接到一个事件...+1来自我@eyllanesc @JakubSzlaur 一个信号可以连接“n”个槽,一个槽可以连接“n”个信号,这是Qt的关键 从来不需要使用它,但老实说很高兴知道这一点! @JakubSzlaur 另一方面,我看到在你的代码中你有self.next_button.clicked.connect(self.signal_next_widget.emit) 但没有必要使用发射,因为你也可以将一个信号连接到另一个信号,所以你可以用@替换它987654324@【参考方案2】:

为此使用QtCore.pyqtSignal 模块:

像这样创建模块(在构造函数之外):

class WidgetOne(qtw.QWidget):
    signal_next_widget = QtCore.pyqtSignal() #Here

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

然后在MainWindow中连接那个信号:

self.widget_one.signal_next_widget.connect(self.next_widget)
self.widget_two.signal_back_to_first_widget.connect(self.back_to_first_widget)

back_to_first_widgetnext_widget 方法添加到MainWindow 并相应地更改它们:

def back_to_first_widget(self):
    self.widget_two.hide()
    self.widget_one.show()

def next_widget(self):
    self.widget_one.hide()
    self.widget_two.show()

这是整个代码:

import sys
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore

class WidgetOne(qtw.QWidget):
    signal_next_widget = QtCore.pyqtSignal()

    def __init__(self):
        super().__init__()
        ########
        # initialization
        ########
        self.layout = qtw.QGridLayout()
        self.setLayout(self.layout)
        ########
        # Buttons
        ########
        self.next_button = qtw.QPushButton('Next')
        self.next_button.clicked.connect(self.signal_next_widget.emit)
        ########
        # Layout
        ########
        self.layout.addWidget(self.next_button)



class WidgetTwo(qtw.QWidget):
    signal_back_to_first_widget = QtCore.pyqtSignal()

    def __init__(self):
        super().__init__()
        ########
        # initialization
        ########
        self.layout = qtw.QVBoxLayout()
        self.setLayout(self.layout)
        ########
        # Buttons
        ########
        self.back_button = qtw.QPushButton('Back')
        self.back_button.clicked.connect(self.signal_back_to_first_widget.emit)
        ########
        # Layout
        ########
        self.layout.addWidget(self.back_button)
        self.hide()


class MainWindow(qtw.QWidget):
    def __init__(self):
        super().__init__()
        ########
        # initialization
        ########
        self.layout = qtw.QVBoxLayout()
        self.setLayout(self.layout)
        self.widget_one = WidgetOne()
        self.widget_two = WidgetTwo()


        self.widget_one.signal_next_widget.connect(self.next_widget)
        self.widget_two.signal_back_to_first_widget.connect(self.back_to_first_widget)

        ########
        # Layout
        ########
        self.layout.addWidget(self.widget_one)
        self.layout.addWidget(self.widget_two)
        self.setWindowTitle("Title")
        self.show()

    def back_to_first_widget(self):
        self.widget_two.hide()
        self.widget_one.show()

    def next_widget(self):
        self.widget_one.hide()
        self.widget_two.show()

if __name__ == '__main__':
    app = qtw.QApplication(sys.argv)
    mw = MainWindow()
    sys.exit(app.exec())

【讨论】:

以上是关于显示当前小部件类之外的小部件的主要内容,如果未能解决你的问题,请参考以下文章

如何通过单击放置在同一页面上的小部件来显示不同的小部件

发送缩放到打印机的小部件内容

Blogger的Gallery小部件显示当前帖子的所有图像

获取当前活动的小部件

如何使“堆栈”中的小部件计数取决于变量?

Flutter 小部件测试点击 - 不会在指定的小部件上进行测试