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

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

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

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

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

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

Спасибо.

[решаемые]

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

self.main_layout.addWidget(self.form_widget)

больше никаких проблем с меню

Ответы [ 3 ]

24 голосов
/ 11 января 2012

Вы ищете что-то подобное?Я не совсем уверен, что ваш 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_())
10 голосов
/ 18 июня 2013
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()) 

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

10 голосов
/ 12 января 2012

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

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

Затем используйте pyuic4, чтобы скомпилировать модули 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.

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

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

...