Wer mit Qt arbeitet der hat sich früher oder später schon mal gefragt wie erstelle ich
ein eigenes Steuerelement und/oder wie zeige ich meine eigene Grafik in meiner GUI an.
Eins vorweg ich arbeit mit Visual Studio und dem Plugin dafür inklusive des Qt-Designers.
Mit dem Qt-Creator sollten die hier Beschriebenen Schritte jedoch ähnlich ablaufen.
In diesem Artikel möchte ich euch zeigen wie einfach es sein kann sowas zu realisieren
und wie man das Steuerelement direkt im Qt Designer platziert. Im Bild rechts sieht man
einen Schalter der ein Volumenmeter, welches auch von Windows verwendet wird um
die Sound- ausgabe zu visualisieren, steuert. Die Programmierung von diesem wird
im folgendem erklärt.
Zunächst erstellen wir uns eine von QWidget abgeleitete Klasse namens QVolumeMeter und deklarieren uns die virtuelle Funktion paintEvent. Diese Funktion wird von der Elternklasse immer dann aufgerufen wenn das Steuerelement gezeichnet werden soll. Die Header-Datei sollte dann in etwa so aussehen:
Nun sollte man sich zunächst Gedanken machen wie man das was Dargestellt werden soll am besten intern Beschreibt. Ich habe wie es für die meisten Fortschrittsanzeigen gemacht wird mir drei Variablen angelegte mit Start, Stop und Position, jeweils mit dem Typ float. An dieser Stelle ist es relativ egal welchen Typ ihr nehmt ihr solltet nur beachten dass ihr die Verwendete Typen richtig für eure Funktion interpretiert. Nun definieren wir für diese Variablen wie es sich gehört jeweils drei sogenannte Getter und Setter Funktionen mit denen man die Werte auslesen und beschreiben kann. Die Getter Funktionen sollten in diesem Fall klar sein, sie geben einfach den aktuell eingestellten Wert wieder zurück. Die Setter Funktionen führen jedoch in meinem Fall noch die Prüfung der übergebenen Werte durch, zb. damit der Stop-Wert sich nicht vor dem Start-Wert befindet und umgekehrt. Eine mögliche Implementierung könnte dann so aussehen (ich habe für stop und start hier min un max verwendet):
Man beachte bei jeder Funktion den letzten Befehl update. Was macht nun dieser Befehl? Es gibt neben update noch den Befehl repaint. Der unterschied zwischen beiden ist, dass repaint das Steuerelement sofort neu zeichnet, update hingegen das Neuzeichnen in „Auftrag“ gibt, sodass wenn mehrere update Befehle eingehen das Steuerelement nur einmal neu gezeichnet wird. Warum benutz ich hier nun update anstelle von repaint? Ganz einfach, wenn man mehrmals diese Funktionen innerhalb einer Aktion aufruft, soll sich das Steuerelement möglichst erst nach dem letzten update Aufruf neu zeichnen um alle neuen Informationen anzuzeigen. Würde man den Befehl repaint verwenden würde dies das Steuerelement jedesmal zum Neuzeichnen veranlassen und das Programm zum stocken bringen, da das Neuzeichnen eines Steuerelementes im vergleich viel Rechenleistung beansprucht. Von daher sollte man darauf achten, dass man das Steuerelement auch nur dann neue Zeichnet wenn es nötig ist.
Kommen wir endlich zum Zeichnen des Steuerelements. Da ich an dieser Stelle ein fertiges Bild auf das Steuerelement male ist die Zeichenroutine auch relativ simple. Ich habe das Bild als Qt-Ressource eingebunden und lade dieses im Konstruktor des eigenen Steuerelements:
Ich möchte an diese Stelle hinweisen, dass wenn man mehrere Steuerelemente der selben eigenen Klasse verwendet sich dann eine Hilfsklasse schreiben sollte um die Bilder besser zu verwalten, da sonst für jedes Steuerelement das selbe Bild immer wieder geladen wird.
Schließlich wird das Bild in der Zeichenfunktion mit Hilfe eines QPainter
Objekts auf das Steuerelement gezeichnet:
Mein Bild besteht aus zwei Hälften, die eine Hälfte zeigt den gefüllten Status und die andere den Ungefühlten Status. Die Berechnung oben in der Zeichenfunktion mixt die zwei Hälften jeweils zu einem zusamen sodass man eine Trennung der Hellen und dunklen Flächen erhält und damit eine Art Höhenanzeige.
Um nun das Steuerelement im Qt Designer verwenden zu können deklariere ich noch ein paar Metaeigenschaften und Slotfunktionen:
Mit diesen Eigenschaften kann nun im Qt Designer die Eigenschafts-Werte vor
der Laufzeit festgelegt werden. Dafür erstellen wir zunächst im Qt Designer
ein einfaches QWidget Objekt und klicken mit der rechten Maustaste darauf
und dann auf Promote to … im nächsten Fenster geben wir unter new die Daten
von unserem eigene Steuerelement an (Bassisklasse, Unser neuer Klassenname
sowie den Headerdateinamen) und fügen diese hinzu. Anschließend können wir
mit einem klick auf Promote dem Designer sagen dass das ausgewählte Widget
das von uns erstellte QVolumeMeter-Widget ist. Es wird jedoch leer angezeigt,
das ist normal da der Qt Designer ohne ein Plugin nicht wissen kann wie wir
dieses programmiert haben. Im Propertyeditor sehen wir dann auch nichts
können jedoch die Eigenschaften die wir für den Metainterpreter hinterlegt
haben selbst hinzufügen und verwenden.
Die Zusätzliche setPercent-Funktion hab ich noch hinzugefügt um ein Signal
eines QSlider-Objekts direkt mit meinem zu Verknüpfen.
Die fertige Klasse sieht letzten endlich dann so aus:
Header:
Und der Sourcecode der Klasse:
Im Prinzip ist es also nicht sonderlich schwer sein eigenes Steuerelement zu erstellen. Wer möchte kann nun hingehen und für sich weitere event-Funktinen implementieren um zB. auf Mausklicks etc zu reagieren, siehe dazu auch QWidget Reference. Das Projekt bzw. den Source findet ihr wieder unter meinem github Account: QTestExampleWidget
Schreibt mir doch für was Ihr euch ein eigenes Steuerelement geschrieben habt.