PyQt - как добавить отдельный виджет пользовательского интерфейса в QMainWindow

Я только недавно начал программировать и Python (PyQt) в частности. У меня есть мой основной класс QMainWindow. Но я хотел отделить его от виджета пользовательского интерфейса, так что все материалы Windows (меню, панели инструментов, общие кнопки) находятся в QMainWindow, но все специальные виджеты для программ/пользовательских интерфейсов (pusgbuttons, comboboxes, images, checkboxes и т.д.) Находятся в отдельный класс QWidget. Но я не уверен, что я делаю это правильно.

  • У меня проблема с макетами - что-то невидимое закрывает меню, так что они не могут щелкнуть мышью, я думаю, что я не добавляю свой виджет пользовательского интерфейса в главное окно правильно

Вот как я это делаю:

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)
  • Я видел другие программы на Python, где приложения разбиты на множество небольших файлов кода (как я понимаю, все, что включено в основной класс, нечитабельно или неуправляемо).

Как вы предлагаете разбить код на мелкие кусочки? Как это лучше сделать? Или для пользовательского интерфейса все это может быть в одном большом месте? Должен ли я вообще нарушать код/​​классы пользовательского интерфейса в отдельный файл?

Спасибо.

[решено]

Я нашел свою ошибку - я удалил main_widget из класса виджета пользовательского интерфейса (теперь все виджеты пользовательского интерфейса размещаются непосредственно в виджетах класса UI), и только это:

self.main_layout.addWidget(self.form_widget)

больше проблем с меню

Ответы

Ответ 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

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

правильный путь!!!

Ответ 3

Я бы рекомендовал использовать Qt Designer для создания максимально возможного интерфейса.

Вам будет намного легче экспериментировать с макетами и т.д. таким образом, и он автоматически сохранит большую часть материала, связанного с пользовательским интерфейсом, отдельно от остальной части вашей логики приложения. Сделайте это для главного окна, а также для любых диалоговых окон, как бы прост.

Затем используйте pyuic4 для компиляции модулей python из всех файлов ui и поместите их все вместе в свой собственный подпакет.

Я бы рекомендовал использовать флаг -w при компиляции файлов ui. Это создаст простой 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.

Я бы не стал беспокоиться о том, чтобы разбить приложение на более мелкие модули до тех пор, пока он не появится в разработке. Возможно, это не обязательно, но если это произойдет, станет более очевидным, как это сделать, когда приложение станет более сложным.

Нет жестких и быстрых правил - каждый проект отличается.