2012-01-11 58 views
15

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

  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控件类main_widget(现在所有的UI控件直接放置在UI类的小部件本身),只有做到这一点:

self.main_layout.addWidget(self.form_widget) 

没有更多的菜单问题

+0

我发现我的错误。我已经从UI小部件中删除了main_widget,并将其本身用作所有其他小部件(按钮,编辑线等)的控件,而主类仅实例化UI部件(请参见上文) - 解决了菜单问题。 – linuxoid 2012-01-12 01:53:18

回答

20

你在寻找类似的东西吗?我真的不知道你的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_()) 
7

我会建议使用Qt Designer创建尽可能多的用户界面尽可能的。

你会发现以这种方式尝试布局等等会更容易,并且它会自动将大部分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实例的属性。

我不会担心在开发过程中将应用程序分成更小的模块。这可能不是必要的 - 但是如果这样做的话,一旦应用程序开始变得更加复杂,如何做到这一点将变得更加明显。

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

+1

我曾经使用Qt设计器,但我不喜欢它生成的代码,它看起来很糟糕,以后很难改变,它也增加了很多我并不需要的垃圾。这就是为什么我从头开始写自己的UI。这样我就可以控制每一行代码。虽然我可能会失去一些东西,但我会学习。谢谢您的回复。 – linuxoid 2012-01-12 01:51:02

+5

@ user665327。你完全误解了生成的模块的用途。他们不适合编辑。它们仅用于_importing_。我不会说手工编写UI代码有什么问题,但是由于不使用Qt Designer而错失了很多。至少,你应该用它作为实验的工具。即使你不使用'pyuic'生成的代码,你仍然可以通过看看它是如何做的事情来学习很多东西(当涉及到布局管理时尤其如此)。 – ekhumoro 2012-01-12 03:20:02

8
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()) 

正确的方法!

相关问题