Créer des pièces de concepteur Qt avec Python (PyQt)

Ceci est un mémo sur la façon de créer un widget avec PyQt et de l'utiliser sur le concepteur Qt. Il comprend également la mise en œuvre du signal et du slot en tant que fonctions. L'exemple utilise Qt4, mais Qt5 est fondamentalement le même (bien que certaines modifications soient nécessaires). J'ai cherché sur le net, mais cela n'a pas frappé facilement, donc je pense que ce sera utile. Certains termes ont été nommés arbitrairement par moi, donc je vous serais reconnaissant de bien vouloir signaler ceux qui s'écartent des règles Qt.

Choses à préparer

  1. widget qui fonctionne avec PyQt.
  2. fichier python pour définir les plugins Seulement ces deux.

Créer un widget

Tout d'abord, créez un widget de test qui fonctionne avec PyQt dans le concepteur. L'apparence est preview.png On dirait. QLavel, QTextInput, QPushbutton sont disposés dans QHBoxLayout. Le nom de l'objet est TextInp. Le signal cliqué du QPushButton est connecté au clear de QTextInput et au slot getPressed de Form. L'emplacement getPressed a été créé sur le concepteur. Enregistrez-le dans le fichier ui_textinp.ui.


<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>TextInp</class>
 <widget class="QWidget" name="TextInp">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>62</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <widget class="QWidget" name="horizontalLayoutWidget">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>391</width>
     <height>61</height>
    </rect>
   </property>
   <layout class="QHBoxLayout" name="horizontalLayout">
    <item>
     <widget class="QLabel" name="label">
      <property name="text">
       <string>TextLabel</string>
      </property>
     </widget>
    </item>
    <item>
     <widget class="QLineEdit" name="lineEdit"/>
    </item>
    <item>
     <widget class="QPushButton" name="pushButton">
      <property name="text">
       <string>PushButton</string>
      </property>
     </widget>
    </item>
   </layout>
  </widget>
 </widget>
 <resources/>
 <connections>
  <connection>
   <sender>pushButton</sender>
   <signal>clicked()</signal>
   <receiver>lineEdit</receiver>
   <slot>clear()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>358</x>
     <y>31</y>
    </hint>
    <hint type="destinationlabel">
     <x>238</x>
     <y>32</y>
    </hint>
   </hints>
  </connection>
  <connection>
   <sender>pushButton</sender>
   <signal>clicked()</signal>
   <receiver>TextInp</receiver>
   <slot>getPressed()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>383</x>
     <y>31</y>
    </hint>
    <hint type="destinationlabel">
     <x>394</x>
     <y>51</y>
    </hint>
   </hints>
  </connection>
 </connections>
 <slots>
  <slot>getPressed()</slot>
 </slots>
</ui>

Ce fichier d'interface utilisateur utilisant pyuic4

$ pyuic4 ui_textinp.ui > ui_textinp.py

Convertir en. Une classe nommée Ui_TextInp est générée dans le fichier python généré. Ce nom vient du nom d'objet TextInp.

Ensuite, créez une application dans laquelle ce widget fonctionne indépendamment. Avec le nom textinp.py

#!/usr/bin/env python

import PyQt4
from PyQt4 import QtCore,QtGui
from PyQt4.QtGui import QApplication,QWidget,QVBoxLayout
 
__version__ = '0.0.1'
 
from ui_textinp import Ui_TextInp
try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s
    
class TextInp(QWidget, Ui_TextInp):
    def __init__(self, parent=None):
        super(TextInp, self).__init__(parent)
        self.setupUi(self)
        vBox = QVBoxLayout()
        vBox.addWidget(self.horizontalLayoutWidget)
        self.setLayout(vBox)
    @QtCore.pyqtSlot()
    def getPressed(self):
        print "PRESSED"
if __name__ == '__main__':
    app = QApplication(sys.argv)
    textinp = TextInp()
    textinp.show()
    sys.exit(app.exec_())

Je ne pense pas que vous ayez besoin de beaucoup de commentaires. La classe TextInp hérite de Ui_TextInp. Sans vBox, la taille ne suivra pas lorsque vous modifiez la taille de la fenêtre. Vous pouvez voir l'implémentation du slot. Lorsque vous cliquez sur QPushButton, la fonction getPressed est appelée et la chaîne PRSSED s'affiche dans la sortie standard. Quand tu cours

$ python textinp.py

Le widget comme indiqué ci-dessus sera affiché, la chaîne de caractères saisie dans le texte sera effacée en appuyant sur le bouton, et PRESSED sera affiché dans la sortie standard.

Créer un fichier de définition de plugin

Vous avez maintenant un widget que vous pouvez exécuter avec PyQt. Vous avez besoin d'un autre fichier python pour l'importer en tant que composant de concepteur. Appelons cela textinpplugin.py. Le fichier est le suivant.

#!/usr/bin/env python

"""
polygonwidgetplugin.py

A polygon widget custom widget plugin for Qt Designer.

Copyright (C) 2006 David Boddie <[email protected]>
Copyright (C) 2005-2006 Trolltech ASA. All rights reserved.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
"""

from PyQt4 import QtGui, QtDesigner
from textinp import TextInp


class TextInpPlugin(QtDesigner.QPyDesignerCustomWidgetPlugin):

    """TextInpPlugin(QtDesigner.QPyDesignerCustomWidgetPlugin)
    Provides a Python custom plugin for Qt Designer by implementing the
    QDesignerCustomWidgetPlugin via a PyQt-specific custom plugin class.
    """

    # The __init__() method is only used to set up the plugin and define its
    # initialized variable.
    def __init__(self, parent=None):
    
        super(TextInpPlugin, 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 TextInp(parent)

    # This method returns the name of the custom widget class that is provided
    # by this plugin.
    def name(self):
        return "TextInp"

    # Returns the name of the group in Qt Designer's widget box that this
    # widget belongs to.
    def group(self):
        return "Example for Qiita"

    # Returns the icon used to represent the custom widget in Qt Designer's
    # widget box.
    def icon(self):
        return QtGui.QIcon(_logo_pixmap)

    # 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="TextInp" name="textinp" />\n'

    # Returns the module containing the custom widget class. It may include
    # a module path.
    def includeFile(self):
        return "textinp"


# Define the image used for the icon.
_logo_16x16_xpm = [
"16 16 3 1",
"a c #008000",
"# c #0080ff",
". c #ffffff",
"................",
"................",
"..#############.",
"..#############.",
"..#############.",
"..#############.",
"..#############.",
"..#############.",
"................",
"................",
"..aaaaaaaaaaaaa.",
"..aaaaaaaaaaaaa.",
"..aaaaaaaaaaaaa.",
"..aaaaaaaaaaaaa.",
"..aaaaaaaaaaaaa.",
"................"]

_logo_pixmap = QtGui.QPixmap(_logo_16x16_xpm)

Je pense qu'il peut être appliqué en réécrivant textinp et TextInp. La chaîne retournée par def group sera le groupe de widgets du concepteur. De plus, le dernier _logo_16x16_xpm est une icône au format xpm.

Jusque là,

textinp.py
ui_textinp.py
textinpplugin.py

Trois fichiers sont créés.

Commencer le concepteur

Parmi ceux-ci, déplacez les fichiers liés au widget vers les widgets et les fichiers liés au plugin dans un sous-répertoire appelé python, définissez les variables d'environnement PYQTDESIGNERPATH et PYTHONPATH, et démarrez le concepteur.

$ mv  textinp.py ui_textinp.py widgets
$ mv  textinpplugin.py python
$ export PYQTDESIGNERPATH=python
$ export PYTHONPATH=widgets
$ designer

Vous devriez voir un widget comme celui ci-dessous dans la boîte de widget du concepteur. a.png Toutes nos félicitations. Le widget que vous avez créé peut maintenant être utilisé sur le concepteur comme n'importe quel autre widget.

De plus, le slot getPressed défini ci-dessus est également valide dans l'éditeur de signal / slot du concepteur. sigslot.png

signal, property

Mise en œuvre du signal

Oups, j'ai implémenté le slot, mais le signal n'était pas encore là. Ajoutez-le à textinp.py plus tôt. Ecrire pour générer (émettre) un signal lorsque getPressed est appelé. Écrivez QtCore.pyqtSignal au début de la définition de classe et appelez outText.emit ("TXT") lorsque vous voulez l'appeler.

class TextInp(QWidget, Ui_TextInp):
    outText=QtCore.pyqtSignal(str)
    def __init__(self, parent=None):
        super(TextInp, self).__init__(parent)
        self.setupUi(self)
        vBox = QVBoxLayout()
        vBox.addWidget(self.horizontalLayoutWidget)
        self.setLayout(vBox)
        self._label_text="Label text"
        self.label.setText(self._label_text)
    @QtCore.pyqtSlot()
    def getPressed(self):
        self.outText.emit(self.lineEdit.text())
        print self.lineEdit.text()

Vous pouvez voir que le signal est implémenté dans le concepteur. sig2.png

Mise en œuvre de la propriété

Textinp.py qui implémente la propriété.

class TextInp(QWidget, Ui_TextInp):
    outText=QtCore.pyqtSignal(str)
    def __init__(self, parent=None):
        super(TextInp, self).__init__(parent)
        self.setupUi(self)
        vBox = QVBoxLayout()
        vBox.addWidget(self.horizontalLayoutWidget)
        self.setLayout(vBox)
        self._label_text="Label text"
        self.label.setText(self._label_text)
    @QtCore.pyqtSlot()
    def getPressed(self):
        self.outText.emit(self.lineEdit.text())
        print self.lineEdit.text()
    def setLabelText(self,inptxt):
        self._label_text=inptxt
        self.label.setText(self._label_text)
    def getLabelText(self):
        return self._label_text
    label_text=QtCore.pyqtProperty(str, getLabelText, setLabelText)

Définissez les fonctions setLabelText et getLabelText dans QtCore.pyqtProperty. Sur le designer property_editor.png Label_text peut être spécifié comme suit.

Recommended Posts

Créer des pièces de concepteur Qt avec Python (PyQt)
Créer Spatia Lite en Python
Créer une fonction en Python
[GUI en Python] PyQt5 -Widget-
[Maya Python] Display .ui créé par Qt Designer dans Maya
Présentation de l'interface graphique: PyQt5 en Python
[GUI en Python] PyQt5 -Event-
Créer un conteneur DI avec Python
Créer un fichier binaire en Python
Créez Gmail en Python sans utiliser l'API
Créer une documentation de projet Python dans Sphinx
Créer une chaîne aléatoire en Python
Créer et lire des paquets de messages en Python
Créez vos propres commandes Linux en Python
Créer ScriptableObject en Python lors de la construction d'ADX2
[LLDB] Créez votre propre commande avec Python
Créer une application GUI simple en Python
[GPS] Créer un fichier kml avec Python
Quadtree en Python --2
CURL en Python
Métaprogrammation avec Python
Créez un environnement de test Vim + Python en 1 minute
Python 3.3 avec Anaconda
Géocodage en python
SendKeys en Python
Créer un fichier GIF en utilisant Pillow en Python
Méta-analyse en Python
Unittest en Python
Je veux créer une fenêtre avec Python
Comment créer un fichier JSON en Python
Créez automatiquement des rapports Word et Excel avec Python
Créer un environnement virtuel avec conda avec Python
Discord en Python
Allemand en Python
DCI en Python
tri rapide en python
nCr en python
N-Gram en Python
Programmation avec Python
Créer une barre de couleurs avec Python + Qt (PySide)
Plink en Python
Constante en Python
Créer une image avec des caractères avec python (japonais)
Créer un modèle d'investissement dynamique simple en Python
FizzBuzz en Python
Sqlite en Python
Étape AIC en Python
Créer une nouvelle page en confluence avec Python
Créer un widget avec une couleur spécifiée avec Python + Qt (PySide)
Créer un objet datetime à partir d'une chaîne en Python (Python 3.3)
LINE-Bot [0] en Python
Créer un package contenant des commandes globales en Python
CSV en Python
Assemblage inversé avec Python
Réflexion en Python
Constante en Python