Über dieses Übungsblatt
Programmierung von GUIs ist ein Thema, dass vieles bereits gelernte vorraussetzt, zusätzlich werden neue Dinge eingeführt. Damit Sie die Möglichkeit haben sich gründlich damit auseinanderzusetzen, wird sich dieses Blatt ausschließlich mit der Programmierung von GUIs in C++ mittels des Qt-Frameworks befassen. Dieses hat einige Vorteile:
- Qt-Code kann plattformübergreifend kompiliert werden
- Qt ist open source und hat eine sehr große Userbase
- Qt enthält einige Wrapper für andere Sprachen. So kann Ihr Qt-Code fast 1:1 in anderen Sprachen eingebettet werden, etwa mittels PyQt in Python. Mit anderen Worten: Die Zeit, die Sie in dieses Übungsblatt stecken ist automatisch auch eine Investition in die Erstellung von GUIs mit anderen Programmiersprachen.
[1] Für das Schlagwort „Qt C++“ gibt Google 23 Mio Suchergebnisse an.
Aufgabe Anlage zu Qt
Letzte Änderung: 15. June 2020, 12:55 Uhr
keine Punkte — im Detail
Ansicht: | Die Anlage enthält ein Tutorial mit den nötigsten Befehlen, um dieses Blatt bearbeiten zu können. Selbstverständlich steht es Ihnen frei auch die restliche Qt-Bibliothek zu verwenden — die Qt-Dokumentation ist vollständig, übersichtlich strukturiert und enthält viele Tutorials und Beispiele.
[1] Glauben Sie mir, das ist auch heutzutage keine Selbstverständlichkeit.
[2] Alle Funktionen einer Klasse werden schön untereinander aufgelistet. Ein- und Ausgabeklassen haben meist eigene Unterseiten.
Aufgabe Telefon
Letzte Änderung: 19. June 2020, 07:46 Uhr
12 Punkte — im Detail
Ansicht: | Änderungshistorie- Hinweis bezüglich connect/Keyboardevents angepasst.
In der Anlage haben Sie erste Ansätze der GUI Entwicklung mit Hilfe des QT Frameworks gesehen. Wir möchten nun das Framework testen, indem wir eine erste einfache GUI implementieren.
Implementieren Sie eine GUI für ein Telefontastenfeld:
- die Tasten (0-9), „Löschen“ und „Anrufen“ soll durch Buttons realisiert werden.
Verwenden Sie zum Platzieren der Buttons einen Layout Manager. - die aktuell getippt Nummer soll in einem Textfeld (
QLineEdit
) erscheinen - zusätzlich sollen die Ziffern auch durch das Drücken der entsprechenden Taste auf der Tastatur betätigt werden können. Wichtig: Gemeint ist hier nicht das Textfeld
QLineEdit
, dieses bietet die Funktionalität bereits von sich aus mit. Durch Signals ist es aber auch möglich eine Zifferntaste zu betätigen, wenn der Fokus nicht auf dem Textfeld liegt.
Hinweis: Arbeiten Sie hier zum Beispiel mit connect
oder direkt mit KeyboardEvents, um auf Eingaben in einer textbasierten Komponente von der Tastatur zu reagieren. Alle Texteingaben und sonstige Tasteneingaben sollen unterdrückt werden. Es soll aber weiterhin möglich, sein Zahlen zu löschen. - Implementieren Sie die Möglichkeit mit den Pfeiltasten im Eingabefeld zu navigieren.
- Stellen Sie sicher, dass in dem Textfeld nur Zahlen eingegeben werden können.
- Realisieren Sie auch eine frei wählbare Funktionalität für die Löschen bzw. Anrufen-Taste.
- Bonus: Erweitern Sie die obige Telefonoberfläche zu einem Taschenrechner:
Fügen Sie die Tasten '+','-','*','/' und '=' ein. Im Textfeld soll das Ergebnis der Rechnung nach drücken des '='—Buttons angezeigt werden. Welche Operation gerade ausgewählt wurde, wird durch Färbung des Operationsbuttons nach der Betätigung angezeigt.
Aufgabe Validieren von Eingaben
Letzte Änderung: 15. June 2020, 13:07 Uhr
8 Punkte — im Detail
Ansicht: | In dieser Aufgabe geht es vielmehr darum die Objekte kontrollieren zu können. Wir beginnen damit ein einfaches Texteingabefeld anzuzeigen und dessen Funktionsweise zu kontrollieren. Die Aufgabe besteht darin durch einen QValidator
(siehe auch die Anlage) die Eingabe eines solchen Eingabefeldes auf Korrektheit zu überprüfen und dabei selbst zu definieren was eine korrekte Eingabe ist.
Einen speziellen QValidator
können wir wie folgt definieren:
class MyValidator : public QValidator {
public:
MyValidator(QObject *parent = nullptr);
virtual ~MyValidator() override = default;
// wird von QLineEdit aufgerufen, wenn eine beliebige Taste gedrückt wird
// (darf den String und die Cursor-Position pos verändern)
virtual QValidator::State validate(QString &input, int &pos) const = 0
// wird von QLineEdit aufgerufen, wenn die Enter-Taste betätigt wird
// (darf den String verändern)
virtual void fixup(QString &input) const
};
QValidator::State
ist hierbei einer der Wert QValidator::Invalid
, QValidator::Intermediate
oder QValidator::Acceptable
. Siehe auch: QValidator States
- Erstellen Sie eine GUI, die ein Texteingabefeld anzeigt.
Es reicht völlig aus ein Textfeld auf einer sonst leeren Oberfläche zu platzieren. (Es geht hier nur darum die Eingabemaske, die wir hier implementieren zu testen.) - Als nächstes Implementieren wir einen
QValidator
, der prüfen soll, ob es sich um eine valide E-Mail Adresse handelt.
Der Einfachheit halber definieren wir eine E-Mail Adresse als einen String, der Form mindestens.ein.nicht-at.zeichen@mindestens.ein.zeichen
ist.
Sofern die Eingabe keine E-Mail Addresse ist, soll der String mittels fixup
durch ein valides Beispiel vervollständigt werden (z.B. ein @emailprovider.xy
angehangen werden). - Sollte der Benutzer einmal keine korrekte Eingabe gemacht haben, so soll sich die Hintergrundfarbe der textbasierten Komponente in eine zufällige Farbe ändern. Bei korrekter Eingabe wird der Hintergrund wieder weiß.
Aufgabe Layouts
Letzte Änderung: 15. June 2020, 13:07 Uhr
8 Punkte — im Detail
Ansicht: | In der Anlage haben Sie erfahren, dass es verschiedene Layouts gibt mit denen mehrere Elemente auf einer Oberfläche (Container) strukturiert werden können. Wir möchten nun ein Programm schreiben mit dem wir verschiedene Layouts testen können, indem wir die Anordnung der Elemente als Nutzer durch die Auswhl eines Layouts dynamisch verändern können.
- Erstellen Sie als erstes eine (Grund)Oberfläche, mit der Sie die verschiedenen Layouts testen können. Auf ihrer Oberfläche befinden sich fünf Elemente (z.B. Labels). Zudem gibt es eine ComboBox, mit der sie die Auswahl des Layouts treffen. Es sollen die vier Standardlayouts
Vertical Layout
, Horizontal Layout
, Grid Layout
und Form Layout
angeboten werden. - Wird ein neues Layout ausgewählt werden die Elemente entsprechend auf ihrer Oberfläche neu angeordnet.
Wichtig: Es geht hier nicht darum die Elemente durch copy-pasta an verschiedenen Stellen im Code immer wieder neu zu erstellen. In dieser Aufgabe sollen die einfach erstellten Objekte neu zu arangieren. - Beschreiben Sie mit eigenen Worten, wie die Layouts ihre Elemente anordnet. Dazu können sie ein weiteres Element (Textfeld) mit auf die Oberfläche aufnehmen, in dem sich der Beschreibungstext bei jeder Layoutänderung anpasst.
Aufgabe (Deutschland)Karte zeichnen
Letzte Änderung: 15. June 2020, 13:07 Uhr
12 Punkte — im Detail
Ansicht: | Ihre Aufgabe besteht darin eine Karte von Deutschland zu zeichnen.
Zu diesem Zweck steht die Datei deutschland.pol
zur Verfügung.
deutschland.pol
(4.9 Mb)
Die ersten 17 Zeilen der Datei sehen etwa so aus:66
11
70894996 90916485
70894967 90916596
70894857 90916900
70894785 90917068
70894689 90917042
70894643 90916941
70894619 90916852
70894796 90916476
70894890 90916276
70894991 90916238
70894996 90916485
212
71167074 91096353
71166917 91096437
71166775 91096512
Diese Textdatei enthält die Umrisse der Bundesrepublik und der Bundesländer als Koordinaten. Die Zahl in der ersten Zeile gibt die Anzahl der Polygone an. Die Zahl in der zweiten Zeile gibt die Anzahl der Punkte des ersten Polygons an. Danach folgen die x- und y-Koordinaten des ersten Polygons. Nun beginnt das zweite Polygon, erneut mit der Anzahl der Punkte, usw.
- Lesen Sie die Datei ein und speichern Sie die 2D-Punkte jedes Polygonzuges in einem
vector
ab. Um sich nun zu merken welche Polygonzug welche Punkte enthält, speichern wir den vector in einer map
, wobei der Schlüssel die Nummer (durchnummeriert) des Polygonzuges ist und der Wert die dazugehörigen Punkte ist.
Hinweis: Falls Sie probleme mit dem einlesen haben, schauen Sie sich noch einmal Aufgabenblatt 03 an, wo wir auch schon eine solch einfach formattierte Datei eingelesen haben. - Erstellen Sie eine GUI, auf der die Karte gezeichnet wird. Der Nutzer soll die Wahl haben, ob er die Karte grob (nur jeden 50. Punkt als groben Polygonzug interpretieren) oder fein (alle Punkte verbinden) angezeigt haben möchte.
Hinweis: Beachten Sie, dass die Koordinaten der Karte sehr groß sind. Direkt die Position an der Stelle \((70894996,90916485)\) zu referenzieren geht nur bei SEHR großen Bildschirmen ;). Skalieren/Verschieben Sie also die Positionen global vor dem Zeichnen so um dass Sie überhaupt etwas sehen können. - Bieten Sie dem Nutzer die Möglichkeit, die Karte einzufärben.
- Bonus: Implementieren Sie das Zoomen und Verschieben der Karte mit der Maus
- Bonus: Flood-Filling: Wir möchten nun das „Einfärben“, das Qt für uns voll-automatisch übernehmen kann, eigenhändig implementieren.
- Dazu beginnen wir damit, dass der User auf ein beliebiges Pixel auf dem gezeichneten Bild klickt.
- Ist das Pixel ungefärbt, so wird es eingefärbt und die Methode wird rekursiv für alle umliegenden Pixel aufgerufen, die keine Konturfarbe aufweisen.
- Ist es bereits eingefärbt passiert nichts.
Hinweis: Um Pixel einzeln einzufärben muss das Basisobjekt auf dem gezeichnet wird ein Bitmap sein, wenn nur Linienzüge gemalt werden ist es auch möglich eine Vektorgrafik zu erstellen. (Der Rest des Codes sollte dabei im Prinzip gleich bleiben.)
Zur Übung: Implementieren Sie die rekursive Methode als while
-Schleife, die über einen Vektor/PriorityQueue der nächsten zu besuchenden Pixel iteriert. Indem Sie zufällige Prioritäten expndieren / auswählen und mit verschiedenen Farben arbeiten können sehr interessante Füllungen entstehen. ;)