Qt Designer to aplikacja dostarczana wraz z biblioteką Qt służąca do tworzenia interfejsów użytkownika naszych aplikacji. Za pomocą przeciągania widżetów z dostępnej palety możemy umieścić wszystkie potrzebne elementy. Co ważne możemy także zadbać o rozmieszczenie poszczególnych widżetów za pomocą szablonów (
Layouts), jak i o nadanie etykiet i domyślnych ustawień poszczególnym widgetom. W tym artykule opiszę tworzenie proste interfejsu prezentującego proces poprawnego tworzenia interfejsu w QtDesignerze.
W przypadku Windowsa QtDesigner będzie dostępny po zainstalowaniu PyQt4. W przypadku Linuksa będzie w pakiecie Qt, lub np. w przypadku Ubuntu, które stosuje rozbite pakiety - jako oddzielny pakiet (szukaj "designer").
Naszym celem będzie stworzenie prostej aplikacji, która będzie startowała pasek postępu przyrastający co sekundę:
Trzy przyciski
QPushButton (Start, Stop, Exit) odpowiednio do uruchamiania i zatrzymywania paska postępu, oraz do zamykania aplikacji. Do tego jeden
QProgressBar.
- Otwieramy Qt Designera i tworzymy nowy Widget:
-
Z menu po lewej przeciągamy trzy przyciski ("Push Button") i jeden pasek postępu ("Progress Bar").
- Klikając na przycisk możemy edytować tekst jaki wyświetla. Gdy zaznaczymy jakiś widget na oknie - w menu po prawej stronie pojawią się jego ustawienia. W przypadku QProgressBar znajdziemy ustawienia określające startową wartość (mamy 24, a wypada zmienić na 0):
Zmieniamy nazwy na przyciskach, a także startową wiadomość paska postępu.
- Każdy widżet ma swoją unikalną etykietę, po której w kodzie można go identyfikować i wykorzystywać. Warto nazwać wszystkie używane widgety spójnie i zgodnie z ich funkcją/przeznaczeniem. Etykietę zmieniamy w menu ustawień:
Przycisk "Start" nazwałem "startButton", "Stop" - "stopButton", "Exit" - "exitButton". Pasek postępu pozostał jako "progressBar".
- Interfejs mamy już gotowy jeżeli chodzi o zawartość. W menu górnym możesz sprawdzić wygląd zaprojektowanego okna: Formularz - Podgląd. Spróbuj rozszerzyć wyświetlone okno. Zobaczysz efekt tego typu:
Widgety nie skalują się wraz z oknem. By widżety skalowały się i odpowiednio układały się w oknie należy zastosować Layout ("szablon"). Taki szablon możemy (i zazwyczaj to robimy) ustawić dla danego okna wybierając szablon z górnego menu QtDesignera
Mamy odpowiednio poziomy i pionowy szablon (rozmieszcza odpowiednio widżety jeden po drugim i jeden pod drugim), następnie poziomy i pionowy Splitter (użytkownik może później przesuwać granicę podziału). Ostatni szablon do "grid" umożliwiający rozmieścić szablony w poziomie i pionie. Te same szablony można także wykorzystywać do zgrupowania kilku widżetów.
- Zaznacz obecne trzy przyciski (klikaj na nie z wciśniętym klawiszem CTRL) a następnie kliknij na poziomy szablon (pierwszy):
Przyciski zostały zgrupowane w szablonie. Teraz nie mając zaznaczonego żadnego widżeta wybierz szablon pionowy (drugi) - by ustawić go dla całego okna. Oto efekt:
Przyciski skalują się do równych długości, jak i też szablon zajmuje całą wolną wysokość.
- Do dopasowywania skalowania się widgetów możemy użyć "wirtualnych" widżetów "Spacers" ("odstępy"):
Wstaw poziomy odstep między przyciskiem Stop a Exit:
A pionowy pod paskiem postępu:
- Teraz widżety w naszym oknie będą płynnie skalowały się wraz z rozmiarem okna:
Interfejs jest gotowy i można przystąpić do jego oprogramowania. Zapisz interfejs w pustym katalogu jako np. counter.ui
Zakładam że przerobiłeś już pierwsze tutoriale opisujące podstawy programowania w PyQt4. Zaczynamy od wygenerowania klasy Pythona z pliku UI:
pyuic4 counter.ui > counter.py
Następtnie tworzymy plik
run.py z takim oto szkieletowym kodem:
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui
from counter import Ui_CounterWindow
class MyCounter(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_CounterWindow()
self.ui.setupUi(self)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyCounter()
myapp.show()
sys.exit(app.exec_())
Gdzie
from counter import Ui_CounterWindow to import klasy naszego okna z pliku
counter.py. Otwierając ten plik zdobędziemy nazwę klasy (Ui_CounterWindow w tym przypadku). Będzie to nazwa wg. schematu "Ui_etykietaOkna". Uruchom plik
run.py - powinno wyświetlić się okno.
- Zaczynamy od połączenia sygnału kliknięcia w przycisk z własnym slotem - metodą wykonującą określony kod. Oto rozwinięty kod szkieletu:
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui
from counter import Ui_CounterWindow
class MyCounter(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_CounterWindow()
self.ui.setupUi(self)
QtCore.QObject.connect(self.ui.startButton,QtCore.SIGNAL("clicked()"), self.start)
QtCore.QObject.connect(self.ui.stopButton,QtCore.SIGNAL("clicked()"), self.stop)
QtCore.QObject.connect(self.ui.exitButton,QtCore.SIGNAL("clicked()"), self.close_app)
def start(self):
"""
Start the counter
"""
print 'start'
def stop(self):
"""
Stop the counter
"""
print 'stop'
def close_app(self):
"""
Close the app
"""
app.exit()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyCounter()
myapp.show()
sys.exit(app.exec_())
Metoda close_app zostanie wywołana po kliknięciu na przycisk "Exit". Sygnał kliknięcia (clicked()) został połączony z tą metodą za pomocą QtCore.QObject.connect. Przycisk określony jest jako self.ui.exitButton, gdzie exitButton to etykieta widżeta ustawiona przez nas w Qt Designerze. Podobnie połączyłem pozostałe dwa przyciski. Na razie metody wypisują tekst w konsoli gdy przycisk został kliknięty.
- By stworzyć ładnie postępujący stan paska postępu użyję Stoperów opisanych w podlinkowanym artykule.
- Oto gotowy kod pliku run.py:
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui
from counter import Ui_CounterWindow
class MyCounter(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_CounterWindow()
self.ui.setupUi(self)
QtCore.QObject.connect(self.ui.startButton,QtCore.SIGNAL("clicked()"), self.start)
QtCore.QObject.connect(self.ui.stopButton,QtCore.SIGNAL("clicked()"), self.stop)
QtCore.QObject.connect(self.ui.exitButton,QtCore.SIGNAL("clicked()"), self.close_app)
# stoper
self.progress_timer = QtCore.QTimer()
QtCore.QObject.connect(self.progress_timer, QtCore.SIGNAL("timeout()"), self.progress_update)
def progress_update(self):
"""
Update the progress bar
"""
val = self.ui.progressBar.value() + 10
if val <= 100:
self.ui.progressBar.setValue(val)
else:
self.progress_timer.stop()
def start(self):
"""
Start the counter
"""
print 'start'
self.progress_timer.start(1000)
def stop(self):
"""
Stop the counter
"""
print 'stop'
self.progress_timer.stop()
def close_app(self):
"""
Close the app
"""
app.exit()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyCounter()
myapp.show()
sys.exit(app.exec_())
- Metoda start uruchamia stoper, który co 1 sekundę będzie wywoływał metodę progress_update, która to o 10% zwiększy postęp paska postępu :)
- Dodane: 19.10.2009 przez riklaunim