web-dev-qa-db-fra.com

PyQt - comment ajouter un widget d'interface utilisateur distinct à QMainWindow

Je n'ai commencé que récemment à programmer et Python (PyQt) en particulier. J'ai ma classe QMainWindow principale. Mais je voulais la séparer des widgets de l'interface utilisateur, afin que toutes les fenêtres (menus, barres d'outils, boutons communs) sont dans QMainWindow, mais tous les widgets spécifiques au programme/à l'interface utilisateur (boutons pusg, boîtes combo, images, cases à cocher, etc.) sont dans une classe QWidget distincte. Mais je Je ne sais pas si je fais ça correctement.

  1. J'ai un problème avec les dispositions - quelque chose d'invisible couvre les menus afin qu'ils ne soient pas cliquables par la souris, je pense que je n'ajoute pas correctement mon widget d'interface utilisateur à la fenêtre principale

Voici comment je le fais:

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. J'ai vu d'autres Python programmes où les applications sont divisées en beaucoup de petits fichiers de code (si je comprends bien, avoir tout dans la classe principale est illisible ou ingérable).

Quelle est votre suggestion pour casser du code en petits morceaux? Comment est-il préférable de le faire? Ou pour l'interface utilisateur, tout peut être au même endroit? Dois-je briser le code/les classes d'interface utilisateur dans un fichier séparé?

Je vous remercie.

[RESOLU]

J'ai trouvé mon erreur - j'ai supprimé le main_widget de la classe de widget UI (maintenant tous les widgets UI sont placés directement sur le widget de classe UI lui-même) et je fais seulement ceci:

self.main_layout.addWidget(self.form_widget)

plus de problèmes avec les menus

20
linuxoid

Cherchez-vous quelque chose comme ça? Je ne sais pas vraiment ce que votre main_widget est

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_())
24
Jeff
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()) 

bonne façon !!!

10
user1176501

Je recommanderais d'utiliser Qt Designer pour créer autant d'interface utilisateur que possible.

Il vous sera beaucoup plus facile d'expérimenter les mises en page et ainsi de suite, et cela gardera automatiquement la plupart des éléments liés à l'interface utilisateur séparés du reste de la logique de votre application. Faites cela pour la fenêtre principale, ainsi que pour toutes les boîtes de dialogue, aussi simples soient-elles.

Utilisez ensuite pyuic4 pour compiler python à partir de tous les fichiers ui, et les mettre tous ensemble dans leur propre sous-package.

Je recommanderais d'utiliser le -w flag lors de la compilation des fichiers ui. Cela générera une classe d'interface utilisateur simple qui peut être directement sous-classée.

Votre fenêtre principale finira donc par ressembler à ceci:

from ui.mainwindow import MainWindowUI

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

Notez que tous les widgets ajoutés dans Qt Designer sont désormais accessibles directement en tant qu'attributs de l'instance MainWindow.

Je ne m'inquiéterais pas de diviser votre application en modules plus petits avant le développement. Cela peut ne pas s'avérer nécessaire - mais si c'est le cas, il deviendra plus évident de le faire une fois que l'application commencera à devenir plus complexe.

Il n'y a pas de règles strictes et rapides - chaque projet est différent.

10
ekhumoro