Ich habe versucht ein Menu, dass ich mit der Lib MenuBackend erstellt
habe auf meinem 20*4 Lcd anzeigen zu lassen.
Ich schaffe es aber nciht mit dem Befehl getName()/getAfter().
Ich dachte mit lcd.print(menu.getAfter()); kann ich das element nach dem
Aktuellen anzeigen.
So sollte das Menu später auf dem LCD aussehen im Bestfall.
-----------------------------
Einstellungen
Zeit
>Werte
usw.
-----------------------------
Doch ich bekomme immer den Fehler bei der Ausgabe:
Menu_Versuch.cpp: In function 'void menuChangeEvent(MenuChangeEvent)':
Menu_Versuch:60: error: 'class MenuBackend' has no member named
'getAfter'
Das menu Funktionier an sich.
Sven schrieb: > Menu_Versuch.cpp: In function 'void menuChangeEvent(MenuChangeEvent)': > Menu_Versuch:60: error: 'class MenuBackend' has no member named > 'getAfter' Was soviel heißt wie? (*) Also: schnapp dir die Klassenbeschreibung, (am besten indem du im zugehörigen Header File nachsiehst) und sieh nach, wie der Member wirklich heißt, bzw. ob du dich in der Groß/Klein Schreibung vertan hast. (*) Du musst lernen dass Fehlermeldungen nicht einfach nur 'Fehler' bedeutet, sondern dass der Text der Fehlermeldung auch etwas aussagt. Wenn der COmpiler die Meldung wirft 'diese Funktion gibt es nicht in dieser Klasse', dann gibt es sie auch nicht. Das kann jetzt mehrere Ursachen haben, unter anderem auch den eines ganz banalen Tippfehlers. Denn dem Compiler reicht es nicht, wenn du eine Funktion rufen willst, du ungefähr so heißt, sondern der Funktionsname muss schon exakt übereinstimmen. Oder aber natürlich, die Funktion existiert tatsächlich nicht. Ein Blick ins Header File schafft dann Klarheit, was Sache ist.
Ich hab nachgeschaut in der Datei. Ich dachte nur MenuBackend sei vllt bekannt und ihr könnt mir schnell den Befehl sagen naja... Hier ist der gesamte Code der Lib ich denke aber das nur der Teil interssant ist "inline MenuItem* getAfter() const { return after; }": /* || || @file MenuBackend.h || @version 1.3 || @author Alexander Brevig || @contact alexanderbrevig@gmail.com || @contribution Adrian Brzezinski adrb@wp.pl || || @description || | Provide an easy way of making menus || # || || @license || | This library is free software; you can redistribute it and/or || | modify it under the terms of the GNU Lesser General Public || | License as published by the Free Software Foundation; version || | 2.1 of the License. || | || | This library is distributed in the hope that it will be useful, || | but WITHOUT ANY WARRANTY; without even the implied warranty of || | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU || | Lesser General Public License for more details. || | || | You should have received a copy of the GNU Lesser General Public || | License along with this library; if not, write to the Free Software || | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA || # || */ #ifndef MenuBackend_h #define MenuBackend_h /* A menu item will be a container for an item that is a part of a menu Each such item has a logical position in the hierarchy as well as a text and maybe a mnemonic shortkey */ class MenuItem { public: MenuItem(const char* itemName, char shortKey='\0' ) : name(itemName), shortkey(shortKey) { before = right = after = left = 0; } //void use(){} //update some internal data / statistics inline const char* getName() const { return name; } inline const char getShortkey() const { return shortkey; } inline const bool hasShortkey() const { return (shortkey!='\0'); } inline void setBack(MenuItem *b) { back = b; } inline MenuItem* getBack() const { return back; } inline MenuItem* getBefore() const { return before; } inline MenuItem* getRight() const { return right; } inline MenuItem* getAfter() const { return after; } inline MenuItem* getLeft() const { return left; } MenuItem *moveBack() { return back; } MenuItem *moveUp() { if (before) { before->back = this; } return before; } MenuItem *moveDown() { if (after) { after->back = this; } return after; } MenuItem *moveLeft() { if (left) { left->back = this; } return left; } MenuItem *moveRight() { if (right) { right->back = this; } return right; } //default vertical menu MenuItem &add(MenuItem &mi) { return addAfter(mi); } MenuItem &addBefore(MenuItem &mi) { mi.after = this; before = &mi; if ( !mi.back ) mi.back = back; return mi; } MenuItem &addRight(MenuItem &mi) { mi.left = this; right = &mi; if ( !mi.back ) mi.back = back; return mi; } MenuItem &addAfter(MenuItem &mi) { mi.before = this; after = &mi; if ( !mi.back ) mi.back = back; return mi; } MenuItem &addLeft(MenuItem &mi) { mi.right = this; left = &mi; if ( !mi.back ) mi.back = back; return mi; } public: const char* name; const char shortkey; MenuItem *before; MenuItem *right; MenuItem *after; MenuItem *left; MenuItem *back; }; //no dependant inclusion of string or cstring bool menuTestStrings(const char *a, const char *b) { while (*a) { if (*a != *b) { return false; } b++; a++; } return true; } bool operator==(MenuItem &lhs, char* test) { return menuTestStrings(lhs.getName(),test); } bool operator==(const MenuItem &lhs, char* test) { return menuTestStrings(lhs.getName(),test); } bool operator==(MenuItem &lhs, MenuItem &rhs) { return menuTestStrings(lhs.getName(),rhs.getName()); } bool operator==(const MenuItem &lhs, MenuItem &rhs) { return menuTestStrings(lhs.getName(),rhs.getName()); } struct MenuChangeEvent { const MenuItem &from; const MenuItem &to; }; struct MenuUseEvent { const MenuItem &item; }; typedef void (*cb_change)(MenuChangeEvent); typedef void (*cb_use)(MenuUseEvent); class MenuBackend { public: MenuBackend(cb_use menuUse, cb_change menuChange = 0) : root("MenuRoot") { current = &root; cb_menuChange = menuChange; cb_menuUse = menuUse; } MenuItem &getRoot() { return root; } MenuItem &getCurrent() { return *current; } void moveBack() { setCurrent(current->getBack()); } void moveUp() { setCurrent(current->moveUp()); } void moveDown() { setCurrent(current->moveDown()); } void moveLeft() { setCurrent(current->moveLeft()); } void moveRight() { setCurrent(current->moveRight()); } void use(char shortkey) { recursiveSearch(shortkey,&root); use(); } void use() { //current->use(); if (cb_menuUse) { MenuUseEvent mue = { *current }; cb_menuUse(mue); } } public: void setCurrent( MenuItem *next ) { if (next) { current = next; if (cb_menuChange) { MenuChangeEvent mce = { *current, *next }; (*cb_menuChange)(mce); } } } void foundShortkeyItem(MenuItem *mi) { mi->setBack(current); current = mi; } char canSearch(const char shortkey, MenuItem *m) { if (m==0) { return 0; } else { if (m->getShortkey()==shortkey) { foundShortkeyItem(m); return 1; } return -1; } } void rSAfter(const char shortkey, MenuItem *m) { if (canSearch(shortkey,m)!=1) { rSAfter(shortkey, m->getAfter()); rSRight(shortkey, m->getRight()); rSLeft(shortkey, m->getLeft()); } } void rSRight(const char shortkey, MenuItem *m) { if (canSearch(shortkey,m)!=1) { rSAfter(shortkey, m->getAfter()); rSRight(shortkey, m->getRight()); rSBefore(shortkey, m->getBefore()); } } void rSLeft(const char shortkey, MenuItem *m) { if (canSearch(shortkey,m)!=1) { rSAfter(shortkey, m->getAfter()); rSLeft(shortkey, m->getLeft()); rSBefore(shortkey, m->getBefore()); } } void rSBefore(const char shortkey, MenuItem *m) { if (canSearch(shortkey,m)!=1) { rSRight(shortkey, m->getRight()); rSLeft(shortkey, m->getLeft()); rSBefore(shortkey, m->getBefore()); } } void recursiveSearch(const char shortkey, MenuItem *m) { if (canSearch(shortkey,m)!=1) { rSAfter(shortkey, m->getAfter()); rSRight(shortkey, m->getRight()); rSLeft(shortkey, m->getLeft()); rSBefore(shortkey, m->getBefore()); } } MenuItem root; MenuItem *current; cb_change cb_menuChange; cb_use cb_menuUse; }; #endif Hier möchte ich den den Befehl dann ausführen: void menuChangeEvent(MenuChangeEvent changed) { lcd.setCursor(0, 0); lcd.print(changed.to.getName()); lcd.setCursor(0, 1); lcd.print(menu.getAfter()); Serial.print("Menu change "); Serial.print(changed.from.getName()); Serial.print(" "); Serial.println(changed.to.getName()); } Ich habe es auch schon mit lcd.at(3,2,menu.getCurrent().getRight(->getRight()->getName()); versucht aber lcd.at gibt nur fehler und mit Serial.print oder lcd.print das selbe. Ich versuche schon Tage lang ein Menü damit zu erstellen aber komme nicht weiter.
PS: Ich habe Testweise alle Klassen in Public geändert aber das ging auch nicht.
Sven schrieb: > class MenuItem { Das ist aber die Klasse MenuItem > inline MenuItem* getAfter() const { return after; } und die hat eine Methode getAfter Hier ist MenuBackend > > class MenuBackend { und die hat weit und breit keine Methode mit diesem Namen. Aber! > MenuItem &getCurrent() { > return *current; > } sie hat eine Methode getCurrent. Und getCurrent liefert dir ein MenuItem. Aaaahhhhaaaaa und ein MenuItem kann man mit getAfter nach seinem Nachfolger befragen! Da du wahrscheinlich mit 'menu' ein MenuBackend Objekt hast, muss es daher lauten menu.GetCurrent().getAfter(); Du musst nur lesen und darauf achten mit welchen Klassen du es zu tun hast!
Mist ich dachte du hast den durchblick aber bei Serial.print(menu.getCurrent().getAfter()); kommt nur: Menu_Versuch.cpp: In function 'void menuChangeEvent(MenuChangeEvent)': Menu_Versuch:67: error: call of overloaded 'print(MenuItem*)' is ambiguous C:\Users\x\Desktop\Microcontroller\arduino-1.0.1\hardware\arduino\cores\ arduino/Print.h:55: note: candidates are: size_t Print::print(char) <near match> C:\Users\x\Desktop\Microcontroller\arduino-1.0.1\hardware\arduino\cores\ arduino/Print.h:56: note: size_t Print::print(unsigned char, int) <near match> C:\Users\x\Desktop\Microcontroller\arduino-1.0.1\hardware\arduino\cores\ arduino/Print.h:57: note: size_t Print::print(int, int) <near match> C:\Users\x\Desktop\Microcontroller\arduino-1.0.1\hardware\arduino\cores\ arduino/Print.h:58: note: size_t Print::print(unsigned int, int) <near match> C:\Users\x\Desktop\Microcontroller\arduino-1.0.1\hardware\arduino\cores\ arduino/Print.h:59: note: size_t Print::print(long int, int) <near match> C:\Users\x\Desktop\Microcontroller\arduino-1.0.1\hardware\arduino\cores\ arduino/Print.h:60: note: size_t Print::print(long unsigned int, int) <near match>
Sven schrieb: > Mist ich dachte du hast den durchblick aber bei > Serial.print(menu.getCurrent().getAfter()); > kommt nur: > > Menu_Versuch.cpp: In function 'void menuChangeEvent(MenuChangeEvent)': > Menu_Versuch:67: error: call of overloaded 'print(MenuItem*)' is > ambiguous Was willst du denn mit der Serial.print Methode? Was kriegst du denn von getAfter() zurück? LIES DOCH EINFACH NUR DIE KLASSENDEFINITIONEN UND HÖR ENDLICH AUF ZU RATEN! Die Welt funktioniert nicht so, wie du dir das denkst und passt sich an dich an. Die Klassen, die Methoden sind dir vorgegeben. Und damit auch wie sie zu benutzen sind. inline MenuItem* getAfter() const { return after; } VOn getAfter kriegst du wieder ein MenuItem. Diesmal in Form eines Pointers (wahrscheinlich deshalb, weil ein Item keinen Nachfolger hat, dann liefert getAfter einen NULL Pointer). Also. WEnn du den Namen des Nachfolgers willst, musst du dir zuerst mal diesen Pointer holen MenuItem* after = menu.getCurrent().getAfter(); und wenn dieser Pointer nicht NULL ist if( after != NULL ) dann kann man ihn um seinen Namen befragen. after->getName(); und den auch ausgeben serial.print( after->getName() ); > > Mist ich dachte du hast den durchblick Lern du lieber erst mal lesen! Es steht alles im Header File. Ich hab die Klassen bis vor 2 Minute kein einziges mal gesehen und kann das in 15 Sekunden zusammensuchen, was du in 2 Tagen nicht schaffst. Es ist doch wirklich nicht schwer. Welche Klasse hat welche Methode und was liefert dir diese Methode? Und patsch, damit ist das im Handumdrehen auseinandersortiert.
Demnach muss es mit void menuChangeEvent(MenuChangeEvent changed) { MenuItem* after = menu.getCurrent().getAfter(); if( after != NULL ){ after->getName(); serial.print( after->getName() ); } } klappen? Sorry ich wollte nicht frech klingen ist nur so das ich erst dachte du schaffst das in 2 min was ich in 2 Tagen nicht geschafft hab.
Sven schrieb: > Sorry ich wollte nicht frech klingen ist nur so das ich erst dachte du > schaffst das in 2 min was ich in 2 Tagen nicht geschafft hab. Um die Zeit sitz ich nicht mehr dauernd vor dem PC und warte auf jemanden der weder Fehlermeldungen noch Klassendefinitionen liest. Der Compiler sagt dir sogar, wo das Problem liegt > Menu_Versuch:67: error: call of overloaded 'print(MenuItem*)' is ambiguous Es gibt keine print Methode, der du einen Pointer auf ein MenuItem Objekt übergeben könntest. LESEN was in der Fehlermeldung steht! Systematisch arbeiten: wovon ist in der Fehlermeldung die Rede? Und darus ergibt sich dann, wie es weitergehen muss.
Ja aber ich kann das Problem nicht alleine lösen. Mit pointern kenne ich mich nicht aus. Ich dachte dafür sind Libs da, um einen das Leben zu erleichtern. Wäre echt super wenn du mir helfen könntest muss ja nicht heute Abend sein...
Sven schrieb: > Ja aber ich kann das Problem nicht alleine lösen. > Mit pointern kenne ich mich nicht aus. Sorry. Aber das hier ist so einfach wie ein Teil aus der Lade A nehmen und in Lade B hineingeben. Alles was du tun musst: Wenn auf Lade B ein Zettel hängt "Bitte nur rote Rechtecke einwerfen", dann musst du dich daran halten. Mehr hast du damit nicht zu tun. Aus der einen Funktion bekommst du was und das gibst du in die nächste Funktion, die damit wieder was macht. Das ganze ist wie Verbinden von Punkten mit einem Kugelschreiber, bis du am Zielpunkt angelangt bist. Und wenn du damit nicht klar kommst, dann lern erst mal C++. brutal gesagt.
> Ich dachte dafür sind Libs da, um einen das Leben zu erleichtern. Noch einfacher können es dir die Leute aber wirklich nicht mehr machen. > Wäre echt super wenn du mir helfen könntest muss ja nicht heute Abend sein... Kopfschüttel. Du erkennst noch nicht mal, wenn ein Problem gelöst ist.
Sven schrieb: > Ja aber ich kann das Problem nicht alleine lösen. > Mit pointern kenne ich mich nicht aus. > Ich dachte dafür sind Libs da, um einen das Leben zu erleichtern. > Wäre echt super wenn du mir helfen könntest muss ja nicht heute Abend > sein... Hallo, ich habe im Sommer auch mit Arduino angefangen zu basteln. Das System ist hier im Forum wohl ziemlich verschrien, die meisten Teilnehmer hier sind wohl anderes gewöhnt als das. Ich bin jedenfalls schwer begeistert. Ja, Arduino-Libs sind dazu da, einem das Leben zu erleichtern. Falls möglich, versuche ich Dir weiterzuhelfen. Also als Hilfe vielleicht so viel: Jeder Hersteller einer Arduino-Library schreibt (mindestens) ein kleines Beispiel ("Example") wie diese Library verwendet wird. Sobald Du die Library installiert hast, findest Du das Programmierbeispiel zur Library unter "Datei - Beispiele - [Name der Library]", und da sind dann ggf. ein oder mehrere Beispiele, die Du laden und ausprobieren kannst. Frage: Wenn Du das Beispiel zur MenuBackend Library ausprobierst, funktioniert es dann, also kann es fehlerfrei compiliert, gestartet und ausgeführt werden? Oder treten dabei Fehler auf? Wenn Fehler auftreten, gleich zwei weitere Rückfragen: - Welche Versionsnummer hat die Library? - Welche Versionsnummer hat die Arduino-Entwicklungsumgebung? Hinweis: Insbesondere bei älteren Libraries, die länger kein Update mehr hatten, kommt es oft vor, dass diese Library nicht kompatibel ist zu Arduino-Versionen ab 1.0 oder höher, sondern nur zu den Arduino-Versionsnummern unterhalb 1.0. Also welche Versionen von Library und von Arduino hast Du in Verwendung?
Also das Beispiel hab ich mir angeschaut und verstehe es auch soweit. Ich hab ja eigentlich schon mein Menü fertig nur bei der ausgabe hapert es. Wie Funktionen funktionieren weiß ich grob auch. Ich habe es jetzt soweit verstanden, das ich nur noch die Ausgabe eines Pointers realisieren muss. Ich schau mal ob ich es schaffe.
Ich habe es nun geschafft mein Menu auszugeben nur hab ich noch ein (ich hoffe letztes problem) und zwar: Seite 1 MenuItem* line101 = menu.getRoot().getAfter(); Seite 2 MenuItem* line201 = menu.getRoot().getRight()->getAfter(); es wird nach rechts geblättert. Kann ich nun das was in line201 steht beim eintreffen eine bedingung in line101 schreiben? (Sorry ich weiß nicht wie ich es erklären soll aber es sollte ca. so aussehen: MenuItem* line100 = menu.getRoot().getAfter()->getRight(); //Wenn das Menu Rechts ausgerufen wird if (changed.to.getName() == line100->getName()){ MenuItem* i = *line202; } //Hier soll immer die Richtig Seite angezeigt werden lcd.print(i->getName()); Nur ich bekomme nur Müll angezeit. Was mach ich falsch? Oder gibt es eine andere Lösung, außer die lcd.print Ausgabe für jede Seite neu zu schreiben?
#include <LiquidCrystal.h> #include <MenuBackend.h> LiquidCrystal lcd(8, 9, 10, 11, 12, 13); /* This is the structure of the modelled menu werte zustand temp soll temp rlf soll ldr wert */ //this controls the menu backend and the event generation MenuBackend menu = MenuBackend(menuUseEvent,menuChangeEvent); //beneath is list of menu items needed to build the menu MenuItem miLine100 = MenuItem("Ueberschrift 1"); MenuItem miLine101 = MenuItem("Line 1,1"); MenuItem miLine102 = MenuItem("Line 1,2"); MenuItem miLine103 = MenuItem("Line 1,3"); MenuItem miLine104 = MenuItem("Line 1.4",'T'); MenuItem miLine105 = MenuItem("Line 1.5"); MenuItem miLine200 = MenuItem("Ueberschrift 2"); MenuItem miLine201 = MenuItem("Line 2.1"); MenuItem miLine202 = MenuItem("Line 2.2"); //this function builds the menu and connects the correct items together void menuSetup() { Serial.println("Setting up menu..."); lcd.begin(20, 4); menu.getRoot().add(miLine100); miLine100.add(miLine101).add(miLine102).add(miLine103).add(miLine104).ad d(miLine105); miLine100.addRight(miLine200).add(miLine201); } /* This is an important function Here all use events are handled This is where you define a behaviour for a menu item */ void menuUseEvent(MenuUseEvent used) { Serial.print("Menu use "); Serial.println(used.item.getName()); if (used.item == miLine100) //comparison agains a known item { Serial.println("Menu Line 100"); } } /* This is an important function Here we get a notification whenever the user changes the menu That is, when the menu is navigated */ void menuChangeEvent(MenuChangeEvent changed) { Serial.print("Menu change: "); Serial.print("->"); Serial.println(changed.to.getName()); MenuItem newMenuItem=changed.to; //get the destination menu MenuItem* line100 = menu.getRoot().getAfter()->getRight(); line100->getName(); MenuItem* line101 = menu.getRoot().getAfter(); MenuItem* line102 = menu.getRoot().getAfter()->getAfter(); MenuItem* line103 = menu.getRoot().getAfter()->getAfter()->getAfter(); MenuItem* line104 = menu.getRoot().getAfter()->getAfter()->getAfter()->getAfter(); MenuItem* line201 = menu.getRoot().getRight()->getAfter(); MenuItem* line202 = menu.getRoot().getRight()->getAfter()->getAfter(); MenuItem* line203 = menu.getRoot().getRight()->getAfter()->getAfter()->getAfter(); MenuItem* line204 = menu.getRoot().getRight()->getAfter()->getAfter()->getAfter()->getAfter( ); MenuItem* i = line103; if (changed.to.getName() == line100->getName()){ Serial.println("Es geht"); MenuItem* i = line201; } lcd.clear(); if (changed.to.getName() == line101->getName()){ lcd.setCursor(10, 0); Serial.println("Jetzt"); } lcd.setCursor(0, 0); //lcd.print(line101->getName()); //lcd.setCursor(10, 0); lcd.print(i->getName()); line102->getName(); if(line102 != NULL){ if (changed.to.getName() == line102->getName()){ lcd.setCursor(0, 1); lcd.print(">"); } lcd.setCursor(1, 1); lcd.print(line102->getName()); } line103->getName(); if(line103 != NULL){ if (changed.to.getName() == line103->getName()){ lcd.setCursor(0, 2); lcd.print(">"); } lcd.setCursor(1, 2); lcd.print(line103->getName()); } line104->getName(); if(line104 != NULL){ if (changed.to.getName() == line104->getName()){ lcd.setCursor(0, 3); lcd.print(">"); } lcd.setCursor(1, 3); lcd.print(line104->getName()); } } /* MenuItem newMenuItem=changed.to; //get the destination menu if(newMenuItem.getName()==menu.getRoot()){ lcd.print("Main Menu "); } //Serial.print("Menu change: "); Serial.print("<-"); Serial.println(changed.to.getName()); //Serial.print(1,1,menu.getCurrent().getAfter()); //Serial.println(3,2,menu.getCurrent().getRight()->getRight()->getName() ); char *charZeiger; // Definition der Zeigervariable charZeiger = 0; // Sichern als Nullzeiger char Buchstabe = 'A'; // Variable soll später das Ziel sein charZeiger = &Buchstabe; // Adresse von Buchstabe zuweisen *charZeiger = 'B'; // Buchstabe enthält nun 'B' lcd.print(); */ void setup() { Serial.begin(9600); menuSetup(); Serial.println("Starting navigation:\r\nUp: w Down: s Left: a Right: d Use: e"); } void loop() { if (Serial.available()) { byte read = Serial.read(); switch (read) { case 'w': menu.moveUp(); break; case 's': menu.moveDown(); break; case 'd': menu.moveRight(); break; case 'a': menu.moveLeft(); break; case 'e': menu.use(); break; case 'q': menu.use('Z'); break; case 'r': menu.toRoot(); break; } } }
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.