PyQt Lab est un outil puissant qui permet aux développeurs de créer des applications 3D avec OpenGL. Il offre une variété de fonctionnalités qui permettent aux développeurs de créer des applications 3D interactives et intuitives. PyQt Lab est un outil open source qui est facile à apprendre et à utiliser. Il est également très flexible et peut être utilisé pour créer des applications 3D pour une variété de plates-formes. Dans cet article, nous allons examiner les principales fonctionnalités de PyQt Lab et comment elles peuvent être utilisées pour créer des applications 3D avec OpenGL.
PyQt Lab’ : 3D avec OpenGL :
Par X. HINAULT – Juin 2013

Ce que l’on va faire ici
- Je vous propose ici de réaliser une interface simple affichant le repère 3D de base et permettant de le visualiser en appliquant rotation et translation.
Pré-requis
- python 2.7
- pyqt4.x
- python-opengl
Le fichier d’interface *.ui
<ui version=« 4.0 »>
<class>Form</class>
<widget class=« QWidget » name=« Form »>
<property name=« geometry »>
<rect>
<x>0</x>
<y>0</y>
<width>540</width>
<height>365</height>
</rect>
</property>
<property name=« windowTitle »>
<string>pyqt + openGL : translation/rotation du repère 3D de base</string>
</property>
<widget class=« QWidget » name=« horizontalLayoutWidget »>
<property name=« geometry »>
<rect>
<x>10</x>
<y>10</y>
<width>320</width>
<height>240</height>
</rect>
</property>
<layout class=« QHBoxLayout » name=« horizontalLayout »/>
</widget>
<widget class=« QLabel » name=« labelTranslation »>
<property name=« geometry »>
<rect>
<x>340</x>
<y>10</y>
<width>81</width>
<height>13</height>
</rect>
</property>
<property name=« text »>
<string>Translation :</string>
</property>
</widget>
<widget class=« QLineEdit » name=« lineEditTx »>
<property name=« geometry »>
<rect>
<x>370</x>
<y>30</y>
<width>45</width>
<height>20</height>
</rect>
</property>
<property name=« text »>
<string>10</string>
</property>
</widget>
<widget class=« QPushButton » name=« pushButtonTxMoins »>
<property name=« geometry »>
<rect>
<x>340</x>
<y>30</y>
<width>23</width>
<height>20</height>
</rect>
</property>
<property name=« text »>
<string>-X</string>
</property>
</widget>
<widget class=« QPushButton » name=« pushButtonTxPlus »>
<property name=« geometry »>
<rect>
<x>420</x>
<y>30</y>
<width>23</width>
<height>20</height>
</rect>
</property>
<property name=« text »>
<string>+X</string>
</property>
</widget>
<widget class=« QPushButton » name=« pushButtonTyMoins »>
<property name=« geometry »>
<rect>
<x>340</x>
<y>60</y>
<width>23</width>
<height>20</height>
</rect>
</property>
<property name=« text »>
<string>-Y</string>
</property>
</widget>
<widget class=« QPushButton » name=« pushButtonTyPlus »>
<property name=« geometry »>
<rect>
<x>420</x>
<y>60</y>
<width>23</width>
<height>20</height>
</rect>
</property>
<property name=« text »>
<string>+Y</string>
</property>
</widget>
<widget class=« QLineEdit » name=« lineEditTy »>
<property name=« geometry »>
<rect>
<x>370</x>
<y>60</y>
<width>45</width>
<height>20</height>
</rect>
</property>
<property name=« text »>
<string>10</string>
</property>
</widget>
<widget class=« QPushButton » name=« pushButtonTzMoins »>
<property name=« geometry »>
<rect>
<x>340</x>
<y>90</y>
<width>23</width>
<height>20</height>
</rect>
</property>
<property name=« text »>
<string>-Z</string>
</property>
</widget>
<widget class=« QPushButton » name=« pushButtonTzPlus »>
<property name=« geometry »>
<rect>
<x>420</x>
<y>90</y>
<width>23</width>
<height>20</height>
</rect>
</property>
<property name=« text »>
<string>+Z</string>
</property>
</widget>
<widget class=« QLineEdit » name=« lineEditTz »>
<property name=« geometry »>
<rect>
<x>370</x>
<y>90</y>
<width>45</width>
<height>20</height>
</rect>
</property>
<property name=« text »>
<string>10</string>
</property>
</widget>
<widget class=« QPushButton » name=« pushButtonRxMoins »>
<property name=« geometry »>
<rect>
<x>340</x>
<y>140</y>
<width>23</width>
<height>20</height>
</rect>
</property>
<property name=« text »>
<string>-X</string>
</property>
</widget>
<widget class=« QLineEdit » name=« lineEditRy »>
<property name=« geometry »>
<rect>
<x>370</x>
<y>170</y>
<width>45</width>
<height>20</height>
</rect>
</property>
<property name=« text »>
<string>10</string>
</property>
</widget>
<widget class=« QPushButton » name=« pushButtonRxPlus »>
<property name=« geometry »>
<rect>
<x>420</x>
<y>140</y>
<width>23</width>
<height>20</height>
</rect>
</property>
<property name=« text »>
<string>+X</string>
</property>
</widget>
<widget class=« QPushButton » name=« pushButtonRzMoins »>
<property name=« geometry »>
<rect>
<x>340</x>
<y>200</y>
<width>23</width>
<height>20</height>
</rect>
</property>
<property name=« text »>
<string>-Z</string>
</property>
</widget>
<widget class=« QPushButton » name=« pushButtonRzPlus »>
<property name=« geometry »>
<rect>
<x>420</x>
<y>200</y>
<width>23</width>
<height>20</height>
</rect>
</property>
<property name=« text »>
<string>+Z</string>
</property>
</widget>
<widget class=« QLineEdit » name=« lineEditRz »>
<property name=« geometry »>
<rect>
<x>370</x>
<y>200</y>
<width>45</width>
<height>20</height>
</rect>
</property>
<property name=« text »>
<string>10</string>
</property>
</widget>
<widget class=« QLabel » name=« labelRotation »>
<property name=« geometry »>
<rect>
<x>340</x>
<y>120</y>
<width>81</width>
<height>13</height>
</rect>
</property>
<property name=« text »>
<string>Rotation</string>
</property>
</widget>
<widget class=« QPushButton » name=« pushButtonRyMoins »>
<property name=« geometry »>
<rect>
<x>340</x>
<y>170</y>
<width>23</width>
<height>20</height>
</rect>
</property>
<property name=« text »>
<string>-Y</string>
</property>
</widget>
<widget class=« QLineEdit » name=« lineEditRx »>
<property name=« geometry »>
<rect>
<x>370</x>
<y>140</y>
<width>45</width>
<height>20</height>
</rect>
</property>
<property name=« text »>
<string>10</string>
</property>
</widget>
<widget class=« QPushButton » name=« pushButtonRyPlus »>
<property name=« geometry »>
<rect>
<x>420</x>
<y>170</y>
<width>23</width>
<height>20</height>
</rect>
</property>
<property name=« text »>
<string>+Y</string>
</property>
</widget>
<widget class=« QLCDNumber » name=« lcdNumberRx »>
<property name=« geometry »>
<rect>
<x>450</x>
<y>140</y>
<width>64</width>
<height>20</height>
</rect>
</property>
<property name=« styleSheet »>
<string notr=« true »>background-color: rgb(170, 255, 127);
color: rgb(0, 85, 0);</string>
</property>
<property name=« segmentStyle »>
<enum>QLCDNumber::Flat</enum>
</property>
</widget>
<widget class=« QLabel » name=« labelRx »>
<property name=« geometry »>
<rect>
<x>520</x>
<y>150</y>
<width>20</width>
<height>13</height>
</rect>
</property>
<property name=« text »>
<string>Rx</string>
</property>
</widget>
<widget class=« QLabel » name=« labelRy »>
<property name=« geometry »>
<rect>
<x>520</x>
<y>180</y>
<width>20</width>
<height>13</height>
</rect>
</property>
<property name=« text »>
<string>Ry</string>
</property>
</widget>
<widget class=« QLCDNumber » name=« lcdNumberRy »>
<property name=« geometry »>
<rect>
<x>450</x>
<y>170</y>
<width>64</width>
<height>20</height>
</rect>
</property>
<property name=« styleSheet »>
<string notr=« true »>background-color: rgb(170, 255, 127);
color: rgb(0, 85, 0);</string>
</property>
<property name=« segmentStyle »>
<enum>QLCDNumber::Flat</enum>
</property>
</widget>
<widget class=« QLabel » name=« labelRz »>
<property name=« geometry »>
<rect>
<x>520</x>
<y>210</y>
<width>20</width>
<height>13</height>
</rect>
</property>
<property name=« text »>
<string>Rz</string>
</property>
</widget>
<widget class=« QLCDNumber » name=« lcdNumberRz »>
<property name=« geometry »>
<rect>
<x>450</x>
<y>200</y>
<width>64</width>
<height>20</height>
</rect>
</property>
<property name=« styleSheet »>
<string notr=« true »>background-color: rgb(170, 255, 127);
color: rgb(0, 85, 0);</string>
</property>
<property name=« segmentStyle »>
<enum>QLCDNumber::Flat</enum>
</property>
</widget>
<widget class=« QLCDNumber » name=« lcdNumberTz »>
<property name=« geometry »>
<rect>
<x>450</x>
<y>90</y>
<width>64</width>
<height>20</height>
</rect>
</property>
<property name=« styleSheet »>
<string notr=« true »>background-color: rgb(170, 255, 127);
color: rgb(0, 85, 0);</string>
</property>
<property name=« segmentStyle »>
<enum>QLCDNumber::Flat</enum>
</property>
</widget>
<widget class=« QLabel » name=« labelTx »>
<property name=« geometry »>
<rect>
<x>520</x>
<y>40</y>
<width>20</width>
<height>13</height>
</rect>
</property>
<property name=« text »>
<string>Tx</string>
</property>
</widget>
<widget class=« QLabel » name=« labelTz »>
<property name=« geometry »>
<rect>
<x>520</x>
<y>100</y>
<width>20</width>
<height>13</height>
</rect>
</property>
<property name=« text »>
<string>Tz</string>
</property>
</widget>
<widget class=« QLabel » name=« labelTy »>
<property name=« geometry »>
<rect>
<x>520</x>
<y>70</y>
<width>20</width>
<height>13</height>
</rect>
</property>
<property name=« text »>
<string>Ty</string>
</property>
</widget>
<widget class=« QLCDNumber » name=« lcdNumberTx »>
<property name=« geometry »>
<rect>
<x>450</x>
<y>30</y>
<width>64</width>
<height>20</height>
</rect>
</property>
<property name=« styleSheet »>
<string notr=« true »>background-color: rgb(170, 255, 127);
color: rgb(0, 85, 0);</string>
</property>
<property name=« segmentStyle »>
<enum>QLCDNumber::Flat</enum>
</property>
</widget>
<widget class=« QLCDNumber » name=« lcdNumberTy »>
<property name=« geometry »>
<rect>
<x>450</x>
<y>60</y>
<width>64</width>
<height>20</height>
</rect>
</property>
<property name=« styleSheet »>
<string notr=« true »>background-color: rgb(170, 255, 127);
color: rgb(0, 85, 0);</string>
</property>
<property name=« segmentStyle »>
<enum>QLCDNumber::Flat</enum>
</property>
</widget>
<widget class=« QPushButton » name=« pushButtonRAZ »>
<property name=« geometry »>
<rect>
<x>350</x>
<y>230</y>
<width>85</width>
<height>20</height>
</rect>
</property>
<property name=« text »>
<string>RAZ</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
<designerdata>
<property name=« gridDeltaX »>
<number>10</number>
</property>
<property name=« gridDeltaY »>
<number>10</number>
</property>
<property name=« gridSnapX »>
<bool>true</bool>
</property>
<property name=« gridSnapY »>
<bool>true</bool>
</property>
<property name=« gridVisible »>
<bool>true</bool>
</property>
</designerdata>
</ui>
Le fichier d’interface *.py
- Fichier obtenu automatiquement avec l’utilitaire pyuic4 à partir du fichier *.ui créé avec QtDesigner :
# Form implementation generated from reading ui file
#
# Created: Mon Aug 19 15:49:52 2013
# by: PyQt4 UI code generator 4.9.1
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName(_fromUtf8(« Form »))
Form.resize(540, 365)
self.horizontalLayoutWidget = QtGui.QWidget(Form)
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(10, 10, 320, 240))
self.horizontalLayoutWidget.setObjectName(_fromUtf8(« horizontalLayoutWidget »))
self.horizontalLayout = QtGui.QHBoxLayout(self.horizontalLayoutWidget)
self.horizontalLayout.setMargin(0)
self.horizontalLayout.setObjectName(_fromUtf8(« horizontalLayout »))
self.labelTranslation = QtGui.QLabel(Form)
self.labelTranslation.setGeometry(QtCore.QRect(340, 10, 81, 13))
self.labelTranslation.setObjectName(_fromUtf8(« labelTranslation »))
self.lineEditTx = QtGui.QLineEdit(Form)
self.lineEditTx.setGeometry(QtCore.QRect(370, 30, 45, 20))
self.lineEditTx.setObjectName(_fromUtf8(« lineEditTx »))
self.pushButtonTxMoins = QtGui.QPushButton(Form)
self.pushButtonTxMoins.setGeometry(QtCore.QRect(340, 30, 23, 20))
self.pushButtonTxMoins.setObjectName(_fromUtf8(« pushButtonTxMoins »))
self.pushButtonTxPlus = QtGui.QPushButton(Form)
self.pushButtonTxPlus.setGeometry(QtCore.QRect(420, 30, 23, 20))
self.pushButtonTxPlus.setObjectName(_fromUtf8(« pushButtonTxPlus »))
self.pushButtonTyMoins = QtGui.QPushButton(Form)
self.pushButtonTyMoins.setGeometry(QtCore.QRect(340, 60, 23, 20))
self.pushButtonTyMoins.setObjectName(_fromUtf8(« pushButtonTyMoins »))
self.pushButtonTyPlus = QtGui.QPushButton(Form)
self.pushButtonTyPlus.setGeometry(QtCore.QRect(420, 60, 23, 20))
self.pushButtonTyPlus.setObjectName(_fromUtf8(« pushButtonTyPlus »))
self.lineEditTy = QtGui.QLineEdit(Form)
self.lineEditTy.setGeometry(QtCore.QRect(370, 60, 45, 20))
self.lineEditTy.setObjectName(_fromUtf8(« lineEditTy »))
self.pushButtonTzMoins = QtGui.QPushButton(Form)
self.pushButtonTzMoins.setGeometry(QtCore.QRect(340, 90, 23, 20))
self.pushButtonTzMoins.setObjectName(_fromUtf8(« pushButtonTzMoins »))
self.pushButtonTzPlus = QtGui.QPushButton(Form)
self.pushButtonTzPlus.setGeometry(QtCore.QRect(420, 90, 23, 20))
self.pushButtonTzPlus.setObjectName(_fromUtf8(« pushButtonTzPlus »))
self.lineEditTz = QtGui.QLineEdit(Form)
self.lineEditTz.setGeometry(QtCore.QRect(370, 90, 45, 20))
self.lineEditTz.setObjectName(_fromUtf8(« lineEditTz »))
self.pushButtonRxMoins = QtGui.QPushButton(Form)
self.pushButtonRxMoins.setGeometry(QtCore.QRect(340, 140, 23, 20))
self.pushButtonRxMoins.setObjectName(_fromUtf8(« pushButtonRxMoins »))
self.lineEditRy = QtGui.QLineEdit(Form)
self.lineEditRy.setGeometry(QtCore.QRect(370, 170, 45, 20))
self.lineEditRy.setObjectName(_fromUtf8(« lineEditRy »))
self.pushButtonRxPlus = QtGui.QPushButton(Form)
self.pushButtonRxPlus.setGeometry(QtCore.QRect(420, 140, 23, 20))
self.pushButtonRxPlus.setObjectName(_fromUtf8(« pushButtonRxPlus »))
self.pushButtonRzMoins = QtGui.QPushButton(Form)
self.pushButtonRzMoins.setGeometry(QtCore.QRect(340, 200, 23, 20))
self.pushButtonRzMoins.setObjectName(_fromUtf8(« pushButtonRzMoins »))
self.pushButtonRzPlus = QtGui.QPushButton(Form)
self.pushButtonRzPlus.setGeometry(QtCore.QRect(420, 200, 23, 20))
self.pushButtonRzPlus.setObjectName(_fromUtf8(« pushButtonRzPlus »))
self.lineEditRz = QtGui.QLineEdit(Form)
self.lineEditRz.setGeometry(QtCore.QRect(370, 200, 45, 20))
self.lineEditRz.setObjectName(_fromUtf8(« lineEditRz »))
self.labelRotation = QtGui.QLabel(Form)
self.labelRotation.setGeometry(QtCore.QRect(340, 120, 81, 13))
self.labelRotation.setObjectName(_fromUtf8(« labelRotation »))
self.pushButtonRyMoins = QtGui.QPushButton(Form)
self.pushButtonRyMoins.setGeometry(QtCore.QRect(340, 170, 23, 20))
self.pushButtonRyMoins.setObjectName(_fromUtf8(« pushButtonRyMoins »))
self.lineEditRx = QtGui.QLineEdit(Form)
self.lineEditRx.setGeometry(QtCore.QRect(370, 140, 45, 20))
self.lineEditRx.setObjectName(_fromUtf8(« lineEditRx »))
self.pushButtonRyPlus = QtGui.QPushButton(Form)
self.pushButtonRyPlus.setGeometry(QtCore.QRect(420, 170, 23, 20))
self.pushButtonRyPlus.setObjectName(_fromUtf8(« pushButtonRyPlus »))
self.lcdNumberRx = QtGui.QLCDNumber(Form)
self.lcdNumberRx.setGeometry(QtCore.QRect(450, 140, 64, 20))
self.lcdNumberRx.setStyleSheet(_fromUtf8(« background-color: rgb(170, 255, 127);\n«
« color: rgb(0, 85, 0); »))
self.lcdNumberRx.setSegmentStyle(QtGui.QLCDNumber.Flat)
self.lcdNumberRx.setObjectName(_fromUtf8(« lcdNumberRx »))
self.labelRx = QtGui.QLabel(Form)
self.labelRx.setGeometry(QtCore.QRect(520, 150, 20, 13))
self.labelRx.setObjectName(_fromUtf8(« labelRx »))
self.labelRy = QtGui.QLabel(Form)
self.labelRy.setGeometry(QtCore.QRect(520, 180, 20, 13))
self.labelRy.setObjectName(_fromUtf8(« labelRy »))
self.lcdNumberRy = QtGui.QLCDNumber(Form)
self.lcdNumberRy.setGeometry(QtCore.QRect(450, 170, 64, 20))
self.lcdNumberRy.setStyleSheet(_fromUtf8(« background-color: rgb(170, 255, 127);\n«
« color: rgb(0, 85, 0); »))
self.lcdNumberRy.setSegmentStyle(QtGui.QLCDNumber.Flat)
self.lcdNumberRy.setObjectName(_fromUtf8(« lcdNumberRy »))
self.labelRz = QtGui.QLabel(Form)
self.labelRz.setGeometry(QtCore.QRect(520, 210, 20, 13))
self.labelRz.setObjectName(_fromUtf8(« labelRz »))
self.lcdNumberRz = QtGui.QLCDNumber(Form)
self.lcdNumberRz.setGeometry(QtCore.QRect(450, 200, 64, 20))
self.lcdNumberRz.setStyleSheet(_fromUtf8(« background-color: rgb(170, 255, 127);\n«
« color: rgb(0, 85, 0); »))
self.lcdNumberRz.setSegmentStyle(QtGui.QLCDNumber.Flat)
self.lcdNumberRz.setObjectName(_fromUtf8(« lcdNumberRz »))
self.lcdNumberTz = QtGui.QLCDNumber(Form)
self.lcdNumberTz.setGeometry(QtCore.QRect(450, 90, 64, 20))
self.lcdNumberTz.setStyleSheet(_fromUtf8(« background-color: rgb(170, 255, 127);\n«
« color: rgb(0, 85, 0); »))
self.lcdNumberTz.setSegmentStyle(QtGui.QLCDNumber.Flat)
self.lcdNumberTz.setObjectName(_fromUtf8(« lcdNumberTz »))
self.labelTx = QtGui.QLabel(Form)
self.labelTx.setGeometry(QtCore.QRect(520, 40, 20, 13))
self.labelTx.setObjectName(_fromUtf8(« labelTx »))
self.labelTz = QtGui.QLabel(Form)
self.labelTz.setGeometry(QtCore.QRect(520, 100, 20, 13))
self.labelTz.setObjectName(_fromUtf8(« labelTz »))
self.labelTy = QtGui.QLabel(Form)
self.labelTy.setGeometry(QtCore.QRect(520, 70, 20, 13))
self.labelTy.setObjectName(_fromUtf8(« labelTy »))
self.lcdNumberTx = QtGui.QLCDNumber(Form)
self.lcdNumberTx.setGeometry(QtCore.QRect(450, 30, 64, 20))
self.lcdNumberTx.setStyleSheet(_fromUtf8(« background-color: rgb(170, 255, 127);\n«
« color: rgb(0, 85, 0); »))
self.lcdNumberTx.setSegmentStyle(QtGui.QLCDNumber.Flat)
self.lcdNumberTx.setObjectName(_fromUtf8(« lcdNumberTx »))
self.lcdNumberTy = QtGui.QLCDNumber(Form)
self.lcdNumberTy.setGeometry(QtCore.QRect(450, 60, 64, 20))
self.lcdNumberTy.setStyleSheet(_fromUtf8(« background-color: rgb(170, 255, 127);\n«
« color: rgb(0, 85, 0); »))
self.lcdNumberTy.setSegmentStyle(QtGui.QLCDNumber.Flat)
self.lcdNumberTy.setObjectName(_fromUtf8(« lcdNumberTy »))
self.pushButtonRAZ = QtGui.QPushButton(Form)
self.pushButtonRAZ.setGeometry(QtCore.QRect(350, 230, 85, 20))
self.pushButtonRAZ.setObjectName(_fromUtf8(« pushButtonRAZ »))
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate(« Form », « pyqt + openGL : translation/rotation du repère 3D de base », None, QtGui.QApplication.UnicodeUTF8))
self.labelTranslation.setText(QtGui.QApplication.translate(« Form », « Translation : », None, QtGui.QApplication.UnicodeUTF8))
self.lineEditTx.setText(QtGui.QApplication.translate(« Form », « 10 », None, QtGui.QApplication.UnicodeUTF8))
self.pushButtonTxMoins.setText(QtGui.QApplication.translate(« Form », « -X », None, QtGui.QApplication.UnicodeUTF8))
self.pushButtonTxPlus.setText(QtGui.QApplication.translate(« Form », « +X », None, QtGui.QApplication.UnicodeUTF8))
self.pushButtonTyMoins.setText(QtGui.QApplication.translate(« Form », « -Y », None, QtGui.QApplication.UnicodeUTF8))
self.pushButtonTyPlus.setText(QtGui.QApplication.translate(« Form », « +Y », None, QtGui.QApplication.UnicodeUTF8))
self.lineEditTy.setText(QtGui.QApplication.translate(« Form », « 10 », None, QtGui.QApplication.UnicodeUTF8))
self.pushButtonTzMoins.setText(QtGui.QApplication.translate(« Form », « -Z », None, QtGui.QApplication.UnicodeUTF8))
self.pushButtonTzPlus.setText(QtGui.QApplication.translate(« Form », « +Z », None, QtGui.QApplication.UnicodeUTF8))
self.lineEditTz.setText(QtGui.QApplication.translate(« Form », « 10 », None, QtGui.QApplication.UnicodeUTF8))
self.pushButtonRxMoins.setText(QtGui.QApplication.translate(« Form », « -X », None, QtGui.QApplication.UnicodeUTF8))
self.lineEditRy.setText(QtGui.QApplication.translate(« Form », « 10 », None, QtGui.QApplication.UnicodeUTF8))
self.pushButtonRxPlus.setText(QtGui.QApplication.translate(« Form », « +X », None, QtGui.QApplication.UnicodeUTF8))
self.pushButtonRzMoins.setText(QtGui.QApplication.translate(« Form », « -Z », None, QtGui.QApplication.UnicodeUTF8))
self.pushButtonRzPlus.setText(QtGui.QApplication.translate(« Form », « +Z », None, QtGui.QApplication.UnicodeUTF8))
self.lineEditRz.setText(QtGui.QApplication.translate(« Form », « 10 », None, QtGui.QApplication.UnicodeUTF8))
self.labelRotation.setText(QtGui.QApplication.translate(« Form », « Rotation », None, QtGui.QApplication.UnicodeUTF8))
self.pushButtonRyMoins.setText(QtGui.QApplication.translate(« Form », « -Y », None, QtGui.QApplication.UnicodeUTF8))
self.lineEditRx.setText(QtGui.QApplication.translate(« Form », « 10 », None, QtGui.QApplication.UnicodeUTF8))
self.pushButtonRyPlus.setText(QtGui.QApplication.translate(« Form », « +Y », None, QtGui.QApplication.UnicodeUTF8))
self.labelRx.setText(QtGui.QApplication.translate(« Form », « Rx », None, QtGui.QApplication.UnicodeUTF8))
self.labelRy.setText(QtGui.QApplication.translate(« Form », « Ry », None, QtGui.QApplication.UnicodeUTF8))
self.labelRz.setText(QtGui.QApplication.translate(« Form », « Rz », None, QtGui.QApplication.UnicodeUTF8))
self.labelTx.setText(QtGui.QApplication.translate(« Form », « Tx », None, QtGui.QApplication.UnicodeUTF8))
self.labelTz.setText(QtGui.QApplication.translate(« Form », « Tz », None, QtGui.QApplication.UnicodeUTF8))
self.labelTy.setText(QtGui.QApplication.translate(« Form », « Ty », None, QtGui.QApplication.UnicodeUTF8))
self.pushButtonRAZ.setText(QtGui.QApplication.translate(« Form », « RAZ », None, QtGui.QApplication.UnicodeUTF8))
if __name__ == « __main__ »:
import sys
app = QtGui.QApplication(sys.argv)
Form = QtGui.QWidget()
ui = Ui_Form()
ui.setupUi(Form)
Form.show()
sys.exit(app.exec_())
Le fichier d’application *Main.py
# -*- coding: utf-8 -*-
# par X. HINAULT – Nov 2012 – Tous droits réservés
# GPLv3 – www.mon-club-elec.fr
# Implémentation de base d’OpenGL dans une interface Qt
# modules a importer
from PyQt4.QtGui import *
from PyQt4.QtCore import * # inclut QTimer..
from PyQt4.QtOpenGL import *
from OpenGL.GL import * # si format glfonction
#from OpenGL import GL # si format GL.glfonction
from OpenGL.GLU import * # librairie associée à OpenGL
#from OpenGL.GLUT import * # librairie associée à OpenGL
import os,sys
import math, random
from tuto_pyqt_openGL_repere_base_buttons import * # fichier obtenu à partir QtDesigner et pyuic4
# déclaration de variables globales
Tx=0 # variable translation courante axe des X
Ty=0 # variable translation courante axe des X
Tz=0 # variable translation courante axe des X
Rx=0 # variable rotation courante axe des X
Ry=0 # variable rotation courante axe des X
Rz=0 # variable rotation courante axe des X
class myApp(QWidget, Ui_Form): # la classe reçoit le Qwidget principal ET la classe définie dans test.py obtenu avec pyuic4
def __init__(self, parent=None):
QWidget.__init__(self) # initialise le Qwidget principal
self.setupUi(parent) # Obligatoire
# intégration d’opengl dans l’interface graphique QT designer
self.glWidget = myGLWidget() # déclare un objet de la classe locale issue de QGLWidget – voir ci-dessous
self.horizontalLayout.addWidget(self.glWidget) # ajoute le GLWidget au HLayout prévu dans QtDesigner
#Ici, personnalisez vos widgets si nécessaire
#– pushButton translation —
self.connect(self.pushButtonTxMoins, SIGNAL(« clicked() »), self.pushButtonTxMoinsClicked) # connecte le signal Clicked de l’objet bouton à l’appel de la fonction voulue
self.connect(self.pushButtonTyMoins, SIGNAL(« clicked() »), self.pushButtonTyMoinsClicked) # connecte le signal Clicked de l’objet bouton à l’appel de la fonction voulue
self.connect(self.pushButtonTzMoins, SIGNAL(« clicked() »), self.pushButtonTzMoinsClicked) # connecte le signal Clicked de l’objet bouton à l’appel de la fonction voulue
self.connect(self.pushButtonTxPlus, SIGNAL(« clicked() »), self.pushButtonTxPlusClicked) # connecte le signal Clicked de l’objet bouton à l’appel de la fonction voulue
self.connect(self.pushButtonTyPlus, SIGNAL(« clicked() »), self.pushButtonTyPlusClicked) # connecte le signal Clicked de l’objet bouton à l’appel de la fonction voulue
self.connect(self.pushButtonTzPlus, SIGNAL(« clicked() »), self.pushButtonTzPlusClicked) # connecte le signal Clicked de l’objet bouton à l’appel de la fonction voulue
#– pushButton rotation —
self.connect(self.pushButtonRxMoins, SIGNAL(« clicked() »), self.pushButtonRxMoinsClicked) # connecte le signal Clicked de l’objet bouton à l’appel de la fonction voulue
self.connect(self.pushButtonRyMoins, SIGNAL(« clicked() »), self.pushButtonRyMoinsClicked) # connecte le signal Clicked de l’objet bouton à l’appel de la fonction voulue
self.connect(self.pushButtonRzMoins, SIGNAL(« clicked() »), self.pushButtonRzMoinsClicked) # connecte le signal Clicked de l’objet bouton à l’appel de la fonction voulue
self.connect(self.pushButtonRxPlus, SIGNAL(« clicked() »), self.pushButtonRxPlusClicked) # connecte le signal Clicked de l’objet bouton à l’appel de la fonction voulue
self.connect(self.pushButtonRyPlus, SIGNAL(« clicked() »), self.pushButtonRyPlusClicked) # connecte le signal Clicked de l’objet bouton à l’appel de la fonction voulue
self.connect(self.pushButtonRzPlus, SIGNAL(« clicked() »), self.pushButtonRzPlusClicked) # connecte le signal Clicked de l’objet bouton à l’appel de la fonction voulue
self.connect(self.pushButtonRAZ, SIGNAL(« clicked() »), self.pushButtonRAZClicked) # connecte le signal Clicked de l’objet bouton à l’appel de la fonction voulue
#Réalisez les connexions supplémentaires entre signaux et slots
# autres objets à déclarer à l’initialisation
#self.timer=QTimer() # déclare un QTimer
#self.timer.start(10) # démarre le QTimer à n ms
#self.connect(self.timer, SIGNAL(« timeout() »), self.timerEvent) # connecte le signal timeOut de l’objet timer à l’appel de la fonction voulue
# les fonctions appelées, utilisées par les signaux
#def timerEvent(self): # fonction appelée lors de la survenue d’un évènement Timer – nom fonction indiférrent
#print(« Timer »)
#self.glWidget.update() # actualise le dessin openGl
#======== fonctions des pushButton =========
# — pushButton translation
def pushButtonTxMoinsClicked(self):
print(« Bouton Tx Moins appuyé »)
global Tx
Tx=Tx-int(self.lineEditTx.text())
self.lcdNumberTx.display(Tx) # MAJ des lcdNumber
self.glWidget.update() # actualise le dessin openGl
def pushButtonTyMoinsClicked(self):
print(« Bouton Ty Moins appuyé »)
global Ty
Ty=Ty-int(self.lineEditTy.text())
self.lcdNumberTy.display(Ty) # MAJ des lcdNumber
self.glWidget.update() # actualise le dessin openGl
def pushButtonTzMoinsClicked(self):
print(« Bouton Tz Moins appuyé »)
global Tz
Tz=Tz-int(self.lineEditTz.text())
self.lcdNumberTz.display(Tz) # MAJ des lcdNumber
self.glWidget.update() # actualise le dessin openGl
def pushButtonTxPlusClicked(self):
print(« Bouton Tx Plus appuyé »)
global Tx
Tx=Tx+int(self.lineEditTx.text())
self.lcdNumberTx.display(Tx) # MAJ des lcdNumber
self.glWidget.update() # actualise le dessin openGl
def pushButtonTyPlusClicked(self):
print(« Bouton Ty Plus appuyé »)
global Ty
Ty=Ty+int(self.lineEditTy.text())
self.lcdNumberTy.display(Ty) # MAJ des lcdNumber
self.glWidget.update() # actualise le dessin openGl
def pushButtonTzPlusClicked(self):
print(« Bouton Tz Plus appuyé »)
global Tz
Tz=Tz+int(self.lineEditTz.text())
self.lcdNumberTz.display(Tz) # MAJ des lcdNumber
self.glWidget.update() # actualise le dessin openGl
# — pushButton Rotation
def pushButtonRxMoinsClicked(self):
print(« Bouton Rx Moins appuyé »)
global Rx
Rx=Rx-int(self.lineEditRx.text())
self.lcdNumberRx.display(Rx) # MAJ des lcdNumber
self.glWidget.update() # actualise le dessin openGl
def pushButtonRyMoinsClicked(self):
print(« Bouton Ry Moins appuyé »)
global Ry
Ry=Ry-int(self.lineEditRy.text())
self.lcdNumberRy.display(Ry) # MAJ des lcdNumber
self.glWidget.update() # actualise le dessin openGl
def pushButtonRzMoinsClicked(self):
print(« Bouton Rz Moins appuyé »)
global Rz
Rz=Rz-int(self.lineEditRz.text())
self.lcdNumberRz.display(Rz) # MAJ des lcdNumber
self.glWidget.update() # actualise le dessin openGl
def pushButtonRxPlusClicked(self):
print(« Bouton Rx Plus appuyé »)
global Rx
Rx=Rx+int(self.lineEditRx.text())
self.lcdNumberRx.display(Rx) # MAJ des lcdNumber
self.glWidget.update() # actualise le dessin openGl
def pushButtonRyPlusClicked(self):
print(« Bouton Ry Plus appuyé »)
global Ry
Ry=Ry+int(self.lineEditRy.text())
self.lcdNumberRy.display(Ry) # MAJ des lcdNumber
self.glWidget.update() # actualise le dessin openGl
def pushButtonRzPlusClicked(self):
print(« Bouton Rz Plus appuyé »)
global Rz
Rz=Rz+int(self.lineEditRz.text())
self.lcdNumberRz.display(Rz) # MAJ des lcdNumber
self.glWidget.update() # actualise le dessin openGl
def pushButtonRAZClicked(self):
print(« Bouton RAZ appuyé »)
global Tx,Ty,Tz,Rx,Ry,Rz
Tx=0
Ty=0
Tz=0
Rx=0
Ry=0
Rz=0
self.lcdNumberTx.display(Tx) # MAJ des lcdNumber
self.lcdNumberTy.display(Ty) # MAJ des lcdNumber
self.lcdNumberTz.display(Tz) # MAJ des lcdNumber
self.lcdNumberRx.display(Rx) # MAJ des lcdNumber
self.lcdNumberRy.display(Ry) # MAJ des lcdNumber
self.lcdNumberRz.display(Rz) # MAJ des lcdNumber
self.glWidget.update() # actualise le dessin openGl
#– fin de la classe principale myApp
class myGLWidget(QGLWidget): # classe locale issue de QGLWidget et redéfinissant les fonctions virtuelles du QGLWidget
def __init__(self, parent=None): # constructeur
QGLWidget.__init__(self, parent) # base la classe locale sur la classe QGLWidget
#ici les fonctions propres du QGLWidget local
def paintGL(self): # fonction de rafraîchissement – doit être appelée par updateGL() via QTimer au besoin
print(« Mise à jour fenêtre OpenGL »)
global Tx,Ty,Tz,Rx,Ry,Rz
# RAZ des angles
if Rx>359:
Rx=0
if Ry>359:
Ry=0
if Rz>359:
Rz=0
print(« Tx: »+str(Tx)+ » Ty: »+str(Ty)+ » Tz: »+str(Tz)+ » Rx: »+str(Rx)+ » Ry: »+str(Ry)+ » Rz: »+str(Rz))
#—- paramètres généraux —-
#——- fixe la couleur de fond de la fenêtre —–
glClearColor(0.0, 0.0, 0.0, 1.0) # couleur d’arrière plan
glClear(GL_COLOR_BUFFER_BIT) # efface le fond
#glEnable(GL_DEPTH_TEST) # active le test de profondeur pour éviter voir faces cachées
#——– définition de la perspective utilisée —–
glMatrixMode(GL_PROJECTION) # sélectionne la matrice de projection
glLoadIdentity() # charge la matrice identité
print(« Matrice de projection : »)
print (glGetFloatv( GL_PROJECTION_MATRIX )) # affiche la matrice de projection courante
#gluPerspective( angle, ratio, near, far )
gluPerspective( 60, 320.0/240.0, 0, –1000 ) # définit la perspective
print(« Matrice de projection : »)
print (glGetFloatv( GL_PROJECTION_MATRIX )) # affiche la matrice de projection courante
#—- définition de l’angle de vue de la caméra —-
# par défaut la caméra se trouve en 0,0,0 et regarde vers l’axe Z-
#gluLookAt (0.0, 0.0, 0.0, 0.0, 0.0, -100.0, 0.0, 1.0, 0.0) # valeur par défaut
#gluLookAt (0.0, 0.0, -200, 0.0, 0.0, -1000.0, 0.0, 1.0, 0.0) # positionne la caméra
#— fixe la taille de la fenêtre de visualisation
glViewport(0, 0, 320, 240) # fixe l’origine et la taille de la fenêtre de visualisation
# utiliser un ratio idem celui de la perspective
# utiliser la même taille que la fenêtre d’affichage à l’écran
#——– dessin du modèle 3D —–
glMatrixMode(GL_MODELVIEW) # sélectionne la matrice de vue du modèle
glLoadIdentity() # charge la matrice identité
# sinon c’est la matrice courante qui est utilisée et les modif s’ajoutent aux modif déjà réalisées
print(« Matrice de vue du modèle : »)
print (glGetFloatv( GL_MODELVIEW_MATRIX )) # affiche la matrice courante
# — positionnement du repère de la fenêtre de visualisation
self.Zo=-207.84 # définition de la valeur Zo
# Zo est en fait la position en Z telle que x,y correspondent à la taille de la fenêtre de l’écran…
glTranslate(0+Tx,0+Ty,self.Zo+Tz) # translation en (0,0,Zo)
glRotate(Rx,1,0,0) # rotation axe X
glRotate(Ry,0,1,0) # rotation axe Y
glRotate(Rz,0,0,1) # rotation axe Z
#– réaffichage des matrices avant de dessiner —
print(« Matrice de projection : »)
print (glGetFloatv( GL_PROJECTION_MATRIX )) # affiche la matrice courante avant dessin
print(« Matrice de vue du modèle : »)
print (glGetFloatv( GL_MODELVIEW_MATRIX )) # affiche la matrice courante avant dessin
# — dessine le point O(0,0,0)
glPointSize(5) # fixe la taille des points
glBegin(GL_POINTS) # début du dessin – mode lignes
glColor3ub(255,255,0) # jaune
glVertex3d(0,0,0)
glEnd()
# dessin à réaliser
glColor3ub(255,255,0) # jaune
#gluSphere(self.quadratic,1,20,20) # tracé d’une sphère
gluDisk(self.quadratic,0,75,24,10) # tracé d’un disque
#gluPartialDisk(self.quadratic,0,75,16,10,60,240)
# — dessine le repère 3D Oxyz – en dernier = par dessus le reste
glBegin(GL_LINES) # début du dessin – mode lignes
taille=100
# Ox
glColor3ub(255,0,0) # rouge
glVertex3d(0,0,0)
glVertex3d(taille,0,0)
# Oy
glColor3ub(0,255,0) # vert
glVertex3d(0,0,0)
glVertex3d(0,taille,0)
# Oz
glColor3ub(0,0,255) # bleu
glVertex3d(0,0,0)
glVertex3d(0,0,taille)
glEnd() # fin du dessin
def resizeGL(self, w, h): # fonction appelée pour redimensionnement (et au 1er lancement)
# et lors de chaque recouvrement de la fenêtre par une autre, etc…
print(« Redimensionnement fenêtre OpenGL »)
def initializeGL(self): # fonction d’initialisation de la fenêtre openGL
print(« Initialisation openGL »)
# déclaration d’un objet quadrique
self.quadratic = gluNewQuadric() # déclaration d’un quadratique = forme 3D
gluQuadricDrawStyle(self.quadratic,GLU_LINE) # fixe le mode de dessin
#gluQuadricDrawStyle(self.quadratic,GLU_FILL) # fixe le mode de dessin
# gestion des évènements
def mousePressEvent(self, event):
print(« Appui souris »)
#self.updateGL() # appelle paintGL
# fin class myGLWidget
# code rendant l’application exécutable
def main(args):
a=QApplication(args) # crée l’objet application
f=QWidget() # crée le QWidget racine
c=myApp(f) # appelle la classe contenant le code de l’application
f.show() # affiche la fenêtre QWidget
r=a.exec_() # lance l’exécution de l’application
return r
if __name__==« __main__ »: # pour rendre le code exécutable
main(sys.argv) # appelle la fonction main
Utilisation
- Les 2 fichiers suivants sont à enregistrer dans un même répertoire, l’un en nom.py et l’autre en nomMain.py.
- Puis lancer l’application depuis Geany ou équivalent, en exécutant le fichier nomMain.py
Articles similaires:
- PyQt Lab’ : Graphiques Math : Pyqtgraph : Afficher un graphique Pyqtgraph vide avec des widgets de paramétrage.
- PyQt Lab’ : Graphiques Math : Afficher un graphique Pyqtgraph vide
- PyQt Lab’ : Graphiques Math : Pyqtgraph : Afficher/masquer des courbes dans un graphique Pyqtgraph à l’aide widgets checkbox.
- PyQt Lab’ : Graphiques Math : Pyqtgraph : Affichage progressif d’une courbe dans un graphique Pyqtgraph avec bouton de Stop, bouton Effacer, bouton réglage vitesse et lcdNumber d’affichage.
- PyQt Lab’ : Graphiques Math : Pyqtgraph : Interagir avec une courbe d’un graphique pyqtgraph à l’aide de sliders.
Articles Liés
- jQuery :
jQuery est une bibliothèque JavaScript open source très populaire qui permet aux développeurs web de…
- Javascript : Graphique Dygraphs simple
Le Javascript est un langage de programmation très populaire et puissant qui permet aux développeurs…
- Javascript : Graphique Dygraphs simple : fixer la taille du graphique
Le Javascript est un langage de programmation très populaire et puissant qui permet aux développeurs…