IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PyQt Python Discussion :

Layout responsive avec PYQT5


Sujet :

PyQt Python

  1. #1
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2022
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Ardèche (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2022
    Messages : 8
    Par défaut Layout responsive avec PYQT5
    Salut ! Je cherche un moyen pour pouvoir disposer l'ensemble de mon layout comme étant responsive, c'est à dire qu'il remplit entièrement / complétement ma nouvelle fenêtre. Par exemple, j'aimerai que mon tableau au lieu d'être en haut à droite, qu'il prenne tout l'espace libre juste en-dessous des boutons.

    Ce code correspond à un code publié par une personne sur ce forum que j'ai repris et modifié pour pouvoir répondre à ce que je souhaitais faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    import sys
    from PyQt5 import (QtWidgets, QtCore, QtSql)
    from PyQt5 import *
    from PyQt5.QtWidgets import QApplication, QLineEdit
     
     
    def ouvrebaseqt(basesql):
     
        db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
        db.setDatabaseName(basesql)
        if not db.open():
            db = None
        return db
     
    def fermebaseqt(db):
        if db!=None:
            db.close()
     
    class VoirTableSql(QtWidgets.QMainWindow):
     
        def __init__(self, basesql, table, parent=None):
            super().__init__(parent)
     
            self.setGeometry(500, 500, 500, 500) 
     
            self.basesql = basesql
            self.db = ouvrebaseqt(self.basesql)
            if self.db == None:
                QtWidgets.QMessageBox.critical(self, "Ouverture de la base de données", "Erreur d'ouverture")
                self.close()
                sys.exit()
     
            self.table = table
     
            self.model = QtSql.QSqlRelationalTableModel(self, self.db)
     
            self.model.setEditStrategy(QtSql.QSqlRelationalTableModel.OnManualSubmit)
     
            self.vuetable = QtWidgets.QTableView(self)
            self.vuetable.setModel(self.model)
     
            self.vuetable.setSortingEnabled(True)
     
            posit = QtWidgets.QGridLayout()
     
            self.bouton1 = QtWidgets.QPushButton("Enregistrer les modifications dans la table", self)
            self.bouton1.clicked.connect(self.appliquer)
     
            posit.addWidget(self.bouton1, 0, 0)
     
            self.setCentralWidget(QtWidgets.QFrame())
     
            posit.addWidget(self.vuetable, 1, 0)
            self.centralWidget().setLayout(posit)
     
            self.model.setTable(self.table)
            self.model.select()
     
            self.vuetable.setItemDelegate(QtSql.QSqlRelationalDelegate(self.vuetable))
     
            self.vuetable.resizeColumnsToContents()
            self.vuetable.resizeRowsToContents()
     
     
        def appliquer(self):
     
            if self.model.submitAll():
                self.vuetable.resizeColumnsToContents()
                self.vuetable.resizeRowsToContents()
     
                QtWidgets.QMessageBox.information(self, "Enregistrement des modifications", "Enregistrement terminé")
            else:
                QtWidgets.QMessageBox.warning(self, "Enregistrement des modifications", "Erreur: %s" % self.model.lastError().text())
     
        def closeEvent(self, event=None):
     
            fermebaseqt(self.db) 
            event.accept()
    Ce code correspond à la fenêtre dans laquelle j'appelle VoirSqlTableau, pour pouvoir afficher les résultats compris dans la table en question, ici Matériel


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QLabel, QVBoxLayout, QWidget
    from SQL import VoirTableSql
     
    import sys
     
    class MaterielWindow(QWidget):
     
        def __init__(self):
            super().__init__()
     
            self.setWindowTitle("Gestion des matériaux")
            self.setGeometry(500, 500, 560, 500) 
     
            self.depart = QPushButton("Retour au menu de départ")        
            self.ajouter = QPushButton("Ajouter un nouveau matériel")
            self.supprimer = QPushButton("Supprimer un matériel")
     
            layout = QVBoxLayout()
     
            layout.addWidget(self.depart)
            layout.addWidget(self.ajouter)
            layout.addWidget(self.supprimer)
     
            layout.addWidget(VoirTableSql("Result/StockTelecom", "Materiel"))
     
            self.depart.clicked.connect(self.Main)  
            self.ajouter.clicked.connect(self.Ajouter)  
            self.supprimer.clicked.connect(self.Supprimer)
     
            self.setLayout(layout)

  2. #2
    Expert confirmé

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 305
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 305
    Par défaut
    Salut,

    Ton code est vraiment n'importe quoi.

    Si on te suis bien tu lances un QWidget dans lequel tu importes une classe héritant, elle, de QMainWindow !

    Franchement, déchire tout ça et utilise le Designer de Qt, tu gagnera beaucoup de temps et, en plus, tu peux tester ton application en cours de travail.

  3. #3
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2022
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Ardèche (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2022
    Messages : 8
    Par défaut
    Citation Envoyé par VinsS Voir le message
    Salut,

    Ton code est vraiment n'importe quoi.

    Si on te suis bien tu lances un QWidget dans lequel tu importes une classe héritant, elle, de QMainWindow !

    Franchement, déchire tout ça et utilise le Designer de Qt, tu gagnera beaucoup de temps et, en plus, tu peux tester ton application en cours de travail.
    Bonjour, en fait mon code il est pas compliqué à comprendre, j'ai un Main que je lance et sur celui-ci j'appelle les fenêtres dont j'ai besoin donc ici en l'occurrence Matériel. La fenêtre Matériel appelle SQL pour obtenir la table de ce que je veux. Moi j'ai juste besoin d'aide pour l'illustration de mon layout en responsive, j'ai pas demandé à ce qu'on me dise que mon travail est flingué.

  4. #4
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 816
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 816
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Citation Envoyé par Mova2 Voir le message
    Je cherche un moyen pour pouvoir disposer l'ensemble de mon layout comme étant responsive, c'est à dire qu'il remplit entièrement / complétement ma nouvelle fenêtre
    Il faut que ton layout appartienne à ladite fenêtre. Tu remplaces posit = QtWidgets.QGridLayout() par posit = QtWidgets.QGridLayout(self.centralWidget()).
    Ou bien tu laisses comme t'as écrit et ensuite tu ajoutes self.centralWidget().setLayout(posit) (en plus c'est ce que tu avais fait dans la classe MaterielWindow, on se demande pourquoi tu n'as pas fait pareil dans l'autre )
    PS: bien entendu, il faut avoir créé le centralWidget du mainWindow avant de le mettre comme parent du layout !!!

    Un exemple ici: https://pyqt.developpez.com/telechar...-au-mainwindow.

    Citation Envoyé par Mova2 Voir le message
    j'ai pas demandé à ce qu'on me dise que mon travail est flingué.
    Ben c'est le petit plus de ce forum: quand un truc est mal fait on le dit. L'autre solution serait de laisser le codeur continuer tout seul, finir par se planter dans le mur et le voir ensuite râler qu'on ne l'a pas prévenu...
    Tu n'as pas besoin de mettre ta sous-fenêtre en QMainWindow. C'est pas interdit mais inutile. De plus ton QMainWindow n'a pas besoin de mettre un QFrame en centralWidget, un QWidget suffit largement (plus tu montes haut dans la hiérarchie des objets Qt plus ton objet Qt est léger).
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour

    Il me semble reconnaître une partie de ma prose dans le 1er code. Comme quoi le PO a de bonnes lectures...

    Concernant le QMainWindow, j'ai déjà vu des critiques comme quoi c'est une fenêtre particulière à n'utiliser qu'une fois dans un programme. Auquel cas, on confond peut-être avec tkinter qui a une fenêtre "main" unique. Mais sous PyQt, on utilise QMainWindow quand on a besoin d'un QWidget avec un menu (et quelques autres fonctionnalités comme une ligne d'outils et la ligne du bas)! Et dans des programmes complexes, on peut appeler autant de QMainWindow qu'on veut. Par exemple, si un programme appelle un éditeur de texte, celui-ci a besoin d'un menu, et ce sera donc un QMainWindow.

    Mais dans le cas présent, si on n'a pas besoin de menu, il vaut mieux faire simple, et utiliser un QWidget! D'autant plus que le positionnement des widgets dans un QWidget est beaucoup plus simple.

  6. #6
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2022
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Ardèche (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2022
    Messages : 8
    Par défaut
    Bonjour !
    Merci pour vos réponses et c'est un honneur de discuter avec vous, car à chaque fois je reprends quelques parties de ce que vous proposez sur le forum pour pouvoir résoudre à chaque fois mes problèmes et cela m'aide pour le développement mais aussi sur la compréhension même si par moment j'ai quand même du mal.

    Pour la partie : self.centralWidget.setLayout(posit), cela ne marche pas :
    'builtin_function_or_method' object has no attribute 'setLayout'
    Pour l'autre moyen, il n'y a pas d'erreur dans le lancement mais aucun résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    posit = QtWidgets.QGridLayout(self.centralWidget())
    Et pour vos retours concernant le code de ma partie SQL, j'ai beau remplacer (QtWidgets.QMainWindow) par seulement QtWidgets, cela m'affiche le résultat suivant :
    class VoirTableSql(QtWidgets):
    TypeError: module() takes at most 2 arguments (3 given)

    PS : Pour les plus curieux pour savoir comment se déroule mon lancement : Main qui centralise les appels de toutes mes fenêtres (je les initialise) et en fonction des boutons sur lesquels j'appuie, ça lance des fenêtres qui possède une configuration unique qui représente à chaque fois une table de ma BDD. Et le fichier SQL, je le réutilise sous un même format dans chacune des tables et j'adapte l'appel sur les fenêtres par rapport à la table dont j'ai besoin.

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 816
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 816
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Mova2 Voir le message
    Pour la partie :
    self.centralWidget.setLayout(posit), cela ne marche pas :
    'builtin_function_or_method' object has no attribute 'setLayout'
    En fait c'est self.centralWidget().setLayout(posit) (et en plus je vois que tu l'avais déjà fait)
    Toutefois, en reprenant ton code et en enlevant tout ce qui est lié à SQL (que chez-moi je ne peux pas appeler) le résultat est parfait.
    Nom : VirtualBox_Debian10_64b_29_04_2022_12_58_35.png
Affichages : 744
Taille : 17,5 Ko

    Je peux tirer la fenêtre, tout suit le mouvement.

    Le code en question
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    #!/usr/bin/env python3
    # coding: utf-8
     
    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
     
    import sys
     
    class MaterielWindow(QWidget):
    	def __init__(self):
    		super().__init__()
    		self.setWindowTitle("Gestion des matériaux")
    		self.setGeometry(500, 500, 560, 500) 
     
    		self.depart = QPushButton("Retour au menu de départ")		
    		self.ajouter = QPushButton("Ajouter un nouveau matériel")
    		self.supprimer = QPushButton("Supprimer un matériel")
     
    		layout = QVBoxLayout(self)
    		layout.addWidget(self.depart)
    		layout.addWidget(self.ajouter)
    		layout.addWidget(self.supprimer)
    		layout.addWidget(VoirTableSql("Result/StockTelecom", "Materiel"))
     
    class VoirTableSql(QMainWindow):
    	def __init__(self, basesql, table, parent=None):
    		super().__init__(parent)
    		self.setCentralWidget(QFrame())
    		self.setGeometry(500, 500, 500, 500) 
    		self.basesql = basesql
    		self.table = table
    		self.vuetable = QTableView(self)
    		self.vuetable.setSortingEnabled(True)
    		posit = QGridLayout(self.centralWidget())
    		self.bouton1 = QPushButton("Enregistrer les modifications dans la table", self)
    		posit.addWidget(self.bouton1, 0, 0)
    		posit.addWidget(self.vuetable, 1, 0)
     
    		self.vuetable.resizeColumnsToContents()
    		self.vuetable.resizeRowsToContents()
     
    if __name__ == "__main__":
    	app=QApplication(sys.argv)
    	wid=MaterielWindow()
    	wid.show()
    	sys.exit(app.exec_())
    # if

    Maintenant il y a peut-être un souci avec le layout choisi parce que prendre un GridLayout pour y mettre un bouton en ligne 0, colonne 0 et la vue en ligne 1 colonne 0 (et rien dans les autres colonnes ) autant prendre alors un QVBoxLayout (mais bon, je sais que je ne suis pas là pour te dire que ton code est flingué)

    Citation Envoyé par Mova2 Voir le message
    Pour l'autre moyen, il n'y a pas d'erreur dans le lancement mais aucun résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    posit = QtWidgets.QGridLayout(self.centralWidget())
    C'est en fait la méthode principale de création d'un layout associé à un widget ce qui évite d'avoir à appeler ensuite setLayout().

    Citation Envoyé par Mova2 Voir le message
    Et pour vos retours concernant le code de ma partie SQL, j'ai beau remplacer (QtWidgets.QMainWindow) par seulement QtWidgets, cela m'affiche le résultat suivant :
    C'est pas ce qui a été dit. C'est un QWidget qu'il faut, pas un QtWidgets !!! Remplacer QtWidgets.QMainWindow par QtWidgets.QWidget.

    Citation Envoyé par Mova2 Voir le message
    PS : Pour les plus curieux pour savoir comment se déroule mon lancement : Main qui centralise les appels de toutes mes fenêtres (je les initialise) et en fonction des boutons sur lesquels j'appuie, ça lance des fenêtres qui possède une configuration unique qui représente à chaque fois une table de ma BDD. Et le fichier SQL, je le réutilise sous un même format dans chacune des tables et j'adapte l'appel sur les fenêtres par rapport à la table dont j'ai besoin.
    Oui, j'ai déjà fait ce genre de truc. Mais moi je fais ça par un menu (donc pas besoin de boutons). Toutefois (encore) mes fenêtres associées aux tables ne sont pas des QMainWindow. Même si ce n'est pas interdit, si ce n'est pas nécessaire alors ça n'est pas nécessaire.
    Donc j'ai un QMainWindow qui est le principal de mon appli et ensuite chaque menu affiche dans son centralWidget le widget dédié à gérer ma table lorsque le menu le demande. Et ce widget est un QDialog (parce que j'ai besoin de certaines de ses caractéristiques) mais il pourrait aussi être un QWidget que cela ne changerait rien.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  8. #8
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2022
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Ardèche (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2022
    Messages : 8
    Par défaut
    Bonjour !
    Malgré votre retour voici le résultat que j'obtiens malheureusement :

    Pièce jointe 618326

    Je souhaite obtenir le tableau centré et qui prend toute la place en bas, mais malheureusement, je n'ai toujours rien. En fait, sans mettre le central, les boutons s'affichent déjà correctement, mais avec ou sans, le tableau ne s'affiche pas comme je le souhaite.

    Pièce jointe 618327

    J'aimerai obtenir ce résultat. (En gros que le tableau complète toute la partie entourée en noir.)

    Merci beaucoup pour vos aides et vos retours.

  9. #9
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 816
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 816
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Mova2 Voir le message
    Bonjour !
    Malgré votre retour voici le résultat que j'obtiens malheureusement :

    Pièce jointe 618326
    Pièce jointe 618327
    Tes liens sont invalides. Enfin peut-être qu'ils le sont pour toi car peut-être ils sont dans un espace du site qui t'es dédié mais pas pour les autres (t'as qu'à revenir ici en tant que "non connecté" et tu le constateras). Si tu veux poster une image il faut le faire depuis ton ordi.
    Et à un moment il faut arrêter. Je te file un code qui fonctionne, et tu reviens en disant "ça ne fonctionne pas" donc admettons mais sans un code minimaliste reproduisant ce qui ne va pas, on pourra pas faire mieux.

    Pour résumer le fonctionnement d'un gestionnaire de positionnement
    1) tu as ton widget à l'écran
    2) tu crées un layout prenant ce widget en paramètre => le widget devient le père du layout. Ou bien tu crées un layout sans widget et tu fais ensuite un setLayout. Ce layout deviendra le layout "principal" du widget
    Petite parenthèse: un mainWindow n'étant pas un widget "pareil" que les autres il ne peut pas être parent d'un layout. C'est pour ça que dans le mainWindow il faut créer un widget dit "central" via setCentralWidget(). Ensuite ce widget "central" peut être récupéré via centralWidget() et être alors mis comme parent du layout.

    Ensuite tu veux placer des sous-widgets dans le layout, tu fais addWidget(). Et si tes widgets ont un placement un peu difficile, alors tu leur crées un layout juste pour eux et c'est ce layout que tu places dans le layout principal.
    Ici un exemple où je place deux widgets côte à côte, et ces deux ensembles placés sur un autre widget: https://pyqt.developpez.com/telechar...s-notre-signal
    Le gridLayout n'est pas forcément une solution adéquate car il taille chaque ligne en fonction du widget le plus haut de la ligne ; et il taille chaque colonne en fonction du widget le plus "large" de la colonne. Il est souvent plus efficace de construire ses briques layout par layout.
    Ici un exemple utilisant un gridLayout: https://qt.developpez.com/telecharge...7284/It-s-time
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Layout responsive avec une image en background d'en-tête
    Par Erakis dans le forum Mise en page CSS
    Réponses: 0
    Dernier message: 15/02/2014, 07h04
  2. [Struts-Layout] problème avec dynMenu
    Par vny dans le forum Struts 1
    Réponses: 3
    Dernier message: 26/11/2008, 14h01
  3. [Struts-Layout] Tableau avec deux couleurs alternées
    Par yolepro dans le forum Struts 1
    Réponses: 2
    Dernier message: 18/09/2006, 16h47
  4. Accéder à <layout:text> avec Javascript
    Par micanti dans le forum Struts 1
    Réponses: 2
    Dernier message: 30/05/2006, 17h59
  5. [Struts-layout]err. avec layout:menuItem
    Par javazer dans le forum Struts 1
    Réponses: 7
    Dernier message: 14/04/2006, 14h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo