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

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

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


person linuxoid    schedule 11.01.2012    source источник
comment
Я нашел свою ошибку. Я удалил main_widget из виджета пользовательского интерфейса и использовал его в качестве удерживающего виджета для всех других небольших виджетов (кнопок, строк редактирования и т. д.), а основной класс просто создает экземпляр виджета пользовательского интерфейса (см. выше) — проблема с меню решена.   -  person linuxoid    schedule 12.01.2012


Ответы (3)


Вы ищете что-то подобное? Я не совсем уверен, какой у тебя 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_())
person Jeff    schedule 11.01.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.

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

Жестких правил нет — каждый проект уникален.

person ekhumoro    schedule 11.01.2012
comment
Раньше я использовал Qt Designer, но мне не нравится его сгенерированный код, он выглядит ужасно и его трудно потом изменить, а также он добавляет много мусора, который мне на самом деле не нужен. Вот почему я начал писать интерфейсы сам с нуля. Таким образом, я контролирую каждую строку кода. Хотя я могу что-то упустить, но я научусь. Спасибо за ваш ответ. - person linuxoid; 12.01.2012
comment
@user665327. Вы совершенно неправильно поняли назначение сгенерированных модулей. Они предназначены для редактирования. Они предназначены только для импорта. Я не скажу, что есть что-то плохое в написании кода пользовательского интерфейса вручную, но вы многое упускаете, не используя Qt Designer. По крайней мере, вы должны использовать его как инструмент для экспериментов. И даже если вы не используете код, сгенерированный pyuic, вы все равно можете многому научиться, увидев, как он работает (это особенно верно, когда речь идет об управлении компоновкой). - person ekhumoro; 12.01.2012

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

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

person Community    schedule 18.06.2013