Von einem analogen Touchpanel erhält man nach Kalibrierung Koordinaten
der Berührung. Nun möchte ich frei wählbare, rechteckige Regionen
definieren, deren Berührung dann z.B. eine Funktion ausführt.
Die Frage ist: wie findet man die Region, in der der Berührpunkt liegt?
Nacheinander X-, dann dazugehörige Y-Bereiche prüfen? Oder alles in
einer Bedingung wie
1
if(x>r1xmin&&x<r1xmax&&y>r1ymin&&y<r1ymax)
2
meinFunktion();
Oder mit dieser Bedingung und den X/Y-min/max-Werten aus einem Array
iterieren, samt Funktionzeiger?
Choose schrieb:> Ersteres ist besser...
Warum?
Ich denke das kommt sehr darauf an, wie viele dieser Regionen du hast,
und ob die Regionen sich evtl. ändern (z.B. bei mehreren Menüseiten).
Dann würde ich es eher flexibel mit Koordinaten-Array und einer Schleife
lösen.
Der Weg mit einzelnen Bedingungen bläht dir sonst ziemlich schnell den
Code auf, und die Schleife kann durch aus auch schneller sein.
Denn die kannst du abbrechen, sobald die passende Region gefunden wurde.
Ist aus Zeitsicht völlig egal.
Grundregel: alles was sich auf einer derartig banalen GUI Ebene abspielt
(was also nicht mit aufwändigen Animationen oder dergleichen verknüpft
ist), ist aus Rechnersicht nicht zeitkritisch. Ob die Reaktion auf die
Berührung 1ms früher oder später erfolgt, kann kein menschlicher
Benutzer je feststellen.
Viel wichtiger ist es, dass du dir den Code vernünftig und wartbar
organisierst, so dass Änderungen (auch in der Menüstruktur) auch in ein
paar Wochen noch einfach und fehlerfrei machbar sind und die Haptik in
Ordnung ist.
> Dann würde ich es eher flexibel mit Koordinaten-Array und einer Schleife lösen.
Allerdings. Nur würde ich das gleich noch weiter treiben und für jeden
Button eine schöne Struktur bauen. Die komplette Beschreibung ist dann
ein Array derartiger Buttons. Denn dieses Beschreibung liefert mir dann
gleich auch die Koordinaten um die für den Benutzer sichtbaren Bereiche
am Display anzeigen zu können.
nur so als Skizze, wie ich das in etwa organisieren würde.
Sieht auf den ersten Blick viel aus, ist es aber nicht. Die Funktionen
für zeichnen bzw. auswerten sind so schon mehr oder weniger fertig. Wenn
ein neuer Screen dazu kommt, definiere ich ein neues Button Array und
baue daraus eine neue Screen Struktur zusammen
Kommt ein neuer Button irgendwo dazu, dann schreib ich ihn einfach ins
Array mitsamt seinen Korrdinaten. Den Rest erledigt der Compiler bzw.
die Funktionen, so dass eine leichte Erweiterbarkeit bzw. Änderbarkeit
gegeben ist.
Karlheinz, du machst es komplizierter, als es ist. (Muß ich mal wieder
von der Lernbetty zu reden anfangen?)
Irgendwann sollten auch C-Programmierer mal lernen, objektorientiert zu
denken und zu programmieren. Da besteht dann ein Menü oder ein Screen
aus Objekten, die zumindest 2 Methoden haben: eine, um sich selbst zu
zeichnen und eine andere, um auf hereinkommende Events zu reagieren. In
der letzteren muß bloß geprüft werden, ob die Touch- oder
Maus-Koordinate innerhalb der eigenen Bounds liegt oder nicht. Wenn ja,
kann drauf reagiert werden, wenn nicht, wird der Event einfach
ignoriert. Sowas ist beliebig und einfach und übersichtlich erweiterbar.
Selbst runde Bounds sind einfach machbar, per Abstand vom Mittelpunkt -
ohne daß das übergeordnete programm sich um die Details des
dargestellten Objekts kümmern müßte.
W.S.
W.S. schrieb:> Karlheinz, du machst es komplizierter, als es ist.
Wieviel soll ich denn den Amateuren noch vorkauen?
> Irgendwann sollten auch C-Programmierer mal lernen, objektorientiert zu> denken und zu programmieren.
Keine Sorge. Ich arbeite seit 20 Jahren ojektorientiert. Ich weiss schon
wie das geht und wie man das macht.
Aber die Vorschläge sollen ja auch Amateuere noch verstehen können, ohne
dass ich sie gleich in die 'Geheimnisse' der Vererbung und in virtuelle
Funktionen auch noch einführen muss. Mir reicht schon, wenn ich ihnen
Strukturen nahelege und ihnen zeige, wie man damit umgeht. Die meisten
hier haben doch schon Angst vor Arrays!
> ignoriert. Sowas ist beliebig und einfach und übersichtlich erweiterbar.
Na dann mach mal.
Wenn du bei weniger als doppelt sovielen Lines of Code landest, ziehe
ich meinen Hut.
Ich würde einfach das Display in feste Tastenregionen aufteilen, z.B.
4*5 und dann die Nummer der gedrückten Taste zurück geben.
Dann ist es auch einfacher, zu entprellen und die Flanke zu erkennen.
Danke für die aufgezeigten Ansätze. Da lag ich ja gar nicht so falsch,
aber natürlich passt ein Funktionszeiger nicht mit in ein
Koordinaten-Array.. Die Lösung mit der Struktur ist übersichtlicher und
wartbarer als mehrere Arrays.
Bei unterschiedlich großen Regionen ist eine feste
Spalten/Zeilen-Aufteilung nicht so sinnvoll, da danach wieder eine
Zusammenführung erfolgen müsste und auch die Regionengrößen Vielfache
sein müssten.
Die Entprellung hätte ich "näher an der Leseroutine" angesetzt, also
unabhängig von den Regionen. Die bekommen nur die "echten"
Touchereigniskoordinaten.
Eine Optimierung durch Sortierung oder so [Pyramiden?] (falls überhaupt
möglich) dürfte aber praktisch tatsächlich überflüssig sein. Evtuelle
Möglichkeiten interessieren mich aber schon :-)
Igor schrieb:> Eine Optimierung durch Sortierung oder so [Pyramiden?] (falls überhaupt> möglich) dürfte aber praktisch tatsächlich überflüssig sein.
Wie schon gesagt:
Wenn dein Programm innerhalb von 0.01 Sekunden auf einen Benutzeraktion
reagiert, ist das mehr als genug und für einen Benutzer praktisch
'sofort'. Für einen µC sind aber 0.01 Sekunden eine halbe Ewigkeit in
der er zwischendurch noch 'teuflisch schwierige quadratische
Gleichungen' (tm) zur eigenen Erbauung lösen kann.
Bei 16Mhz macht ein AVR in dieser Zeitspanne immerhin rund 140-tausend
Instruktionen. Es gibt also keinen Grund sich vor 20*4
Koordinatenvergleichen und ein bischen Steuerung drumherum zu fürchten.
Mehr (und zwar richtig mehr) als 20 Bereiche wirst du hoffentlich ja nie
auf einer Anzeigeseite haben. Da fängt es dann sowieso schon an
unübersichtlich zu werden.
> Evtuelle> Möglichkeiten interessieren mich aber schon :-)
Dann google mal nach "Quadtree".
Karl Heinz schrieb:> Na dann mach mal.> Wenn du bei weniger als doppelt sovielen Lines of Code landest, ziehe> ich meinen Hut.
Darf ich mich in die Schlange der Wartenden einreihen? Bin zwar kein
Huttraeger, aber es heisst, dass ich sehr zackig mit den Absaetzen
knallen und in perfekt preussischer Manier mich vor dem Gegenüber
verneigen kann.
Igor schrieb:> Bei unterschiedlich großen Regionen ist eine feste> Spalten/Zeilen-Aufteilung nicht so sinnvoll, da danach wieder eine> Zusammenführung erfolgen müsste und auch die Regionengrößen Vielfache> sein müssten.
Ich würde auch mal an den Benutzer denken.
Es ist für ihn einfacher zu lernen, wenn die Tasten immer an festen
Positionen liegen und eine feste ergonomische Größe haben und nicht in
jedem Menüpunkt lustig umher wandern.
Und Tasten an gleicher Position sollten auch in jedem Menü eine
zumindest ähnliche Funktion haben.
Schau Dir mal kommerzielle Geräte an, wie die das machen.
Es sei denn Du willst ein Spiel programmieren: Suchen sie die Taste.
Peter Dannegger schrieb:> Schau Dir mal kommerzielle Geräte an, wie die das machen.
Auch dort gibt es unterschiedlich große Tasten, die nicht alle in einem
Raster angeordnet sind :-)
Igor schrieb:> Peter Dannegger schrieb:>> Schau Dir mal kommerzielle Geräte an, wie die das machen.>> Auch dort gibt es unterschiedlich große Tasten, die nicht alle in einem> Raster angeordnet sind :-)
Ein Raster ist allerdings meistens schon zu erkennen, aber Tasten sind
oft unterschiedlich gross, je nach Wichtigkeit.
Man schaue einfach mal einer KellnerIn auf die seit einigen Jahren
üblichen Bestellungs-Aufnehme-Terminals, mit denen sie auch die
Abrechnung machen. Die Tasten sind bei weitem nicht alle gleich groß.
Die Tasten für den Ziffernblock, mit dem sie Preise ausrechnen kann,
sind meist größer. Genauso wie die + Taste, bzw. andere oft benötigte
Waren.
Oder man denke einfach nur an den Ziffernblock auf einer PC Tastatur.
Enter und + sind größer als die anderen.
Hmm, auf meinem Ziffernblock sind 0, Enter und + zwar größer als die
anderen Tasten, liegen aber im Raster, d.h. belegen den Platz von genau
zwei Rasterkästchen.
Einen Touchscreen könnte man also in z.B. 5x4 Kästchen einteilen, und zu
jedem Menü gehört dann eben ein Array mit 20 Einträgen, die den
dazugehörigen "Tastencode" oder auch gleich einen Funktionspointer
enthalten. Das wäre schön einfach für die Software, aber natürlich eine
deutliche Einschränkung für's Design.
Unabhängig davon ist es natürlich immer sinnvoll, wenn Tasten mit der
gleichen Bedeutung in jedem Menü an derselben Stelle liegen. Oder wenn
das "Ja" bei der Rückfrage ("Wollen Sie wirklich...?") an einer
anderen Stelle liegt als die Taste, die die Rückfrage verursacht hat.
Karl Heinz schrieb:> Na dann mach mal.> Wenn du bei weniger als doppelt sovielen Lines of Code landest, ziehe> ich meinen Hut.
Eigentlich sollte ich mich jetzt über dich ärgern. Aber ich tu's einfach
nicht. So, bäh.
Die Grade an Übersichtlichkeit und Wartbarkeit und Buganfälligkeit sind
nicht proportional zur Anzahl der dastehenden Zeilen. Deshalb ist es mir
auch lieber, wenn die Dinge sauber voneinander getrennt werden:
Typdefinitionen, Variablendeklarationen und Initialisierungen. Aber
gerade bei C-Programmierern, die sich besonders schlau dünken, ist es
Mode, all sowas in möglichst einen Rülps zusammenzuziehen. Ich denke
mal, das war so ein bissel dein Hintergedanke.
Aber mal zu deinem Ansatz: Dein DrawScreen und HandlePress sind ziemlich
albern, weil sie komplett vereinheitlichte innere "Objekte"
voraussetzen. Entweder ist alles ein rechteckiger Button oder es geht
garnix. Warst du früher beim Militär? Ein normales Menü hat deutlich
mehr an inneren Unterschieden: Buttons, statischen Text, Icons,
Fortschrittsbalken, und und und. Manches davon kann fokussiert werden,
anderes nicht und die Draw-Methode unterscheidet sich von Objekt zu
Objekt. Was soll da deine alberne DreawScreen Routine tun? Aufgebläht
werden, bis du selbst die Übersicht verloren hast? Nein, das ist
natürlich nicht der richtige Weg.
W.S.