Forum: Mikrocontroller und Digitale Elektronik GLCD Menü "scrollen"


von Jan H. (janiiix3)


Lesenswert?

Hey Leute,

ich denke wahrscheinlich wieder viel zu kompliziert.
Möchte gerne durch ein "Menü" scrollen.
Die Texte dafür befinden sich in der Struktur.
Anzeigen klappt auch alles. Nun habe ich nur Zeile 0-5 zur Verfügung.
Wenn ich unten angekommen bin (5) möchte Ich gerne wieder bei Zeile 0 
anfangen und den rest der im Array noch nicht ausgegeben wurde an 
"Menütext" ausgeben..
1
void openMenue(menue_t *m,uint8_t cursor, size_t array)
2
{
3
  static uint8_t oldCursor = 1;
4
  static uint8_t index = 0;
5
  uint8_t scroll = 0;
6
  
7
  if (oldCursor != cursor)
8
  {
9
    glcdGotoXY(oldCursor,0);
10
    glcdPuts("                     ");
11
  }
12
  oldCursor = cursor;
13
  
14
  if (cursor >= array)cursor = 0;
15
  
16
  do
17
  {
18
    if (index == cursor)
19
    {
20
      strcpy((char*)buffer,"->");
21
      strcat((char*)buffer,m[cursor].Name);
22
    }
23
    else
24
    {
25
      strcpy((char*)buffer,m[index].Name);
26
    }
27
    glcdGotoXY(index,0);
28
    glcdPuts((char*)buffer);
29
    
30
  } while (index++<array);
31
  index = 0;
32
}
Kann mir jemand auf die Sprünge helfen?

: Bearbeitet durch Moderator
von Joe F. (easylife)


Lesenswert?

Jan H. schrieb:
> Nun habe ich nur Zeile 0-5 zur Verfügung.
> Wenn ich unten angekommen bin (5) möchte Ich gerne wieder bei Zeile 0
> anfangen und den rest der im Array noch nicht ausgegeben wurde an
> "Menütext" ausgeben..

Dein Problem verstehe ich noch nicht ganz.
Heisst das du hast 6 Zeilen auf dem Display zur Verfügung, dein Menu 
kann jedoch mehr als 6 Einträge haben?
In diesem Fall möchtest du dann das Menu "seitenweise" (zu je max. 6 
Einträgen) anzeigen?

: Bearbeitet durch User
Beitrag #5293407 wurde vom Autor gelöscht.
von Jan H. (janiiix3)


Lesenswert?

Folgendes..

Displayaufbau
1
->Menüpunkt[0]
2
->Menüpunkt[1]
3
->Menüpunkt[2]
4
->Menüpunkt[3]
5
->Menüpunkt[4]
6
->Menüpunkt[5]
7
**Newsticker**

Übergeben tue ich der Funktion die Texte die dargestellt werden sollen 
(Menüpunkte).
Wenn ich jetzt ein "Menü" übergebe welches mehr als "6" Members hat, 
möchte ich gerne das sich "Menüpunkt[0] weiter nach oben verschiebt, so 
das man es nicht mehr sehen kann und alle anderen die weiter unten sind 
nach oben rücken solange ich durch das Menü "scrolle"..

Verständlicher?

von Joe F. (easylife)


Lesenswert?

Vorschlag für seitenweise Menu-Darstellung
1
void showMenue(menue_t *m, uint8_t cursor_pos, size_t menu_len)
2
{
3
  uint8_t page_start = (cursor_pos / 6) * 6;
4
  uint8_t y;
5
  uint8_t menu_entry;
6
  
7
  for (y=0, y<6; y++)
8
  {
9
    glcdGotoXY(y, 0);
10
    glcdPuts("                     "); // clear line
11
12
    menu_entry = page_start + y;
13
    if (menu_entry < menu_len)
14
    {
15
      glcdGotoXY(y, 0);
16
      if (menu_entry == cursor_pos)
17
        glcdPuts("->");
18
      else
19
        glcdPuts("  ");
20
        
21
      glcdGotoXY(y, 3);
22
      glcdPuts((char*)buffer,m[menu_entry].Name);
23
    }
24
  } 
25
}


Und das hier sollte den Cursor vom Anfang so etwa bis zur Mitte des 
Menus bewegen, dann scrollt das ganze Menu zeilenweise, und am Ende 
bewegt sich der Cursor bis zur letzten Zeile.
Alles ungetestet... probiers mal aus.
1
void showMenue(menue_t *m, uint8_t cursor_pos, size_t menu_len)
2
{
3
  int8_t  page_start;
4
  uint8_t y;
5
  uint8_t menu_entry;
6
  
7
  page_start = cursor_pos - 3;
8
    
9
  if ((page_start + 6) >= menu_len)
10
    page_start = menu_len - 6;
11
12
  if (page_start < 0) 
13
    page_start = 0;
14
  
15
  for (y=0, y<6; y++)
16
  {
17
    glcdGotoXY(y, 0);
18
    glcdPuts("                     "); // clear line
19
20
    menu_entry = page_start + y;
21
    if (menu_entry < menu_len)
22
    {
23
      glcdGotoXY(y, 0);
24
      if (menu_entry == cursor_pos)
25
        glcdPuts("->");
26
      else
27
        glcdPuts("  ");
28
        
29
      glcdGotoXY(y, 3);
30
      glcdPuts((char*)buffer,m[menu_entry].Name);
31
    }
32
  } 
33
}

: Bearbeitet durch User
von Jan H. (janiiix3)


Lesenswert?

Joe F. schrieb:
> glcdPuts((char*)buffer,m[menu_entry].Name);

Die Funktion erwartet nur einen Parameter(char *).
Ist das so gewollt das beides ausgegeben werden soll?

von Joe F. (easylife)


Lesenswert?

Jan H. schrieb:
>> glcdPuts((char*)buffer,m[menu_entry].Name);
>
> Die Funktion erwartet nur einen Parameter(char *).
> Ist das so gewollt das beides ausgegeben werden soll?

ne, soll heissen:

glcdPuts(m[menu_entry].Name);

wie gesagt, ich habs nur kurz runtergehackt ohne irgendwas zu 
compilieren oder zu testen.
Die Idee sollte aber klar werden (mit der Variablen "page_start")

: Bearbeitet durch User
von Jan H. (janiiix3)


Lesenswert?

Wenn ich jetzt die Begrenzung einbauen will, was genau wird abgefragt?
Er läuft nach oben und unten jeweils über..?

von Joe F. (easylife)


Lesenswert?

Verstehe deine Frage nicht.
Die Funktionen zeigen dir das Menu an, unter Berücksichtigung der 
jeweiligen Cursorposition.
Beim Aufruf musst du natürlich sicherstellen, dass "cursor_pos" >= 0 ist 
und < "menu_len".

von Jan H. (janiiix3)


Lesenswert?

Kann man das nicht direkt in der Funktion begrenzen? Ich möchte ja nicht 
über die Bereiche bzw. Einträge scrollen. Scrolle ich zu weit nach oben, 
verschwindet der Pfeil, genau das gleiche wenn Ich zu weit nach unten 
Scrolle..

Ich habe versucht direkt am Anfang innerhalb der Funktion eine if 
Abfrage zu machen...
If cursor >= menueLen.. Hat aber nicht geklappt..

von Joe F. (easylife)


Lesenswert?

Jan H. schrieb:
> Kann man das nicht direkt in der Funktion begrenzen?

warum?

> Ich möchte ja nicht
> über die Bereiche bzw. Einträge scrollen.

dann verhindere dies ausserhalb der Funktion, an der Stelle an der 
cursor_pos inkrementiert oder dekrementiert wird (ich vermute über 
Tastendrücke).

Jan H. schrieb:
> Scrolle ich zu weit nach oben,
> verschwindet der Pfeil, genau das gleiche wenn Ich zu weit nach unten
> Scrolle..

Ja eben.
Du müsstest wenn du zu weit nach oben gelaufen bist erstmal wieder die 
gleichen Schritte nach unten machen, damit der Pfeil wieder kommt.

Also. Begrenze cursor_pos an der richtigen Stelle im Programm.

: Bearbeitet durch User
von Jan H. (janiiix3)


Lesenswert?

Joe F. schrieb:
> Also. Begrenze cursor_pos an der richtigen Stelle im Programm

Ob ich das jetzt direkt vor dem funktionsaufruf tue oder direkt in der 
Funktion als erstes sollte wohl doch egal sein..

von Joe F. (easylife)


Lesenswert?

Jan H. schrieb:
> Ob ich das jetzt direkt vor dem funktionsaufruf tue oder direkt in der
> Funktion als erstes sollte wohl doch egal sein..

Ist es nicht.
showMenue() hat nur die Aufgabe das Menu anzuzeigen, und nicht die 
Variable "cursor_pos" zu verändern.
Dies müsstest du aber in der Funktion tun, um z.B. bei cursor_pos == -1 
cursor_pos auf 0 zu setzen.
Ginge, indem man einen Pointer auf cursor_pos übergäbe.

Das ist aber allerdreckigster Programmierstil.

Warum tust du dir so schwer, cursor_pos ausserhalb der 
Menu-Anzeigefunktion im gültigen Wertebereich zu halten?
1
if (key_up)
2
{
3
  if (cursor_pos > 0)
4
  {
5
    cursor_pos--;
6
    showMenu(&menu, cursor_pos, menu_len);
7
  }
8
}
9
else if (key_down)
10
{
11
  if (cursor_pos < menu_len-1)
12
  {
13
    cursor_pos++;
14
    showMenu(&menu, cursor_pos, menu_len);
15
  }
16
}

: Bearbeitet durch User
von Jan H. (janiiix3)


Lesenswert?

Nehmen wir mal an ich habe X verschiedene Menüs die ich der Funktion an 
anderen Stellen übergeben, so muss ich mehrere if abfragen einbauen 
anstatt eine in der Funktion.

von Joe F. (easylife)


Lesenswert?

Wie sieht denn dein menue_t aus?
Sinnvollerweise würdest du dann menu_len und cursor_pos auch dort 
hineinpacken.

Abgesehen davon kannst du für x verschiedene Menüs auch ein array mit x 
menu_len anlegen, und kannst dann jeweils die gleiche if Bedingung für 
alle Menus nutzen.

: Bearbeitet durch User
von Jan H. (janiiix3)


Lesenswert?

Joe F. schrieb:
> Wie sieht denn dein menue_t aus?
> Sinnvollerweise würdest du dann menu_len und cursor_pos auch dort
> hineinpacken.
>
> Abgesehen davon kannst du für x verschiedene Menüs auch ein array mit x
> menu_len anlegen, und kannst dann jeweils die gleiche if Bedingung für
> alle Menus nutzen.

Du meinst eine extra Struktur und die dann mit diesen Informationen 
übergeben?

von Joe F. (easylife)


Lesenswert?

Jan H. schrieb:
> Joe F. schrieb:
>> Wie sieht denn dein menue_t aus?
>> Sinnvollerweise würdest du dann menu_len und cursor_pos auch dort
>> hineinpacken.
>>
>> Abgesehen davon kannst du für x verschiedene Menüs auch ein array mit x
>> menu_len anlegen, und kannst dann jeweils die gleiche if Bedingung für
>> alle Menus nutzen.
>
> Du meinst eine extra Struktur und die dann mit diesen Informationen
> übergeben?

Nein.
Du baust eine Struktur, in der alle nötigen Informationen für ein Menü 
enthalten sind.
- Anzahl der Menueinträge
- Texte der Menueinträge
- sonstige benötigte Informationen
- und von mir aus auch die Cursorposition

Wenn du mehrere Menus hast, benutzt du einfach ein Array dieser 
Struktur.

: Bearbeitet durch User
von Jan H. (janiiix3)


Lesenswert?

Also meine vorhandene Array struktur um eben diese Information 
erweitern. Eine gute Idee. Ich danke dir für deine Hilfe!

von Jan H. (janiiix3)


Lesenswert?

Moin,

jetzt muss Ich  doch noch mal eine Frage los werden. Wie würdest du das 
jetzt am besten auswerten, welcher Menüpunkt ausgewählt wurde oder eher 
auf welchen gerade gezeigt wird? Ich habe ja einen Drehencoder auf dem 
Board.

von W.S. (Gast)


Lesenswert?

Jan H. schrieb:
> Hey Leute,
>
> ich denke wahrscheinlich wieder viel zu kompliziert.
> Möchte gerne durch ein "Menü" scrollen.
> Die Texte dafür befinden sich in der Struktur.

Hey Jan.

Nee, du hast nicht zu kompliziert gedacht, sondern zu wenig. Du solltest 
einen ganz anderen Denkansatz wählen. Ich versuch mal, dir ein paar 
Denkanstöße zu geben.

Also, ein Menüsystem ist ja erstens etwas, wo man sich durch 
irgendwelche Eingaben hindurch maneuvrieren kann. Obendrein soll es auch 
noch passend angezeigt werden, damit man sieht, wo man grad ist und was 
man grad mit der letzten Eingabe angerichtet hat.

Das sind zwei verschiedene Dinge: a) das Maneuvrieren im Menü und b) das 
Anzeigen des Menüs.

Je nachdem, was man an Eingabemöglichkeiten hat, gibt es zumindest drei 
verschiedene Dinge:
- UP    = ich will rauf (oder eben rückwärts)
- DOWN  = ich will runter (oder eben vorwärts)
- ENTER = ich will ne Aktion (das machen, was der aktuelle Menüpunkt 
anzeigt)

Also sollte dein Menü - wenn es denn in Form eines Arrays aus 
Menü-Elementen aufgebaut sein sollte - in jedem Menü-Element wenigstens 
folgende Dinge haben:
- einen Zeiger auf die Funktion, die bei Eingabe von "ENTER" aufgerufen 
werden soll
- einen Text oder ein Icon, eben etwas, das auf dem Display angezeigt 
werden soll
- bei grafischen Menüs auch eine Koordinate, wo das aktuelle Element 
erscheinen soll

Generell muß es logischermaßen zwei globale Variablen geben:
a)  die Nummer des Menüelements, was grad den Fokus hat, also das, wo du 
grad bist
b) wenn du scrollen mußt, dann eben auch die Nummer des Menüelementes, 
was als oberstes bzw. erstes auf dem Display erscheinen soll

Und nun muß es 2 verschiedene Funktionen geben:
a) die Menüfunktion. Diese kriegt als Input einen Event (UP, DOWN oder 
ENTER oder weitere Tasten o.ä.) und sie erledigt die eigentlichen 
Menüaufgaben. Also bei UP muß der Fokus zum vorherigen Element 
verschoben werden, ggf. umschlagen auf das Ende der Einträge, ebenso muß 
ggf. die Nummer des ersten anzuzeigenden Elements korrigiert werden. 
Entsprechendes dann auch für DOWN. Ausführen der angegebenen Funktion 
bei ENTER.

b) die Zeichenfunktion. Diese muß nach allen Menü-Änderungen aufgerufen 
werden, um das Menü neu zu zeichnen. Sie verläßt sich drauf, daß sie bei 
dem Element anfangen muß, dessen Nummer in der globalen Variable (b) 
steht, und sie muß das Element, was in der globalen Variable (a) steht, 
irgendwie kennzeichnen. z.B. invertiert oder mit einem Häkchen davor 
oder einem Rahmen drumherum o.ä., damit man sieht, welches Element grad 
das Aktuelle ist.

W.S.

von Jan H. (janiiix3)


Lesenswert?

W.S. schrieb:
> - einen Zeiger auf die Funktion, die bei Eingabe von "ENTER" aufgerufen
> werden soll

Habe ich soweit ja alles verstanden.
Nur das mit dem Zeiger auf die Funktionen die bei dem jeweiligen 
Menüpunkt ausgeführt werden soll.

Was mache Ich, wenn ich verschiedene Funktionen haben, die auch 
unterschiedliche Übergabeparameter haben oder Rückgabeparameter?

So wie Ich es bis jetzt verstanden habe, ist das ohne "großen" Aufwand 
nicht so einfach möglich?

von grundschüler (Gast)


Lesenswert?

Jan H. schrieb:
> Nur das mit dem Zeiger auf die Funktionen die bei dem jeweiligen
> Menüpunkt ausgeführt werden soll.

Ich habe auf der x-1-Position ein '*' der durch Pfeil-oben/unten durch 
das Menu bewegt wird. die jeweilge Menu-position wird als Wert 
gespeichert. Wenn dann ein 'ok' eingegeben wird, wird über ein switch 
der gespeicherte Menu-Wert abgerufen und ausgewertet. Ganz einfach. 
Zeiger braucht man da nicht.

Wenn das funktioniert, muss der Überlauf programmiert werden.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.