6 PyQtIntro Ihm Lille
6 PyQtIntro Ihm Lille
6 PyQtIntro Ihm Lille
Sylvain Malacria
http://www.malacria.com/
mailto:[email protected]
http://pyqt.sourceforge.net/Docs/PyQt5/
Qu’est ce que Qt ?
Multi-Plateforme
‣ Windows | Mac | Linux
‣ Android | iOS | WinRT | BlackBerry* | SailFish
‣ Embedded Linux | Embedded Android | Windows Embedded
Performance (C++)
Relativement Simple
Gratuit (GPL) et code source
Nombreux outils
‣ Générateur d’interface : Qt Designer
‣ Internationalisation : Qt Linguist
‣ Documentation : Qt Assistant Qt creator
‣ Examples : Qt Examples
‣ Programmation : Qt Creator (eclipse)
Multi-Plateformes
‣ Look and feel simulé
Designer
Aujourd’hui
Utilisateurs de Qt :
‣ ESA, Nokia, Nasa, Adobe, Motorola, Google, …
Qt Widgets
Aujourd'hui
v.s.
v.s.
v.s.
int a = 4
a=4
type(a) <class 'int'>
a = 4.1
type(a) <class 'float'>
Quelques types de base
Booléen
Numériques
‣ int
‣ long
‣ float
‣ complex
Collections
‣ list
‣ tuple
‣ set
‣ dict
‣ etc.
Quelques types de base
Booléen
Numériques
list1 = ['physics','chemistry',1200]
‣ int print(list1[0])
‣ long
‣ float >>> ‘physics’
‣ complex
list1.append("bla")
Collections print(list1[3])
‣ list
‣ tuple >>> ‘bla’
‣ set
‣ dict
print(list1[1:3])
‣ etc.
Booléen
Numériques
list1 = ['physics','chemistry',1200]
‣ int print(list1[0])
‣ long
‣ float >>> ‘physics’
‣ complex
list1.append("bla")
Collections print(list1[3])
‣ list
‣ tuple >>> ‘bla’
‣ set
‣ dict
print(list1[1:3])
‣ etc.
alphabetT2 = ‘a’,’b','c','d',('e','é','è'),'f','g','h','i','j','k'
len(alphabetT2[4])
>>> 3
for i in range(2,len(alphabetT)):
print(alphabetT[i])
Entrées/Sorties fichiers
http://pyqt.sourceforge.net/Docs/PyQt5/
Les principaux modules
QtCore
QtWidgets
QtGUI
QtBluetooth
QtOpenGL
QtSript/QtScriptTools
QtSql
QtSvg
QtWebKit
QtXml/QtXmlPatterns
QtMultimedia
QtSensors
Module QtCore
QObject
Type de base :
‣ QChar, QDate, QString, QStringList, Qtime,…
File systems :
‣ QDir, QFile,…
Container :
‣ QList, Qmap, Qpair, QSet, QVector,…
Graphique :
‣ QLine, Qpoint, QRect, QSize …
Thread :
‣ QThread, Qmutex, …
Autres :
‣ QTimer, …
QString
QTimer QWidget
QLabel QLineEdit
Module QtWidgets
Qwidget QComboBox
QPushButton QSlider
QLabel QProgressBar
QCheckBox QTabBar
QRadioButton QMenu
QTableView QTreeView
Arbre d’héritage
vs.
arbre d’instanciation
Arbres d’heritage
QObject
QTimer QWidget
QLabel QLineEdit
Principaux widgets
Arbre d’heritage
QCheckBox
QToolButton
QPushButton
Arbre d’instanciation
Si le parent d’un Widget est nul, le Widget est une fenêtre (Window).
Que font les parents ?
‣ Ils ont une liste des enfants
‣ Ils détruisent automatiquement les enfants quand ils sont détruits
‣ Enable/disable les enfants quand ils enable/disable eux memes
‣ Pareil pour Show/Hide
Arbre d’instanciation
def main(args) :
app = QApplication(args)
button = QPushButton("Hello World !", None)
button.resize(100,30)
button.show()
app.exec_()
if __name__ == "__main__":
main(sys.argv)
Simple window with button in widget
def main(args) :
app = QApplication(args)
widget = QWidget(None)
widget.resize(400,90)
button = QPushButton("Hello World !", widget)
button.resize(100,30)
widget().show()
app.exec_()
if __name__ == "__main__":
main(sys.argv)
Signaux et slots
Solutions:
‣ MFC (introduit un langage au dessus de C++)
‣ Java (utilise des listeners)
‣ Qt (utilise principalement des signaux et slots)
Application algorithmique
Programmation “classique” :
‣ Programme principal initialise et appelle des fonctions dans un ordre pre-déterminé
‣ Les éventuels évènements utilisateurs sont « demandés » (programme en pause)
Programmation “événementielle” :
‣ Programme principal initialise des variables et les fonctions réagissent aux
événements
‣ Le déroulement est contrôlé par la survenue d’événements
(dont les actions de l’utilisateur)
‣ Boucle principale qui traite les événements (enfouie dans la bibliothèque)
Quels évènements?
Actions utilisateurs
Notifications de processus (applications, OS, MAJ)
Capteurs sensorielles (info ubiquitaire)
while (true){
if(!queue.isEmpty()){
event = queue.nextEvent();
source = findSourceForEvent(event);
source.processEvent(event);
}
}
42
Signal émis
Connecter signaux et slots
42 42
Signal émis
Slot implémenté
Connecter signaux et slots
42 connexion 42
Signal émis
Slot implémenté
slider.valueChanged.connect(lcd.display)
Connecter signaux et slots
class QSlider(QObject):
….
def mousePressEvent(self)
self.valueChanged.emit(value)
…
slider = QSlider(None)
42 connexion 42
Signal émis
Slot implémenté
slider.valueChanged.connect(lcd.display)
Connecter signaux et slots
class QLCDNumber(QObject):
def display(num)
m_value = num;
…
lcd = QLCDNumber(None)
42 connexion 42
Signal émis
Slot implémenté
slider.valueChanged.connect(lcd.display)
Une classe avec des signaux et des slots
class MyClass(QObject):
mySignal = pyqtSignal(int)
class MyClass(QObject):
mySignal = pyqtSignal(int)
@pyqtSlot(int)
def mySlot( num ): parfois nécessaire
blabla
Modularité, flexibilité
‣ Connecter plusieurs signaux à un slot
‣ Connecter un signal à plusieurs slots
Philosophie
‣ L’émetteur n’a pas besoin de connaître le(s) récepteur(s)
‣ L’émetteur ne sait pas si le signal a été reçu
‣ Le récepteur ne connaît pas non plus l’émetteur
‣ Programmation par composant (indépendant, réutilisable)
class PunchingBag(QObject):
punched = pyqtSignal() Signal
def __init__(self):
# Initialize the PunchingBag as a QObject
QObject.__init__(self)
@pyqtSlot()
def say_punched():
print('Bag was punched.')
def main(args):
bag = PunchingBag()
# Connect the bag's punched signal to the say_punched slot
bag.punched.connect(say_punched) Connexion
# Punch the bag 10 times
for i in range(10):
bag.punch()
if __name__ == "__main__":
main(sys.argv)
Questions
def main(args) :
app = QApplication(args)
widget = QWidget(None)
widget.resize(400,90)
button = QPushButton("Hello World !", widget)
button.resize(100,30)
button.clicked.connect(app.quit)
widget().show()
app.exec_()
if __name__ == "__main__":
main(sys.argv)
Les principaux modules
QtCore
QtWidgets
QtGUI
QtBluetooth
QtOpenGL
QtSript/QtScriptTools
QtSql
QtSvg
QtWebKit
QtXml/QtXmlPatterns
QtMultimedia
QtSensors
QStyle
class Win(QMainWindow):
def __init__(self):
self.resize(200,300)
QMainWindow
Menus
fileMenu.addAction(newAct)
newAct.triggered.connect( self.open )
QMainWindow
QToolTip, QWhatsThis
Composant central
textEdit = TextEdit( self );
self.setCentralWidget( textEdit );
Buttons
Input Widgets
Containers
QToolBox
QScrollArea
QCompleter
standard widgets use data that is part of the widget
def main(args):
app = QApplication(args)
tableView = QTableView()
myModel = MyModel()
tableView.setModel( myModel )
tableView.show()
app.exec()
Display Widgets
Boites de dialogue
QProgressDialog
QFileDialog
QMessageBox
QColorDialog QFontDialog
Boîte de dialogue modale
Solution simplifiée
Problèmes
‣ internationalisation
‣ redimensionnement
‣ complexité du code
Layout
QFormLayout
QHBoxLayout
QVBoxLayout QGridLayout
Layout
Exemple
v_layout = QVBoxLayout( )
v_layout.addWidget( QPushButton( "OK" ) )
v_layout.addWidget( QPushButton( "Cancel" ) )
v_layout.addStretch( )
v_layout.addWidget( QPushButton( "Help" ) )
country_list = QListBox( );
countryList.insertItem( "Canada" );
...etc...
h_layout = QHBoxLayout( )
h_layout.addWidget( country_list )
h_layout.addLayout( v_layout )
top_layout = QVBoxLayout( )
top_layout.addWidget( QLabel( "Select a country" ) )
top_layout.addLayout( h_layout );
container = QWidget()
container.setLayout( top_layout )
win.setCentralWidget(container)
win.show( ) Notes sur layouts :
- peuvent être emboîtés
- cf. le « stretch »
Layout
Exemple
v_layout = QVBoxLayout( )
v_layout.addWidget( QPushButton( "OK" ) )
v_layout.addWidget( QPushButton( "Cancel" ) )
v_layout.addStretch( )
v_layout.addWidget( QPushButton( "Help" ) )
country_list = QListBox( );
countryList.insertItem( "Canada" );
...etc...
h_layout = QHBoxLayout( )
h_layout.addWidget( country_list )
h_layout.addLayout( v_layout )
top_layout = QVBoxLayout( )
top_layout.addWidget( QLabel( "Select a country" ) )
top_layout.addLayout( h_layout );
container = QWidget()
container.setLayout( top_layout )
win.setCentralWidget(container)
win.show( ) Notes sur layouts :
- peuvent être emboîtés
- cf. le « stretch »
Layout
Exemple
v_layout = QVBoxLayout( )
v_layout.addWidget( QPushButton( "OK" ) )
v_layout.addWidget( QPushButton( "Cancel" ) )
v_layout.addStretch( )
v_layout.addWidget( QPushButton( "Help" ) )
country_list = QListBox( );
countryList.insertItem( "Canada" );
...etc...
h_layout = QHBoxLayout( )
h_layout.addWidget( country_list )
h_layout.addLayout( v_layout )
top_layout = QVBoxLayout( )
top_layout.addWidget( QLabel( "Select a country" ) )
top_layout.addLayout( h_layout );
container = QWidget()
container.setLayout( top_layout )
win.setCentralWidget(container)
win.show( ) Notes sur layouts :
- peuvent être emboîtés
- cf. le « stretch »
Layout
Exemple
v_layout = QVBoxLayout( )
v_layout.addWidget( QPushButton( "OK" ) )
v_layout.addWidget( QPushButton( "Cancel" ) )
v_layout.addStretch( )
v_layout.addWidget( QPushButton( "Help" ) )
country_list = QListBox( );
countryList.insertItem( "Canada" );
...etc...
h_layout = QHBoxLayout( )
h_layout.addWidget( country_list )
h_layout.addLayout( v_layout )
top_layout = QVBoxLayout( )
top_layout.addWidget( QLabel( "Select a country" ) )
top_layout.addLayout( h_layout );
container = QWidget()
container.setLayout( top_layout )
win.setCentralWidget(container)
win.show( ) Notes sur layouts :
- peuvent être emboîtés
- cf. le « stretch »