3

I am trying to write some code to make it easy to add different buttons to a touch screen. I need each object to be a different object of class 'touchButton'. I'd like to be able to run a touchButton.Draw function, which in turn will run LCD library commands. Is there a way I could do that? Here is my source code:

TouchScreen.ino:

#include "touchButton.h"
#include <UTFT.h>
#include <UTouch.h>
#include <avr/pgmspace.h>
UTFT    myGLCD(ITDB32S, 38, 39, 40, 41);
UTouch  myTouch( 6, 5, 4, 3, 2);
extern uint8_t SmallFont[];

void setup() {
  myGLCD.InitLCD();
  myGLCD.setFont(SmallFont);
  myGLCD.clrScr();
  myTouch.InitTouch();
  myTouch.setPrecision(PREC_MEDIUM);
  myGLCD.fillScr(51, 51, 51);
  //what I want to be able to do:
  //touchButton Button1 (10, 10, 20, 20, 'p');
  //Button1.Draw();
}

void loop() {
}

touchButton.h

#ifndef touchButton_h
#define touchButton_h
#include "Arduino.h"
class touchButton {
  public:
    touchButton(int x, int y, int xs, int ys, char use);
    void Draw();
    int x1;
    int y1;
    int xsize;
    int ysize;
    char use;
    boolean toggle = false;
};
#endif

touchButton.cpp

  #include "Arduino.h"
  #include "touchButton.h"
  touchButton::touchButton(int x, int y, int xs, int ys, char myuse) {
    x1 = x;
    y1 = y;
    xsize = xs;
    ysize = ys;
    use = myuse;
  }

  void touchButton::Draw() {
    switch (use) {
      case 'p':
      //this is what I would like to have called from the main file.
      //myGLCD.drawRoundRect(x1, y1, x1+xsize, y1+ysize);
        break;

       default:
        break;
    }
  }

4 Answers 4

2

The best way is to provide the myGLCD object as a parameter to the constructor:

touchButton::touchButton(UTFT &glcddev, int x, int y, int xs, int ys, char myuse) {
  x1 = x;
  y1 = y;
  xsize = xs;
  ysize = ys;
  use = myuse;
  glcd = &glcddev;
}

Then in your header you provide a:

private: 
  UTFT *glcd;

Your library code then uses the glcd pointer to the object:

glcd->drawRoundedRectangle(...);

Note the use of -> since glcd is a pointer to the object (as created by the & operator when it was assigned in the constructor).

Of course, as Miagma mentions, you need to ensure that anywhere that references any UTFT functions or objects has the UTFT.h header included or it won't know what you're talking about.

You can also do the same with the UTouch class - pass that object as a parameter, then each widget can have its own routine to deal with the touch events.

You can see all this kind of thing in action in the same context in the Widget class of my DisplayCore system for chipKIT boards:

2

The simplest solution (ignoring possible improvements) is to add the following to touchButton.cpp.

#include "Arduino.h"
#include "touchButton.h"

// Extern reference to the LCD instance
#include <UTFT.h>
extern UTFT myGLCD;

touchButton::touchButton(int x, int y, int xs, int ys, char myuse) {
  x1 = x;
  y1 = y;
  xsize = xs;
  ysize = ys;
  use = myuse;
}

void touchButton::Draw() {
  switch (use) {
    case 'p':
      myGLCD.drawRoundRect(x1, y1, x1+xsize, y1+ysize);
    break;

   default:
    break;
  }
}

There are several improvements such as passing the UTFT instance reference as parameter, moving myGLCD to a separate .h/.cpp file, etc.

An example of "extern" object reference may be found in HardwareSerial.h.

Cheers!

0

I'm not 100% certain I understand what you mean. It's clear that you understand object-oriented code and some of the murkier aspects of c++, judging from what you wrote.

I apologize if you already know this (and I'm guessing you do) or if this is completely off base, but your code should already work. That is, you defined your class in your header, implemented it in the .cpp file, and then instantiated it in the .ino file. If you want to operate on it in another file, you could declare the variable as an "extern" data type, which is rather dangerous, or pass it as a reference to a function in another file.

However, I don't believe this is what you mean. From reading your code, I feel that you're asking how you can execute function "x" from another object every time you create a button.

If this is the case, it's definitely possible. myGLCD looks like it's an object (can't read it at the moment), which is good. What you can do is declare your touchLCD class as a derived class of whomever myGLCD belongs to -adding the appropriate header of course:

#include <Parent Class Name.h>

class touchLCD : public <Parent Class Name>.

If the functions you want are public or protected, then you can access them without restriction. Here you have a few options. The easiest would probably be calling the function from within the constructor. If you don't have access to the desired function, you'll have to define your class as a friend class.

Hope this helps.

0

You are asking a question that can be considered as the classical:

"is a" vs. "has a"

If you want, you can find more details here.

On this specific case, I sort of agree with Majenko, that proposes to pass the address of the LCD object to each button, but I would prefer a different implementation where the pointer is stored in a static field shared by all the instances of touchButton, because you are always referring to the same object. That will of course change if you have more than 1 LCD.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.