I'm writing a new Arduino project that uses an 16x2 LCD Crystal Display with a KeyShield. I would like to construct a menu structure in which the user can navigate using the buttons.
I'm new to Arduino but I do have 5 yrs experience in C#. What I would like to do is the following:
Define an interface called Screen
and inherit each Screen from it such as LanguageScreen
, TurnOffAfterScreen
, MainScreen
, etc. Each specialized Screen implements a method called drawScreen
that will take care of the screen content.
Now I would like to have a class named ScreenController
that handles the navigation between the Screens. In this class I'd like to store the screens in an array Screen screens[3]
.
When user presses the Select
button on the KeyShield the Controller would call the next Screen's drawScreen
method something like this:
void showNextScreen()
{
currentScreen++;
screens[currentScreen]->drawScreen();
}
Is this possible to do in an Arduino project? Am I expecting too much? :)
2 Answers 2
class Screen {
public:
virtual void drawScreen() = 0; // Needs to be implemented by each subclass
virtual ~Screen() {} // Destructor
};
class LanguageScreen : public Screen {
public:
virtual void drawScreen();
};
class MainScreen : public Screen {
public:
virtual void drawScreen();
};
void LanguageScreen::drawScreen() {
// Draw language screen
}
void MainScreen::drawScreen() {
// Draw main screen
}
MainScreen mainScreen;
LanguageScreen languageScreen;
Screen *const screens[2] = {&mainScreen, &languageScreen};
int currenScreen = 0;
-
2\$\begingroup\$ It would be a good idea to avoid calling new in a microcontroller example. Declare them as statics/globals and then use their addresses. \$\endgroup\$walrii– walrii2013年06月19日 00:15:33 +00:00Commented Jun 19, 2013 at 0:15
-
\$\begingroup\$ Good point, @walrii. I’ve revised the code to do that. \$\endgroup\$microtherion– microtherion2013年06月19日 01:28:43 +00:00Commented Jun 19, 2013 at 1:28
-
\$\begingroup\$ Thank you so much! This was quite helpful. Now I have good menu structure using well defined OOP code :) \$\endgroup\$papaiatis– papaiatis2013年06月20日 18:19:17 +00:00Commented Jun 20, 2013 at 18:19
-
\$\begingroup\$ I'm coming from PHP and I'm expecting to get an error message if I don't implement a method in a class that's based on an interface.
class Screen { public: virtual void drawScreen() = 0; // Needs to be implemented by each subclass virtual ~Screen() {} // Destructor }; class LanguageScreen : public Screen { // I didn't define the void drawScreen(); };
So I actually want to get a message that the method drawScreen() is missing in the class LanguageScreen since it implements the "interface" class Screen. Or is this different to PHP? \$\endgroup\$alve89– alve892020年01月21日 08:44:13 +00:00Commented Jan 21, 2020 at 8:44 -
1\$\begingroup\$ @alve89 if you try this in C++, you will find that the
= 0;
in the original declaration will also guarantee an error message if you try to use a subclass that does not implementdrawScreen
. The difference is that you can inherit over multiple levels, and only one of them needs to implement the method. \$\endgroup\$microtherion– microtherion2020年01月23日 02:23:02 +00:00Commented Jan 23, 2020 at 2:23
C++ using classes on a microcontroller with limited memory is generally not considered to be a viable development strategy. There are literally limitless ways that you can construct a "menu system" on a display without having to resort to resource intensive OOP programming style.
Edit: I am amazed at the reader reaction to putting a lot of down votes to my answer. I can tell you that with over 30 years of experience in developing code and firmware solutions for microcontrollers of many sorts that there is truth to the statement of my answer. There are loads of applications using low performance MCUs (in comparison to their big brothers in PCs and the like) where the program at times even needs to be coded in assembly language to get the job done in a efficient and low latency way.
-
2\$\begingroup\$ It won't be that big project so I'm not afraid of running out of memory. I prefer OOP to spagetti code. \$\endgroup\$papaiatis– papaiatis2013年06月18日 19:47:38 +00:00Commented Jun 18, 2013 at 19:47
-
2\$\begingroup\$ @papaiatis - A menu system can be coded in nice clean programming style in C or even Assembly language without it turning into spagetti code. The latter mess of code usually results when you try to program something up by the seat of the pants without taking the time to do a full architectural design of the intended functionality tp be developed. \$\endgroup\$Michael Karas– Michael Karas2013年06月18日 19:57:39 +00:00Commented Jun 18, 2013 at 19:57
-
\$\begingroup\$ You might be right I have no doubt. But I'm still rather interested in the OOP way. \$\endgroup\$papaiatis– papaiatis2013年06月18日 20:05:52 +00:00Commented Jun 18, 2013 at 20:05
-
5\$\begingroup\$ The Arduino I/O library is in fact a very conventional OOP design, constructed around a set of classes with virtual methods. There is little in OOP programming style which is inherently "resource intensive". \$\endgroup\$microtherion– microtherion2013年06月18日 20:47:15 +00:00Commented Jun 18, 2013 at 20:47
-
1\$\begingroup\$ I concur - given the limited memory on these puppies, you are right on the money with your answer. I also dislike the buttons on these LCD shields, as they use variable resistance for each button through an analog input, and the shield I have gives some wildly different values each time. \$\endgroup\$Ron J.– Ron J.2013年06月19日 12:53:53 +00:00Commented Jun 19, 2013 at 12:53
Screen
would have to be an (abstract) base class, and your array would have to beScreen * screens[3]
. \$\endgroup\$