2023-05-31 09:02 PM - edited 2023-11-20 04:16 AM
I'm fairly new to TouchGFX as well as C++ inheritance so trying to understand how to implement a custom virtual function when a key is released. I see when I create an interaction in touchGFX so when a key is pressed it calls a virtual function...
Which creates the following in the base class of the custom container...
I understand how to override the startBrewCycle() virtual function in the non-base cpp file which is called with the pressed even in the callback below...
How can I implement another virtual function stopBrewCycle() when the same button is released?
Solved! Go to Solution.
2023-06-01 11:22 AM
Hello
I found my old example, just modify it for flexbutton, maybe this helps. The flexButton click handler is bit more tricky than other button types. Here in the example flexbutton has just Box with border- element.
------
One way is to create ClickListener to the FlexButton, so set it on at Mixins of your flexButton:
Then add the callback definitions to the screen1.hpp (or whatever you have)
class Screen1View : public Screen1ViewBase
{
public:
Screen1View();
virtual ~Screen1View() {}
virtual void setupScreen();
virtual void tearDownScreen();
// Add this public function definition:
void flexButtonClickHandler(const touchgfx::BoxWithBorderButtonStyle< touchgfx::TouchButtonTrigger > & ,const ClickEvent& e);
// int16_t pressCount=0;
// int16_t releaseCount=0;
protected:
// And add this protected function definition:
Callback<Screen1View, const touchgfx::BoxWithBorderButtonStyle< touchgfx::TouchButtonTrigger > &,const ClickEvent&> flexButtonClickedCallback;
};
and then in screen1.cpp:
#include <gui/screen1_screen/Screen1View.hpp>
#include <touchgfx/Utils.hpp>
// Add this callback to the constructor:
Screen1View::Screen1View():
flexButtonClickedCallback(this,&Screen1View::flexButtonClickHandler)
{
}
void Screen1View::setupScreen()
{
Screen1ViewBase::setupScreen();
// This sets the click action for flexButton1 !!
flexButton1.setClickAction(flexButtonClickedCallback);
}
void Screen1View::tearDownScreen()
{
Screen1ViewBase::tearDownScreen();
}
// Add this function
void Screen1View::flexButtonClickHandler(const touchgfx::BoxWithBorderButtonStyle< touchgfx::TouchButtonTrigger >& b,const ClickEvent& e)
{
if(&b==&flexButton1) // button1 -> your button name
{
switch(e.getType())
{
case ClickEvent::PRESSED:
touchgfx_printf("Pressed flexButton1 \r\n");
//pressCount++;
break;
//case ClickEvent::RELEASED:
//case ClickEvent::CANCEL:
default:
touchgfx_printf("Released or Cancel flexButton1 \r\n");
//releaseCount++;
// this handles REALEASED and CANCEL- events !
break;
}
//This is just debug print to display, since its tested also in device :
//Unicode::snprintf(CounterBuffer, COUNTER_SIZE, "press:%3u release:%3u",pressCount,releaseCount);
//Counter.invalidate();
}
}
Please note that this works only with flexButton that has only Box with border. If you have some other elements, check in screen1base.hpp the inheritance structure of your flexButton
/* Screen1ViewBase.hpp
* Member Declarations
*/
// HERE !!:
touchgfx::ClickListener< touchgfx::BoxWithBorderButtonStyle< touchgfx::TouchButtonTrigger > > flexButton1;
Only BoxWithBorder:
touchgfx::ClickListener< touchgfx::BoxWithBorderButtonStyle< touchgfx::TouchButtonTrigger > > flexButton1;
All 4 elements:
touchgfx::ClickListener< touchgfx::IconButtonStyle< touchgfx::TextButtonStyle< touchgfx::ImageButtonStyle< touchgfx::BoxWithBorderButtonStyle< touchgfx::TouchButtonTrigger > > > > > flexButton1;
This case you must replace the callback and clickHandler function parameters to match your flexbutton elements at in Screen1.cpp and .hpp !
Example is tested with Simulator and F769IDisco evalkit. BTW what hardware you are using ?
2023-06-01 11:22 AM
Hello
I found my old example, just modify it for flexbutton, maybe this helps. The flexButton click handler is bit more tricky than other button types. Here in the example flexbutton has just Box with border- element.
------
One way is to create ClickListener to the FlexButton, so set it on at Mixins of your flexButton:
Then add the callback definitions to the screen1.hpp (or whatever you have)
class Screen1View : public Screen1ViewBase
{
public:
Screen1View();
virtual ~Screen1View() {}
virtual void setupScreen();
virtual void tearDownScreen();
// Add this public function definition:
void flexButtonClickHandler(const touchgfx::BoxWithBorderButtonStyle< touchgfx::TouchButtonTrigger > & ,const ClickEvent& e);
// int16_t pressCount=0;
// int16_t releaseCount=0;
protected:
// And add this protected function definition:
Callback<Screen1View, const touchgfx::BoxWithBorderButtonStyle< touchgfx::TouchButtonTrigger > &,const ClickEvent&> flexButtonClickedCallback;
};
and then in screen1.cpp:
#include <gui/screen1_screen/Screen1View.hpp>
#include <touchgfx/Utils.hpp>
// Add this callback to the constructor:
Screen1View::Screen1View():
flexButtonClickedCallback(this,&Screen1View::flexButtonClickHandler)
{
}
void Screen1View::setupScreen()
{
Screen1ViewBase::setupScreen();
// This sets the click action for flexButton1 !!
flexButton1.setClickAction(flexButtonClickedCallback);
}
void Screen1View::tearDownScreen()
{
Screen1ViewBase::tearDownScreen();
}
// Add this function
void Screen1View::flexButtonClickHandler(const touchgfx::BoxWithBorderButtonStyle< touchgfx::TouchButtonTrigger >& b,const ClickEvent& e)
{
if(&b==&flexButton1) // button1 -> your button name
{
switch(e.getType())
{
case ClickEvent::PRESSED:
touchgfx_printf("Pressed flexButton1 \r\n");
//pressCount++;
break;
//case ClickEvent::RELEASED:
//case ClickEvent::CANCEL:
default:
touchgfx_printf("Released or Cancel flexButton1 \r\n");
//releaseCount++;
// this handles REALEASED and CANCEL- events !
break;
}
//This is just debug print to display, since its tested also in device :
//Unicode::snprintf(CounterBuffer, COUNTER_SIZE, "press:%3u release:%3u",pressCount,releaseCount);
//Counter.invalidate();
}
}
Please note that this works only with flexButton that has only Box with border. If you have some other elements, check in screen1base.hpp the inheritance structure of your flexButton
/* Screen1ViewBase.hpp
* Member Declarations
*/
// HERE !!:
touchgfx::ClickListener< touchgfx::BoxWithBorderButtonStyle< touchgfx::TouchButtonTrigger > > flexButton1;
Only BoxWithBorder:
touchgfx::ClickListener< touchgfx::BoxWithBorderButtonStyle< touchgfx::TouchButtonTrigger > > flexButton1;
All 4 elements:
touchgfx::ClickListener< touchgfx::IconButtonStyle< touchgfx::TextButtonStyle< touchgfx::ImageButtonStyle< touchgfx::BoxWithBorderButtonStyle< touchgfx::TouchButtonTrigger > > > > > flexButton1;
This case you must replace the callback and clickHandler function parameters to match your flexbutton elements at in Screen1.cpp and .hpp !
Example is tested with Simulator and F769IDisco evalkit. BTW what hardware you are using ?
2023-06-06 02:17 AM
Hello PFlor.2,
This thread also treats this subject, but it's pretty much what JTP wrote, I think his answer is good.
Basically, you'll need to get the event type of your click and this is what he's doing in here :
switch(e.getType())
{
case ClickEvent::PRESSED:
...
/Osman
2023-06-06 07:40 AM
Thanks for this information, I think this is exactly what I need. I've been working on other aspects but will try this out shortly.
I also need to be able to trigger a virtual function once the button has been held down for 2 seconds as well but think I could use aspects of this for that as well. Maybe wait 2 seconds after the initial press then check to see if still isPressed or not.
Using STM32H643 on custom hardware.
2023-06-06 09:08 AM
Note also that you can do this system without new callbacks, just use handleTickEvent. This handleTickEvent will be called automatically with in every frame. This is not the most elegant way but it does it job:
// add to view.hpp:
void handleTickEvent();
bool exButtonPressed=0;
uint32_t ButtonPressedTimeCounter=0;
// add to view.cpp:
void Screen1View::handleTickEvent()
{
bool buttonPressedNow;
buttonPressedNow=yourFlexButton.getPressed();
if(buttonPressedNow)
{
if(exButtonPressed==0)
{
// handle button pressed down if needed
ButtonPressedTimeCounter=0;
}
else // also last time was pressed
{
// note that this increment can overflow, it takes years
// of continuos press but anyway.
// It could have some protection like
// if(ButtonPressedTimeCounter<0xFFFFFFFF)
ButtonPressedTimeCounter++;
//replace '120' with your 2 sec frame rate
if(ButtonPressedTimeCounter==120)
{
// handle 2 sec button pressed
}
}
}
else // not pressed now
{
// last time was ?
if(exButtonPressed)
{
// handle button released
}
}
exButtonPressed=buttonPressedNow;
}
2023-07-06 02:32 PM - edited 2023-07-06 02:33 PM
2023-07-06 09:17 PM
Hello. Hmm...did you put 'setAction' - call to the 'initialize' - function ? Otherwise it looks ok with quick review.
You can also test the functionality by changing trigger to 'click' instead of repeat, i have never use click callbacks with repeat button.
Br. J.T
2023-08-09 12:21 PM - edited 2023-08-09 12:48 PM
was missing the setAction in initialize, thanks so much for the assitance
2023-08-09 12:45 PM
Thanks JTP1...I was missing the setAction. Totally missed you had sent a reply on 7/6. Thanks again for the assistance!