【问题标题】:PyQt - how to add separate UI widget to QMainWindowPyQt - 如何将单独的 UI 小部件添加到 QMainWindow
【发布时间】:2012-02-07 12:35:13
【问题描述】:

我最近才开始编程,尤其是 Python (PyQt)。我有我的主要QMainWindow 课程。但我想将它与 UI 小部件分开,以便所有 Windows 的东西(菜单、工具栏、常用按钮)都在 QMainWindow 中,但所有程序/UI 特定的小部件(按钮、组合框、图像、复选框等)都在单独的QWidget 类。但我不确定我这样做是否正确。

  1. 我的布局有问题 - 一些不可见的东西覆盖了菜单,因此它们不能被鼠标点击,我想我没有正确地将我的 UI 小部件添加到主窗口中

我是这样做的:

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

        self.main_widget = QWidget(self)
        ...
        self.form_widget = FormWidget(self) 
        #This is my UI widget

        self.main_layout = QVBoxLayout(self.main_widget)
        self.main_layout.sizeConstraint = QLayout.SetDefaultConstraint
        self.main_layout.addWidget(self.form_widget.main_widget) 
        #form_widget has its own main_widget where I put all other widgets onto

        self.main_widget.setLayout(self.main_layout)
        self.setCentralWidget(self.main_widget)
  1. 我见过其他 Python 程序,其中应用程序被分解为许多小代码文件(据我了解,主类中的所有内容都是不可读或无法管理的)。

您对将代码分成小块有什么建议?怎么做比较好?或者对于 UI,它可以都在一个大的地方?我应该把 UI 代码/类分成单独的文件吗?

谢谢。

[已解决]

我发现我的错误 - 我从 UI 小部件类中删除了 main_widget(现在所有 UI 小部件都直接放在 UI 类小部件本身上)并且只这样做:

self.main_layout.addWidget(self.form_widget)

菜单不再有问题

【问题讨论】:

  • 我发现了我的错误。我已经从 UI 小部件中删除了 main_widget 并将其自身用作所有其他小部件(按钮、编辑线等)的保持小部件,并且主类只是实例化 UI 小部件(见上文) - 菜单问题已解决。

标签: python layout pyqt qmainwindow


【解决方案1】:

您正在寻找这样的东西吗?我不太确定你的main_widget 是什么

from PyQt4.QtCore import *
from PyQt4.QtGui  import *

import sys

class MyMainWindow(QMainWindow):

    def __init__(self, parent=None):

        super(MyMainWindow, self).__init__(parent)
        self.form_widget = FormWidget(self) 
        self.setCentralWidget(self.form_widget) 


class FormWidget(QWidget):

    def __init__(self, parent):        
        super(FormWidget, self).__init__(parent)
        self.layout = QVBoxLayout(self)

        self.button1 = QPushButton("Button 1")
        self.layout.addWidget(self.button1)

        self.button2 = QPushButton("Button 2")
        self.layout.addWidget(self.button2)

        self.setLayout(self.layout)

app = QApplication([])
foo = MyMainWindow()
foo.show()
sys.exit(app.exec_())

【讨论】:

    【解决方案2】:

    我建议使用 Qt Designer 来创建尽可能多的 UI。

    您会发现以这种方式尝试布局等要容易得多,并且它会自动将大部分与 UI 相关的内容与您的应用程序逻辑的其余部分分开。对主窗口执行此操作,也对任何对话框执行此操作,无论多么简单。

    然后使用pyuic4从所有ui文件中编译python模块,并将它们全部放在自己的子包中。

    我建议在编译 ui 文件时使用 -w 标志。这将生成一个简单的封装 UI 类,可以直接对其进行子类化。

    所以你的主窗口最终看起来像这样:

    from ui.mainwindow import MainWindowUI
    
    class MainWindow(MainWindowUI):
        def __init__(self):
            super(MainWindow, self).__init__()
            # connect signals...
            # do other setup stuff...
    

    请注意,Qt Designer 中添加的所有小部件现在都可以作为MainWindow 实例的属性直接访问。

    在开发后期之前,我不会担心将您的应用程序分解成更小的模块。结果可能没有必要 - 但如果有必要,一旦应用程序开始变得更加复杂,如何做到这一点就会变得更加明显。

    没有硬性规定 - 每个项目都不同。

    【讨论】:

    • 我曾经使用Qt Designer,但我不喜欢它生成的代码,它看起来很糟糕,以后很难更改,它还添加了很多我不需要的垃圾.这就是我开始自己从头开始编写 UI 的原因。这样我就控制了每一行代码。虽然我可能会遗漏一些东西,但我会学习的。感谢您的回复。
    • @user665327。您完全误解了生成模块的目的。它们不用于编辑。它们仅用于导入。我不会说手工编写 UI 代码有什么问题,但不使用 Qt 设计器会让你大失所望。至少,您应该将其用作实验工具。即使您不使用pyuic 生成的代码,您仍然可以通过查看它的工作方式来了解很多(在布局管理方面尤其如此)。跨度>
    【解决方案3】:
    import sys
    from PyQt4 import QtCore, QtGui
    
    
    class MainWindow(QtGui.QMainWindow):
    
        def __init__(self, parent=None):
            super(MainWindow, self).__init__(parent)
            self.form_widget = FormWidget(self)
            _widget = QtGui.QWidget()
            _layout = QtGui.QVBoxLayout(_widget)
            _layout.addWidget(self.form_widget)
            self.setCentralWidget(_widget)
    
    class FormWidget(QtGui.QWidget):
    
        def __init__(self, parent):
            super(FormWidget, self).__init__(parent)
            self.__controls()
            self.__layout()
    
        def __controls(self):
            self.label = QtGui.QLabel("Name for backdrop")
            self.txted = QtGui.QLineEdit()
            self.lbled = QtGui.QLabel("Select a readNode")
            self.cmbox = QtGui.QComboBox()
    
        def __layout(self):
            self.vbox = QtGui.QVBoxLayout()
            self.hbox = QtGui.QHBoxLayout()
            self.h2Box = QtGui.QHBoxLayout()
    
            self.hbox.addWidget(self.label)
            self.hbox.addWidget(self.txted)
    
            self.h2Box.addWidget(self.lbled)
            self.h2Box.addWidget(self.cmbox)
    
            self.vbox.addLayout(self.hbox)
            self.vbox.addLayout(self.h2Box)
            self.setLayout(self.vbox)
    
    def main():
        app = QtGui.QApplication(sys.argv)
        win = MainWindow()
        win.show()
        app.exec_()
    
    if __name__ == '__main__':
        sys.exit(main()) 
    

    正确方法!!!

    【讨论】:

      猜你喜欢
      • 2017-10-31
      • 2012-08-14
      • 2014-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-19
      相关资源
      最近更新 更多