简体   繁体   English

PyQt5:如何将子小部件移动到主 window 中?

[英]PyQt5: how to move sub widgets into main window?

This code opens 3 separate windows:此代码打开 3 个单独的 windows:

1) main window
2) widgetA 
3) widgetB.

How to write the code in such a way that it moves 2 and 3 into 1?如何以将 2 和 3 移动到 1 的方式编写代码?

So we just have one main window and in it 2 widgets that can communicate with each other.所以我们只有一个主要的 window,其中有 2 个可以相互通信的小部件。 Also, an additional feature: how can we write a function in such a way that it listens to incoming data and then sends it away?此外,还有一个附加功能:我们如何编写一个 function 以侦听传入数据然后将其发送出去?

class mainwindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(mainwindow, self).__init__(parent)

        self.button = QtWidgets.QPushButton("Click Me", self)
        self.button.clicked.connect(self.on_button_clicked)

        self.setCentralWidget(self.button)

        self.widgetA = widgetA()
        self.widgetB = widgetB()

        self.widgetA.procStart.connect(self.widgetB.on_procStart)
        self.widgetB.procDone.connect(self.widgetA.on_widgetB_procDone)

    @QtCore.pyqtSlot()
    def on_button_clicked(self):
        self.widgetA.show()
        self.widgetB.show()

        self.widgetA.raise_()

class widgetA(QtWidgets.QWidget):
    procStart = QtCore.pyqtSignal(str)

    def __init__(self, parent=None):
        super(widgetA, self).__init__(parent)

        self.lineEdit = QtWidgets.QLineEdit(self)
        self.lineEdit.setText("Hello!")

        self.button = QtWidgets.QPushButton("Send Message to B", self)
        self.button.clicked.connect(self.on_button_clicked)

        self.layout = QtWidgets.QHBoxLayout(self)
        self.layout.addWidget(self.lineEdit)
        self.layout.addWidget(self.button)

    @QtCore.pyqtSlot()
    def on_button_clicked(self):
        self.procStart.emit(self.lineEdit.text())

    @QtCore.pyqtSlot(str)
    def on_widgetB_procDone(self, message):
        self.lineEdit.setText("From B: " + message)

        self.raise_()


class widgetB(QtWidgets.QWidget):

    procDone = QtCore.pyqtSignal(str)

    def __init__(self, parent=None):
        super(widgetB, self).__init__(parent)

        self.lineEdit = QtWidgets.QLineEdit(self)
        self.button = QtWidgets.QPushButton("Send Message to A", self)
        self.layout = QtWidgets.QHBoxLayout(self)
        self.layout.addWidget(self.lineEdit)
        self.layout.addWidget(self.button)

        self.button.clicked.connect(self.on_button_clicked)

    @QtCore.pyqtSlot()
    def on_button_clicked(self):
        self.procDone.emit(self.lineEdit.text())

    @QtCore.pyqtSlot(str)
    def on_procStart(self, message):
        self.lineEdit.setText("From A: " + message)

        self.raise_()

if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    main = mainwindow()
    main.show()
    sys.exit(app.exec_())

If you need to show more than one widget into a "top level window" (no matter if it's a QWidget, a QDialog or a QMainWindow) you need to create a container widget.如果您需要在“顶层窗口”中显示多个小部件(无论它是 QWidget、QDialog 还是 QMainWindow),您需要创建一个容器小部件。

In your case you're using a QMainWindow, which is a very special kind of QWidget, as it has its own (internal and almost unaccessible) layout.在您的情况下,您使用的是 QMainWindow,它是一种非常特殊的 QWidget,因为它有自己的(内部且几乎不可访问的)布局。 The main content that is normally shown within a QMainWindow (besides its menubar, statusbar, toolbars and dockbars) is called the "central widget", and you're setting it to a QPushButton, so there's no room for anything else.通常在 QMainWindow 中显示的主要内容(除了它的菜单栏、状态栏、工具栏和停靠栏)称为“中央小部件”,并且您将其设置为 QPushButton,因此没有其他空间

The most common and conventional approach is to create a new QWidget (which is an empty widget that is used as the basis for all Qt widgets), set a layout for it and add the actual widgets to it:最常见和传统的方法是创建一个新的 QWidget(这是一个空的小部件,用作所有Qt 小部件的基础),为其设置布局并向其中添加实际的小部件:

class mainwindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(mainwindow, self).__init__(parent)

        container = QtWidgets.QWidget() self.setCentralWidget(container) # using a widget as an argument in a Qt layout constructor results in # automatically setting the layout for that widget layout = QtWidgets.QVBoxLayout(container)

        self.button = QtWidgets.QPushButton("Click Me", self)
        self.button.clicked.connect(self.on_button_clicked)

        self.widgetA = widgetA()
        self.widgetB = widgetB()

        layout.addWidget(self.button) layout.addWidget(self.widgetA) layout.addWidget(self.widgetB)
        # ...

Note that if you're not using QMainWindow but a standard QWidget or QDialog, you obviously don't need to use the "central widget", and you can just create a new layout on the current instance ( self ).请注意,如果您使用的不是 QMainWindow,而是标准的 QWidget 或 QDialog,您显然不需要使用“中央小部件”,您只需在当前实例 ( self ) 上创建一个新布局即可。

class SomeWidget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        layout = QtWidgets.QVBoxLayout(self)
        # ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM