Tworzenie interfejsów graficznych w QtDesigner dla aplikacji PyQt4
19 October 2009
Comments
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").
Tworzenie interfejsu w QtDesigner
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
Oprogramowanie interfejsu
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_())
- 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:
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.
# -*- 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_())
- 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 :)
Kod źródłowy
RkBlog
Comment article