Icons stellen eine besondere Art von Bild dar. Diese bestehen zwar auch aus einzelnen Bildpunkten (Pixel), sind meist jedoch kleiner und einfacher gehalten als übliche Bilder. Icons werden oft auch als Symbol oder Piktogramm bezeichnet. Der Aussagegehalt soll dabei auf das Wesentliche reduziert werden.
Dadurch, dass Symbole offensichtlich relativ wenig Ressourcen brauchen, sind sie besonders interessant für sich wiederholende Aufgaben (Schaltflächen, Statusanzeigen, etc.) in einer Mensch-Maschine-Schnittstelle in Form einer grafischen Benutzeroberfläche.
Die verwendeten Bibliotheken enthalten eine Reihe von Icons. Diese Icons sind zum Beispiel in Form einer Liste auf dem Display darzustellen.
Falls Sie nicht in der Vorgehensmodell-Ebene sind, navigieren Sie diese bitte an (nach oben). Falls das Projekt nicht mehr geöffnet ist, öffnen sie das SiSy UML-Projekt wieder. Legen Sie ein neues Klassendiagramm an und wählen Sie die Sprache ARM C++. Beachten Sie die Einstellungen für die Zielplattform STM32F4-Discovery. Beim Öffnen des Diagramms (rechte Maustaste, nach unten) laden Sie die Diagrammvorlage für eine ARM C++ Applikation mit Grafikdisplay ohne µGL.
Selektieren Sie die Operation onStart der Klasse Application.
Ersetzen Sie möglicherweise vorhandenen Beispielquelltext durch folgenden Code:
onStart()
display.clearScreen();
Erstellen und übertragen Sie die Anwendung auf den Mikrocontroller.
Icons werden in der µGL mit einer verringerten Farbtiefe abgebildet. Dabei wird auf eine Farbpalette zurückgegriffen. Diese kann bei Bedarf auch anwendungsspezifische Farbcodes enthalten. Jede Farbe in der Palette wird als RGB-Wert codiert.
// RGB-Makro, Farbanteil 0-255 // RGB(rot,grün,blau) color_t red,green,blue,gray,black,white, red = RGB( 255, 0, 0 ); green = RGB( 0, 255, 0 ); blue = RGB( 0, 0, 255 ); gray = RGB( 128, 128, 128 ); black = RGB( 0, 0, 0 ); white = RGB( 255, 255, 255 );
Die Farbpalette selbst ist ein Array von 16 Farbwerten. Dabei sind den ersten vier Farbwerten besondere Bedeutungen zugewiesen. Diese werden in der Funktion drawIcon entsprechend dem Farbschema, der Darstellungsoptionen und der Displaymöglichkeiten berücksichtigt.
// Farbpalette für Icons, 4Bit Codiert, 16 Farbwerte color_t paletteIcon[] = { // Farb-Index ColorBackground, // 0 ColorForeground, // 1 ColorTransparent, // 2 ColorHalfTransparent, // 3 RGB(255,255,255), // 4 RGB(0,0,0), // 5 RGB(255,0,0), // 6 RGB(0,255,0), // 7 RGB(255,255,0), // 8 RGB(0,0,255), // 9 RGB(170,123,0), // 10 RGB(195,195,195), // 11 RGB(255,201,14), // 12 RGB(237,151,35), // 13 RGB(221,36,236), // 14 RGB(87,87,87) // 15 };
Die oben aufgezeigte Standardpalette enthält die folgend dargestellten Farben:
Für 16 Farben reichen vier Bit zur Codierung aus. Damit lassen sich in einem Byte zwei Bildpunkte abbilden. Um dem Entwickler diese Codierungsaufgabe etwas zu erleichtern, bietet die Bibliothek das Makro Pixel4 an. Das Makro verfügt über zwei Parameter. Diese repräsentieren den Farbindex (0-16) der obigen Farbpalette. Die eigentlichen Bildpunkte der Icons werden dann über diese Makros im Code abgebildet.
// 2x4Bit Farbwerte, erst low, dann high #define Pixel4(c1,c2) (c1+(c2<<4))
Die Displayfunktion drawIcon erwartet als Parameter das Icon in Form einer Struktur mit einem sogenannten Header. Darin werden wesentliche Eigenschaften des darzustellenden Icons abgebildet. Übrigens haben Bilder (Bitmaps) letztlich den selben Header. Das Strukturelement Typ enthält in diesem Fall ein 'b'.
struct IconHeader{ unsigned char type; // uint8_t='i' unsigned char width; // uint8_t unsigned char height; // uint8_t unsigned char dataStart; // uint8_t };
Die in der Bibliothek vorgefertigten Icons werden wiederum als Liste und mit einem Namen angeboten.
// IconNamen #define iconAbort_12 ((IconHeader*)_iconAbort_12) #define iconBack_12 ((IconHeader*)_iconBack_12) #define iconBatt0_12 ((IconHeader*)_iconBatt0_12) #define iconBatt100_12 ((IconHeader*)_iconBatt100_12) ... // IconListen-Struktur struct IconIndex { unsigned char id; IconHeader* pIcon; }; //IconListe für 12x12Pixel Icons IconIndex icons12[] ={ {'x',iconAbort_12}, {'b',iconBack_12}, {'b',iconBatt0_12}, {'9',iconBatt100_12}, {'7',iconBatt33_12}, {'8',iconBatt66_12}, {'B',iconBright_12}, {'C',iconCalculator_12}, ...
Somit lassen sich Icons als Element einer Icon-Liste, aber auch über ihren Namen ansprechen.
Ein konkretes Icon sieht im Code dann wie folgt aus:
uint8_t _iconAbort_12[] ={ 'i', 12, 12, Pixel4(2,1),Pixel4(1,2),Pixel4(2,2),Pixel4(2,2),Pixel4(2,1),Pixel4(1,2), Pixel4(1,1),Pixel4(1,1),Pixel4(2,2),Pixel4(2,2),Pixel4(1,1),Pixel4(1,1), Pixel4(1,1),Pixel4(1,1),Pixel4(1,2),Pixel4(2,1),Pixel4(1,1),Pixel4(1,1), Pixel4(2,1),Pixel4(1,1),Pixel4(1,1),Pixel4(1,1),Pixel4(1,1),Pixel4(1,2), Pixel4(2,2),Pixel4(1,1),Pixel4(1,1),Pixel4(1,1),Pixel4(1,1),Pixel4(2,2), Pixel4(2,2),Pixel4(2,1),Pixel4(1,1),Pixel4(1,1),Pixel4(1,2),Pixel4(2,2), Pixel4(2,2),Pixel4(2,1),Pixel4(1,1),Pixel4(1,1),Pixel4(1,2),Pixel4(2,2), Pixel4(2,2),Pixel4(1,1),Pixel4(1,1),Pixel4(1,1),Pixel4(1,1),Pixel4(2,2), Pixel4(2,1),Pixel4(1,1),Pixel4(1,1),Pixel4(1,1),Pixel4(1,1),Pixel4(1,2), Pixel4(1,1),Pixel4(1,1),Pixel4(1,2),Pixel4(2,1),Pixel4(1,1),Pixel4(1,1), Pixel4(1,1),Pixel4(1,1),Pixel4(2,2),Pixel4(2,2),Pixel4(1,1),Pixel4(1,1), Pixel4(2,1),Pixel4(1,2),Pixel4(2,2),Pixel4(2,2),Pixel4(2,1),Pixel4(1,2) };
Bei diesem Icon handelt es sich um das Symbol _iconAbort_12.
Für die Entwicklung von eigenen Icons steht Ihnen ein spezielles Werkzeug zur Verfügung. Mit dem Icon-Designer und Bitmap-Konverter können Sie sich den benötigten C++ Code für Icons und Bitmaps aus den Bildern generieren lassen.
Nach den Vorbereitungen liegt uns eine einfache Grafikanwendung vor. In der Operation onStart wird bis jetzt lediglich der Displayinhalt gelöscht. Die Icon-Anwendung soll in zwei Schritten realisiert werden.
Um mit vorgefertigten Icons arbeiten zu können muss das entsprechende Paket in die Anwendung eingefügt werden. Das geschieht, indem Sie das Paket UglIcons zum Beispiel aus dem Navigator (Navigator, rechte Maustaste, UML-Pakete) in das Klassendiagramm der Anwendung ziehen.
In der ersten Itteration soll ganz einfach auf Icons aus dem Fundus 12×12 und 20×20 per Name und per Index zugegriffen werden.
onStart:
display.clearScreen(); display.drawIcon( 10, 10, icons12[0].pIcon ); display.drawIcon( 10, 30, iconAbort_20 ); display.drawIcon( 10, 60, iconBatt66_12 ); display.drawIcon( 10, 70, icons20[5].pIcon );
Erstellen und übertragen sie die Anwendung auf den Controller. Vergleichen sie die Darstellung auf dem Display mit dem Programmcode.
Bei der zweiten Itteration gehen wir je Icon-Liste (12×12 und 20×20) die Icons in einer Schleife durch und stellen diese an einer neuen Position dar. Wir wollen dabei dem Auge etwas Zeit geben jedes Icon einzeln wahrzunehmen.
onStart:
display.clearScreen(); // das Icon "Abbruch" 12x12 und 20x20 display.drawIcon( 10, 10, icons12[0].pIcon ); display.drawIcon( 10, 30, iconAbort_12 ); // das Icon "Batterie 60%" 12x12 und 20x20 display.drawIcon( 10, 50, icons12[5].pIcon ); display.drawIcon( 10, 70, iconBatt66_12 ); // etwas warten, nächstes Bild vorbereiten waitMs(2000); display.clearScreen(); // die komplette 12x12 IconListe int i=0,x=5,y=5; // solange index i auf ein gültiges 12x12 Icon zeigt while( icons12[i].pIcon ) { // Icon mit Index i darstellen display.drawIcon( x, y, icons12[i].pIcon ); // next Icon, next Position i++; x += icons12[i].pIcon->width+5; if(x > 240-5-20 ) { x = 5; y += icons12[i].pIcon->height+5; } // etwas fürs Auge warten waitMs(200); } // etwas Abstand, neue Startposition, Index auf Listenanfang stellen y += 50; i=0,x=5; // solange index i auf ein gültiges 20x20 Icon zeigt while( icons20[i].pIcon ) { // Icon mit Index i darstellen display.drawIcon( x, y, icons20[i].pIcon ); // next Icon, next Position i++; x += icons20[i].pIcon->width+5; if(x > 240-5-20 ) { x = 5; y += icons20[i].pIcon->height+5; } // etwas fürs Auge warten waitMs(200); }
Erstellen und übertragen sie die Anwendung auf den Controller. Vergleichen sie die Darstellung auf dem Display mit dem Programmcode.
Als Übung stellen Sie bitte ein eigenes (benutzerdefiniertes) Icon dar. Der Code für das Icon kann mit dem Icon-Desinger und Bitmap-Konverter erstellt werden. Im folgenden das Ergebnis der Codegenerierung.
// generierter Code aus dem IconDesiner uint8_t _iconTest[] ={ 'i', 20, 20, Pixel4(4,4),Pixel4(4,4),Pixel4(4,4),Pixel4(4,6),Pixel4(6,6),Pixel4(6,6), Pixel4(6,4),Pixel4(4,4),Pixel4(4,4),Pixel4(4,4),Pixel4(4,4),Pixel4(4,4), Pixel4(4,6),Pixel4(6,8),Pixel4(8,8),Pixel4(8,8),Pixel4(8,6),Pixel4(6,4), Pixel4(4,4),Pixel4(4,4),Pixel4(4,4),Pixel4(4,4),Pixel4(6,8),Pixel4(8,8), Pixel4(8,8),Pixel4(8,8),Pixel4(8,8),Pixel4(8,6),Pixel4(4,4),Pixel4(4,4), Pixel4(4,4),Pixel4(4,6),Pixel4(8,8),Pixel4(8,8),Pixel4(8,8),Pixel4(8,8), Pixel4(8,8),Pixel4(8,8),Pixel4(6,4),Pixel4(4,4),Pixel4(4,4),Pixel4(6,8), Pixel4(8,8),Pixel4(8,8),Pixel4(8,8),Pixel4(8,8),Pixel4(5,8),Pixel4(8,8), Pixel4(8,6),Pixel4(4,4),Pixel4(4,6),Pixel4(8,8),Pixel4(8,8),Pixel4(5,5), Pixel4(5,8),Pixel4(8,8),Pixel4(8,5),Pixel4(8,8),Pixel4(8,8),Pixel4(6,4), Pixel4(4,6),Pixel4(8,8),Pixel4(8,5),Pixel4(4,4),Pixel4(4,5),Pixel4(8,8), Pixel4(8,5),Pixel4(8,8),Pixel4(8,8),Pixel4(6,4),Pixel4(6,8),Pixel4(8,8), Pixel4(8,5),Pixel4(4,5),Pixel4(5,5),Pixel4(8,8),Pixel4(8,8),Pixel4(5,8), Pixel4(8,8),Pixel4(8,6),Pixel4(6,8),Pixel4(8,8),Pixel4(8,5),Pixel4(4,5), Pixel4(5,5),Pixel4(8,8),Pixel4(8,8),Pixel4(5,8),Pixel4(8,8),Pixel4(8,6), Pixel4(6,8),Pixel4(8,8),Pixel4(8,8),Pixel4(5,5),Pixel4(5,8),Pixel4(8,8), Pixel4(8,8),Pixel4(8,5),Pixel4(8,8),Pixel4(8,6),Pixel4(6,8),Pixel4(8,8), Pixel4(8,8),Pixel4(8,8),Pixel4(8,8),Pixel4(8,8),Pixel4(8,8),Pixel4(8,5), Pixel4(8,8),Pixel4(8,6),Pixel4(6,8),Pixel4(8,8),Pixel4(8,8),Pixel4(5,5), Pixel4(5,8),Pixel4(8,8),Pixel4(8,8),Pixel4(8,5),Pixel4(8,8),Pixel4(8,6), Pixel4(6,8),Pixel4(8,8),Pixel4(8,5),Pixel4(4,5),Pixel4(5,5),Pixel4(8,8), Pixel4(8,8),Pixel4(5,8),Pixel4(8,8),Pixel4(8,6),Pixel4(4,6),Pixel4(8,8), Pixel4(8,5),Pixel4(4,5),Pixel4(5,5),Pixel4(8,8),Pixel4(8,8),Pixel4(5,8), Pixel4(8,8),Pixel4(6,4),Pixel4(4,6),Pixel4(8,8),Pixel4(8,5),Pixel4(4,4), Pixel4(4,5),Pixel4(8,8),Pixel4(8,5),Pixel4(8,8),Pixel4(8,8),Pixel4(6,4), Pixel4(4,4),Pixel4(6,8),Pixel4(8,8),Pixel4(5,5),Pixel4(5,8),Pixel4(8,8), Pixel4(8,5),Pixel4(8,8),Pixel4(8,6),Pixel4(4,4),Pixel4(4,4),Pixel4(4,6), Pixel4(8,8),Pixel4(8,8),Pixel4(8,8),Pixel4(8,8),Pixel4(5,8),Pixel4(8,8), Pixel4(6,4),Pixel4(4,4),Pixel4(4,4),Pixel4(4,4),Pixel4(6,8),Pixel4(8,8), Pixel4(8,8),Pixel4(8,8),Pixel4(8,8),Pixel4(8,6),Pixel4(4,4),Pixel4(4,4), Pixel4(4,4),Pixel4(4,4),Pixel4(4,6),Pixel4(6,8),Pixel4(8,8),Pixel4(8,8), Pixel4(8,6),Pixel4(6,4),Pixel4(4,4),Pixel4(4,4),Pixel4(4,4),Pixel4(4,4), Pixel4(4,4),Pixel4(4,6),Pixel4(6,6),Pixel4(6,6),Pixel4(6,4),Pixel4(4,4), Pixel4(4,4),Pixel4(4,4) }; // Namens- und Typzuweisung #define iconTest (IconHeader*) _iconTest
Entwickeln Sie die vollständige Anwendung. Erstellen und Übertragen Sie den Code der Anwendung auf den Mikrocontroller. Das Ergebnis sollte wie folgt aussehen: