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 :

Création et intégration de widgets personnalisés avec QtDesigner


Sujet :

PyQt Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2009
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juillet 2009
    Messages : 51
    Par défaut Création et intégration de widgets personnalisés avec QtDesigner
    Bonjour,

    J'aimerai créer mes widegets personnalisés dans QtDesigner et pouvoir les réutiliser pour créer mon application principale.

    Prenons un exemple simple :
    Je crée un LineEdit assosié à un Label. J'appel ça un LabeledLineEdit > LabeledLineEdit.ui
    Comment feriez-vous pour réutiliser ce LabeledLineEdit dans la création d'une MainWindow par exemple ?

    Pour l'instant, j'ai eu l'idée de transformer le LabeledLineEdit.ui en ui_LabeledLineEdit.py grâce à pyuic :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    pyuic4 -o ui_LabeledLineEdit.py -wx LabeledLineEdit.ui
    Ensuite, je créer un plugin pour QtDesigner comme dans les exemples fournis avec PyQt LabeledLineEditPlugin.py.
    Enfin, je démare QtDesigner et je devrai voir apparaitre mon LabelLineEdit dans la liste des widgets mais rien n'apparait...

    Pour vérrifier que ça peut marcher, j'ai copier/coller un des exemples (widget+plugin) PyQt dans les mêmes répertoires que ui_LabeledLineEdit.py et LabeledLineEditPlugin.py. Et là ça marche !

    Merci

    ui_configViewer.py :
    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
    from PyQt4 import QtCore, QtGui
     
    class Ui_configViewer(QtGui.QWidget):
        def setupUi(self, configViewer):
            configViewer.setObjectName("configViewer")
            configViewer.resize(400, 346)
            self.cVGridLayout = QtGui.QGridLayout(configViewer)
            self.cVGridLayout.setObjectName("cVGridLayout")
            self.configViewerToolBox = QtGui.QToolBox(configViewer)
            self.configViewerToolBox.setObjectName("configViewerToolBox")
            self.configViewerToolBoxPage = Ui_configViewerToolBoxPage()
            self.configViewerToolBoxPage.setGeometry(QtCore.QRect(0, 0, 382, 264))
            self.configViewerToolBoxPage.setObjectName("configViewerToolBoxPage")
            self.configViewerToolBoPageGridLayout = QtGui.QGridLayout(self.configViewerToolBoxPage)
            self.configViewerToolBoPageGridLayout.setObjectName("configViewerToolBoPageGridLayout")
            self.configViewerToolBox.addItem(self.configViewerToolBoxPage, "")
            self.cVGridLayout.addWidget(self.configViewerToolBox, 1, 0, 1, 2)
            self.confAsCurrentPushButton = QtGui.QPushButton(configViewer)
            self.confAsCurrentPushButton.setObjectName("confAsCurrentPushButton")
            self.cVGridLayout.addWidget(self.confAsCurrentPushButton, 0, 0, 1, 1)
            spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
            self.cVGridLayout.addItem(spacerItem, 0, 1, 1, 1)
     
            self.retranslateUi(configViewer)
            self.configViewerToolBox.setCurrentIndex(0)
            QtCore.QMetaObject.connectSlotsByName(configViewer)
     
        def retranslateUi(self, configViewer):
            configViewer.setWindowTitle(QtGui.QApplication.translate("configViewer", "Form", None, QtGui.QApplication.UnicodeUTF8))
            self.configViewerToolBox.setItemText(self.configViewerToolBox.indexOf(self.configViewerToolBoxPage), QtGui.QApplication.translate("configViewer", "Page 1", None, QtGui.QApplication.UnicodeUTF8))
            self.confAsCurrentPushButton.setText(QtGui.QApplication.translate("configViewer", "Exporter comme configuration courante", None, QtGui.QApplication.UnicodeUTF8))
     
    from ui_configViewerToolBoxPage import Ui_configViewerToolBoxPage
     
    class configViewer(QtGui.QWidget, Ui_configViewer):
        def __init__(self, parent=None, f=QtCore.Qt.WindowFlags()):
            QtGui.QWidget.__init__(self, parent, f)
     
            self.setupUi(self)
     
     
    if __name__ == "__main__":
        import sys
        app = QtGui.QApplication(sys.argv)
        configViewer = QtGui.QWidget()
        ui = Ui_configViewer()
        ui.setupUi(configViewer)
        configViewer.show()
        sys.exit(app.exec_())
    configViewerPlugin.py :
    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
    #!/usr/bin/env python
     
    from PyQt4 import QtGui, QtDesigner
    from Interface.widgets.ui_configViewer import *
     
    class ConfigViewerPlugin(QtDesigner.QPyDesignerCustomWidgetPlugin, configViewer):
     
            # The __init__() method is only used to set up the plugin and define its
        # initialized variable.
        def __init__(self, parent=None):
     
            super(ConfigViewerPlugin, self).__init__(parent)
     
            self.initialized = False
     
        # The initialize() and isInitialized() methods allow the plugin to set up
        # any required resources, ensuring that this can only happen once for each
        # plugin.
        def initialize(self, core):
     
            if self.initialized:
                return
     
            self.initialized = True
     
        def isInitialized(self):
     
            return self.initialized
     
        # This factory method creates new instances of our custom widget with the
        # appropriate parent.
        def createWidget(self, parent):
            return configViewer(parent)
     
        # This method returns the name of the custom widget class that is provided
        # by this plugin.
        def name(self):
            return "ConfigViewer"
     
        # Returns the name of the group in Qt Designer's widget box that this
        # widget belongs to.
        def group(self):
            return "PyQt Examples"
     
     
        # Returns a short description of the custom widget for use in a tool tip.
        def toolTip(self):
            return ""
     
        # Returns a short description of the custom widget for use in a "What's
        # This?" help message for the widget.
        def whatsThis(self):
            return ""
     
        # Returns True if the custom widget acts as a container for other widgets;
        # otherwise returns False. Note that plugins for custom containers also
        # need to provide an implementation of the QDesignerContainerExtension
        # interface if they need to add custom editing support to Qt Designer.
        def isContainer(self):
            return False
     
        # Returns an XML description of a custom widget instance that describes
        # default values for its properties. Each custom widget created by this
        # plugin will be configured using this description.
        def domXml(self):
            return '<widget class="configViewer" name="ConfigViewer">\n' \
                   ' <property name="toolTip">\n' \
                   '  <string>Le template d\' une config</string>\n' \
                   ' </property>\n' \
                   ' <property name="whatsThis">\n' \
                   '  <string>Le widget pour afficher une config</string>\n' \
                   ' </property>\n' \
                   '</widget>\n'
     
        # Returns the module containing the custom widget class. It may include
        # a module path.
        def includeFile(self):
            return "Interface.widgets.ui_configViewer"

  2. #2
    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,

    Comme j'avais absolument besoin de ça, j'ai creusé un peu le sujet, et tu trouveras ce que je fais ici:

    http://python.jpvweb.com/mesrecettes...uveaux_widgets

    Ça a l'air un peu compliqué, comme ça, mais une fois qu'on a compris, ça marche très bien!

  3. #3
    Expert confirmé

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

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par défaut
    Pour que ton widget apparaisse dans le Designer, il faut qu'il soit placé au bon endroit et dans une catégorie.

    Exemple Linux, tu adaptes le début des chemins à ta situation, avec les fichiers:
    LabeledLineEdit.py -> le widget
    LabeledLineEditplugin.py -> le plugin
    et le groupe MyWidgets

    Dans le dossier:
    /usr/lib/pythonx.y/dist-packages/MyWidgets/
    (ou sa variante site-packages)
    tu places le fichier LabeledLineEdit.py

    Dans le dossier:
    /usr/lib/qt4/plugins/designer/python/MyWidgets/
    (variante, /usr/lib/x86_64-linux-gnu/qt4/...)
    tu replaces le fichier LabeledLineEdit.py

    Dans le dossier:
    /usr/lib/qt4/plugins/designer/python/
    (variante, /usr/lib/x86_64-linux-gnu/qt4/...)
    tu places le fichier LabeledLineEditplugin.py

    Dans le fichier plugin, tu devras adapter avant tout:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        def group(self):
            return "MyWidgets"
     
    ...
     
        def includeFile(self):
            return "MyWidgets.LabeledLineEdit"
    Normalement ton widget apparaîtra dans sa catégorie dans le Designer.
    Si ce n'est pas le cas, lance-le dans un terminal pour voir si ce n'est pas le script du widget qui est rejeté
    Sous Linux:

    D'autres exemples:
    http://bazaar.launchpad.net/~vincent...y-1.0/VWidgets

  4. #4
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2009
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juillet 2009
    Messages : 51
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Bonjour,

    Comme j'avais absolument besoin de ça, j'ai creusé un peu le sujet, et tu trouveras ce que je fais ici:

    http://python.jpvweb.com/mesrecettes...uveaux_widgets

    Ça a l'air un peu compliqué, comme ça, mais une fois qu'on a compris, ça marche très bien!
    tyrtamos : Je me suis inspiré exactement des même sources que toi et mis en place quasiment la même solution à une différence prêt : la tienne marche !
    Je ne pense pas avoir de problème au niveu de l'environnement parce que j'ai copié/collé l'exemple "analogClock" de PyQt dans mes répertoires plugins et widgets et il marche très bien (il s'affiche dans QtDesigner) !
    J'en déduit que les erreurs ne peuvent apparaitre qu'à cause de mon code soit du plugin, soit du widget.
    Le code du widget est généré directement avec pyuic4. Il n'a donc pas de slot ni properties ect...

    VinsS: Comme j'ai répondu plus haut, je ne pense pas avoir de souci d'environnement car un exemple tourne sur mon arboressance. Merci pour tes exemples.


    Comme je n'arrive pas à voir le configViewer généré avec pyuic, j'ai essayé de coder un petit widget perso codé à la main. Il n'apparait toujours pas !

    Mes dossiers :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    runQtDesigner.py
    plugins/
    |____ configViewerPagePlugin.py
    |____ analogclockplugin.py
    widgets/
    |____ configViewerPage.py
    |____ analogclock.py
    configViewerPagePlugin.py

    configViewerPage.py :
    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
    from PyQt4 import QtCore, QtGui
     
     
    class ConfigViewerPage(QtGui.QWidget):
     
        def __init__(self, parent=None):
            super(ConfigViewerPage, self).__init__(parent)
     
            self.gridLayout = QtGui.QGridLayout()
            self.myPushButton = QtGui.QPushButton("Mon bouton !")
            self.groupsVLayout = QtGui.QVBoxLayout()
            self.label1 = QtGui.QLabel("hyalaaaaa !!!")
            self.label2 = QtGui.QLabel("hyalaaaaa22222 !!!")
            self.groupsVLayout.addWidget(self.label1)
            self.groupsVLayout.addWidget(self.label2)        
            self.gridLayout.addLayout(self.groupsVLayout, 0,0)
            self.gridLayout.addWidget(self.myPushButton, 1,0)
            self.setLayout(self.gridLayout)
     
     
     
    if __name__ == "__main__":
        import sys
        app = QtGui.QApplication(sys.argv)
        widget = ConfigViewerPage()
        widget.show()
        sys.exit(app.exec_())

    configViewerPagePlugin.py :

    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
    from PyQt4 import QtGui, QtDesigner
    from Interface.widgets.configViewerPage import ConfigViewerPage
     
    class ConfigViewerPagePlugin(QtDesigner.QPyDesignerCustomWidgetPlugin):
     
        def __init__(self, parent=None):
            super(ConfigViewerPagePlugin, self).__init__(parent)
     
            self.initialized = False
     
        def initialize(self, core):
            if self.initialized:
                return
            self.initialized = True
     
        def isInitialized(self):
            return self.initialized
     
        def createWidget(self, parent):
            return ConfigViewerPage(parent)
     
        def name(self):
            return 'configViewerPage'
     
        def group(self):
            return 'Diam widget'
     
        def domXml(self):
            return '<widget class="ConfigViewerPage" name="configViewerPage" />\n'
     
        def includeFile(self):
            return 'configViewerPage'
    Du coup j'ai essayé de reprendre exactement l'exemple sur le widget de géolocalisation que tyrtamos présente mais sans plus de résultat !

    J'ai regardé dans la rubrique Aide/"A propos de plugins" dans QtDesigner et il ne charge que des librairies en .so. Je ne sais pas si c'est normal mais il n'y a aucun widget écrit en python qui apparait dans la rubrique.

    Merci pour vos réponses

  5. #5
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2009
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juillet 2009
    Messages : 51
    Par défaut
    J'ai mis trop d'informations sur mon précédent poste.
    La réflexion est :
    Mon QtDesigner ne voit que les librairies .so est-ce normal ? Si oui, comment génère-t-on ces librairies à partir des plugins écrit en python ?

    On gagne en clarté mais excusez moi pour ce double post.
    Merci

  6. #6
    Expert confirmé

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

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par défaut
    Pourrais-tu préciser ton arborescence ?

    Qu'est-ce que c'est que ce runQtDesigner.py ?

    Exemple chez moi:

    /usr/lib/i386-linux-gnu/qt4/plugins/designer/libpythonplugin.so
    /usr/lib/i386-linux-gnu/qt4/plugins/designer/python/vlineeditplugin.py
    /usr/lib/i386-linux-gnu/qt4/plugins/designer/python/VWidgets/vlineedit.py


    Le premier fichier libpythonplugin.so est indispensable, si il n'est pas présent, c'est un problème au niveau de l'installation de PyQt qui est censé l'installer.


    Ensuite je vois que tu as défini un groupe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
        def group(self):
            return 'Diam widget'
     
     
        def includeFile(self):
            return 'configViewerPage'
    C'est le nom de la catégorie tel qu'il apparaît dans le panneau des widgets. Après ceux de Qt et, chez moi, avant ceux de KDE.
    Selon moi tes widgets doivent se trouver dans un dossier de ce nom. Donc quelque chose comme ça:
    .../qt4/plugins/designer/libpythonplugin.so
    .../qt4/plugins/designer/python/configViewerPagePlugin.py
    .../qt4/plugins/designer/python/Diam_widget/configViewerPage.py

    et changer le code du plugin:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
        def group(self):
            return 'Diam_widget'
     
     
        def includeFile(self):
            return 'Diam_widget.configViewerPage'

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 22/02/2010, 10h40
  2. Création d'un livre d'or avec dreamweaver
    Par stanley dans le forum Dreamweaver
    Réponses: 2
    Dernier message: 24/10/2008, 17h07
  3. Kdevelop avec Qtdesigner
    Par Moonshadow dans le forum Linux
    Réponses: 5
    Dernier message: 10/03/2006, 10h35
  4. Création d'une variable de session avec un ID
    Par PrinceMaster77 dans le forum ASP
    Réponses: 4
    Dernier message: 18/10/2004, 10h28

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