cancel
Showing results for 
Search instead for 
Did you mean: 

long touch detect on STM32L4R9AI-eval

prathima
Associate II

hello...

I am working on STM32L4R9AI-EVAL board..i want to detect the long touch..means in one screen if i do long touch it has to go to the other screen...I need deep explanation

how do i do this ....any example code

thank you

1 ACCEPTED SOLUTION

Accepted Solutions
Alexandre RENOUX
Principal

A way of doing that is to create a button class that allows you to receive an event on both press and release action. Then, you just implement the handleTickEvent() in your screenView. As @Martin KJELDSEN​ mentioned, referring to Button, AbstractButton and at the code generated when creating a FlexButton in the Designer can help you considerably.

Here is a possible version :

customButtonContainer.hpp

#ifndef CUSTOMBUTTONCONTAINER_HPP
#define CUSTOMBUTTONCONTAINER_HPP
 
#include <touchgfx/containers/Container.hpp>
#include <touchgfx/widgets/Image.hpp>
 
namespace touchgfx
{
/**
 * @class CustomButtonTrigger CustomButtonTrigger.hpp
 */
class CustomButtonContainer : public Container
{
public:
 
    /**
     * @fn CustomButtonContainer::CustomButtonContainer()
     *
     * @brief Default constructor.
     */
    CustomButtonContainer() : pressed(false), alpha(255), up(), down(), action(0)
    {
        setTouchable(true);
        buttonImage.setXY(0, 0);
        add(buttonImage);
    }
 
    /**
     * @fn virtual CustomButtonContainer::~CustomButtonContainer()
     *
     * @brief Destructor.
     */
    virtual ~CustomButtonContainer() {}
 
    /**
     * @fn virtual void CustomButtonContainer::setBitmaps(const Bitmap& bmpReleased, const Bitmap& bmpPressed)
     *
     * @brief Sets the bitmaps.
     *
     * @param bmpReleased The bitmap released.
     * @param bmpPressed  The bitmap pressed.
     */
    virtual void setBitmaps(const Bitmap& bmpReleased, const Bitmap& bmpPressed)
    {
        up = bmpReleased;
        down = bmpPressed;
        setWidth(down.getWidth());
        setHeight(down.getHeight());
 
        handlePressedUpdated();
    }
 
    /**
     * @fn void CustomButtonContainer::setBitmapXY(uint16_t x, uint16_t y)
     *
     * @brief Sets bitmap xy.
     *
     * @param x An uint16_t to process.
     * @param y An uint16_t to process.
     */
    void setBitmapXY(uint16_t x, uint16_t y)
    {
        buttonImage.setXY(x, y);
    }
 
    /**
     * @fn Bitmap CustomButtonContainer::getCurrentlyDisplayedBitmap() const
     *
     * @brief Gets currently displayed bitmap.
     *
     * @return The currently displayed bitmap.
     */
    Bitmap getCurrentlyDisplayedBitmap() const
    {
        return (pressed ? down : up);
    }
 
    /**
     * @fn void CustomButtonContainer::setPressed(bool isPressed)
     *
     * @brief Sets the pressed state.
     *
     * @param isPressed True if is pressed, false if not.
     */
    void setPressed(bool isPressed)
    {
        pressed = isPressed;
        handlePressedUpdated();
    }
 
    /**
     * @fn bool CustomButtonContainer::getPressed()
     *
     * @brief Gets the pressed state.
     *
     * @return True if it succeeds, false if it fails.
     */
    bool getPressed()
    {
        return pressed;
    }
 
    /**
     * @fn void CustomButtonContainer::setAlpha(uint8_t newAlpha)
     *
     * @brief Sets an alpha value.
     *
     * @param newAlpha The new alpha.
     */
    void setAlpha(uint8_t newAlpha)
    {
        alpha = newAlpha;
        handleAlphaUpdated();
    }
 
    /**
     * @fn uint8_t CustomButtonContainer::getAlpha() const
     *
     * @brief Gets the alpha.
     *
     * @return The alpha value.
     */
    uint8_t getAlpha() const
    {
        return alpha;
    }
 
    /**
     * @fn void CustomButtonContainer::setAction(GenericCallback< const CustomButtonContainer&, bool& >& callback)
     *
     * @brief Sets an action callback.
     *
     * @param callback The callback.
     */
    void setAction(GenericCallback< const CustomButtonContainer&, bool& >& callback)
    {
        action = &callback;
    }
 
    /**
     * @fn virtual void CustomButtonContainer::handleClickEvent(const ClickEvent& event)
     *
     * @brief Handles the click event described by event.
     *
     * @param event The event.
     */
    virtual void handleClickEvent(const ClickEvent& event)
    {
        bool wasPressed = getPressed();
        bool newPressedValue = (event.getType() == ClickEvent::PRESSED);
        if ((newPressedValue && !wasPressed) || (!newPressedValue && wasPressed))
        {
            setPressed(newPressedValue);
            invalidate();
            if (action->isValid())
            {
                action->execute(*this, pressed);
            }
        }
    }
 
    
protected:
    bool pressed;        ///< True if pressed
    uint8_t alpha;       ///< The current alpha value. 255 denotes solid, 0 denotes completely transparent.
    Image buttonImage; ///< The button image
    Bitmap  up;        ///< The image to display when button is released.
    Bitmap  down;      ///< The image to display when button is pressed.
 
    GenericCallback< const CustomButtonContainer&, bool&>* action;  ///< The action
 
    /**
     * @fn virtual void CustomButtonContainer::handlePressedUpdated()
     *
     * @brief Handles the pressed updated.
     */
    virtual void handlePressedUpdated() 
    {
        buttonImage.setBitmap(pressed ? down : up);
    }
 
    /**
     * @fn virtual void CustomButtonContainer::handleAlphaUpdated()
     *
     * @brief Handles the alpha updated.
     */
    virtual void handleAlphaUpdated()
    {
        buttonImage.setAlpha(alpha);
    }
};
 
 
} // namespace touchgfx
 
#endif // CUSTOMBUTTONCONTAINER_HPP

Screen1View.hpp

#ifndef SCREEN1VIEW_HPP
#define SCREEN1VIEW_HPP
 
#include <gui_generated/screen1_screen/Screen1ViewBase.hpp>
#include <gui/screen1_screen/Screen1Presenter.hpp>
#include <gui/common/customButtonContainer.hpp>
 
class Screen1View : public Screen1ViewBase
{
public:
    Screen1View();
    virtual ~Screen1View() {}
    virtual void setupScreen();
    virtual void tearDownScreen();
 
    virtual void handleTickEvent();
protected:
    touchgfx::CustomButtonContainer customButton1, customButton2;
 
    uint16_t counter;
    bool buttonPressedFlag;
 
    Callback<Screen1View, const CustomButtonContainer&, bool&> buttonEventCallback;
 
    void handleButtonEvent(const CustomButtonContainer& element, bool& buttonState);
};
 
#endif // SCREEN1VIEW_HPP

Screen1View.cpp

#include <gui/screen1_screen/Screen1View.hpp>
#include "BitmapDatabase.hpp"
 
Screen1View::Screen1View():
    counter(0),
    buttonPressedFlag(false),
    buttonEventCallback(this, &Screen1View::handleButtonEvent)
{
    customButton1.setBitmaps(Bitmap(BITMAP_BLUE_BUTTONS_ROUND_EDGE_MEDIUM_ID), Bitmap(BITMAP_BLUE_BUTTONS_ROUND_EDGE_MEDIUM_PRESSED_ID));
    customButton1.setBitmapXY(0, 0);
    customButton1.setPosition(285, 200, 230, 60);
 
    customButton2.setBitmaps(Bitmap(BITMAP_BLUE_BUTTONS_ROUND_EDGE_MEDIUM_ID), Bitmap(BITMAP_BLUE_BUTTONS_ROUND_EDGE_MEDIUM_PRESSED_ID));
    customButton2.setBitmapXY(0, 0);
    customButton2.setPosition(20, 20, 230, 60);
 
    add(customButton1);
    add(customButton2);
 
    customButton1.setAction(buttonEventCallback);
    customButton2.setAction(buttonEventCallback);
}
 
void Screen1View::setupScreen()
{
    Screen1ViewBase::setupScreen();
}
 
void Screen1View::tearDownScreen()
{
    Screen1ViewBase::tearDownScreen();
}
 
void Screen1View::handleButtonEvent(const CustomButtonContainer& element, bool& buttonState)
{
    if(buttonState)
    {
        if(&element == &customButton1)
        {
            touchgfx_printf("pressed 1\n");
            buttonPressedFlag = true;
        }
        else if(&element == &customButton2)
        {
            touchgfx_printf("pressed 2\n");
        }
    }
    else
    {
        if(&element == &customButton1)
        {
            touchgfx_printf("released 1\n");
            buttonPressedFlag = false;
            counter = 0;
        }
        else if(&element == &customButton2)
        {
            touchgfx_printf("released 2\n");
        }
    }
}
 
void Screen1View::handleTickEvent()
{
   if(buttonPressedFlag)
   {
       counter++;
       if(counter%180 == 0) // 3 seconds has passed
       {
           //move to another screen
       }
   }
}

/Alexandre

View solution in original post

14 REPLIES 14
Martin KJELDSEN
Chief III

Look at how a Button and AbstractButton is implemented. The callback is fired, in the case of a normal button, when the user presses the button (not releases). It's easy to create your own subclass LongPressButton that registers itself to receive ticks, and you simply count those until you're satisfied and fire the event once the press is "long".

I've written this button a thousand times, so i'll look around my harddrive 🙂 But until them, look at Button, AbstractButton and look for widgets that register themselves as "Timer widgets". You should be able to do it easily. Source code for a lot of widgets is available in the distribution.

/Martin

Martin KJELDSEN
Chief III

Okay, this explains how to register a widget as a timer widget to receive ticks - Hence the handleTickEvent() method. I'll leave it up to you to decide how you want to call fadeIn() - Take a look at Button and AbstractButton and see how Button offers pressed/released images and how AbstractButton offers a clickHandler() - Combine the two to get what you want. E.g. once the button is pressed, call fadeIn() (could be private function) - handleTickEvent() will be called every tick. Unregister timer widget once number of ticks = long press, and invoke the callback (check AbstractButton to see how this is done).

So, the code below is just to show you how to register timer widgets and react to ticks. The FadeButton actually does not handle fadeIn() internally.

void FadeButton::fadeIn()
{
    fadingOut = false;
    Application::getInstance()->registerTimerWidget(this);
}
 
void FadeButton::fadeOut()
{
    fadingOut = true;
    Application::getInstance()->registerTimerWidget(this);
 
    // Deactivate during fade out
    setTouchable(false);
}
 
void FadeButton::handleTickEvent()
{
    if (fadingOut)
    {
        if (alpha <= 2) // Be careful of not underrunning datatype
        {
            alpha = 0;
            Application::getInstance()->unregisterTimerWidget(this);
        }
        else
        {
            alpha -= 3;
        }
    }
    else // fading in
    {
        if (alpha >= 253) // Be careful of not overrunning datatype
        {
            alpha = 255;
            Application::getInstance()->unregisterTimerWidget(this);
            // Activate after fade in is finished
            setTouchable(true);
        }
        else
        {
            alpha += 3;
            invalidate();
        }
    }
 
    // Force redrawing of FadeButton, since changing alpha does not yield redraw.
    invalidate();
}

prathima
Associate II

Application::getInstance()->unregisterTimerWidget(this);

when am writing this project in my screen1...am getting error at "this"in above statement

it saying argument of type "screenview1*" is incompatable with screen parameter of type screen1 "touchgfx::drawable*"

prathima
Associate II

Hello....Martin

I am not getting properly what your trying to say....my need is when i long touch the screen let say 3 sec, i want to take another action like i want to go to other screen.....that before releasing the touch ..i hope you understand what i mean to say.......

and the code that you have provided was ,i just can't able to understand what your intention,,,there

Can you explain bit more information......

thank you

Alexandre RENOUX
Principal

A way of doing that is to create a button class that allows you to receive an event on both press and release action. Then, you just implement the handleTickEvent() in your screenView. As @Martin KJELDSEN​ mentioned, referring to Button, AbstractButton and at the code generated when creating a FlexButton in the Designer can help you considerably.

Here is a possible version :

customButtonContainer.hpp

#ifndef CUSTOMBUTTONCONTAINER_HPP
#define CUSTOMBUTTONCONTAINER_HPP
 
#include <touchgfx/containers/Container.hpp>
#include <touchgfx/widgets/Image.hpp>
 
namespace touchgfx
{
/**
 * @class CustomButtonTrigger CustomButtonTrigger.hpp
 */
class CustomButtonContainer : public Container
{
public:
 
    /**
     * @fn CustomButtonContainer::CustomButtonContainer()
     *
     * @brief Default constructor.
     */
    CustomButtonContainer() : pressed(false), alpha(255), up(), down(), action(0)
    {
        setTouchable(true);
        buttonImage.setXY(0, 0);
        add(buttonImage);
    }
 
    /**
     * @fn virtual CustomButtonContainer::~CustomButtonContainer()
     *
     * @brief Destructor.
     */
    virtual ~CustomButtonContainer() {}
 
    /**
     * @fn virtual void CustomButtonContainer::setBitmaps(const Bitmap& bmpReleased, const Bitmap& bmpPressed)
     *
     * @brief Sets the bitmaps.
     *
     * @param bmpReleased The bitmap released.
     * @param bmpPressed  The bitmap pressed.
     */
    virtual void setBitmaps(const Bitmap& bmpReleased, const Bitmap& bmpPressed)
    {
        up = bmpReleased;
        down = bmpPressed;
        setWidth(down.getWidth());
        setHeight(down.getHeight());
 
        handlePressedUpdated();
    }
 
    /**
     * @fn void CustomButtonContainer::setBitmapXY(uint16_t x, uint16_t y)
     *
     * @brief Sets bitmap xy.
     *
     * @param x An uint16_t to process.
     * @param y An uint16_t to process.
     */
    void setBitmapXY(uint16_t x, uint16_t y)
    {
        buttonImage.setXY(x, y);
    }
 
    /**
     * @fn Bitmap CustomButtonContainer::getCurrentlyDisplayedBitmap() const
     *
     * @brief Gets currently displayed bitmap.
     *
     * @return The currently displayed bitmap.
     */
    Bitmap getCurrentlyDisplayedBitmap() const
    {
        return (pressed ? down : up);
    }
 
    /**
     * @fn void CustomButtonContainer::setPressed(bool isPressed)
     *
     * @brief Sets the pressed state.
     *
     * @param isPressed True if is pressed, false if not.
     */
    void setPressed(bool isPressed)
    {
        pressed = isPressed;
        handlePressedUpdated();
    }
 
    /**
     * @fn bool CustomButtonContainer::getPressed()
     *
     * @brief Gets the pressed state.
     *
     * @return True if it succeeds, false if it fails.
     */
    bool getPressed()
    {
        return pressed;
    }
 
    /**
     * @fn void CustomButtonContainer::setAlpha(uint8_t newAlpha)
     *
     * @brief Sets an alpha value.
     *
     * @param newAlpha The new alpha.
     */
    void setAlpha(uint8_t newAlpha)
    {
        alpha = newAlpha;
        handleAlphaUpdated();
    }
 
    /**
     * @fn uint8_t CustomButtonContainer::getAlpha() const
     *
     * @brief Gets the alpha.
     *
     * @return The alpha value.
     */
    uint8_t getAlpha() const
    {
        return alpha;
    }
 
    /**
     * @fn void CustomButtonContainer::setAction(GenericCallback< const CustomButtonContainer&, bool& >& callback)
     *
     * @brief Sets an action callback.
     *
     * @param callback The callback.
     */
    void setAction(GenericCallback< const CustomButtonContainer&, bool& >& callback)
    {
        action = &callback;
    }
 
    /**
     * @fn virtual void CustomButtonContainer::handleClickEvent(const ClickEvent& event)
     *
     * @brief Handles the click event described by event.
     *
     * @param event The event.
     */
    virtual void handleClickEvent(const ClickEvent& event)
    {
        bool wasPressed = getPressed();
        bool newPressedValue = (event.getType() == ClickEvent::PRESSED);
        if ((newPressedValue && !wasPressed) || (!newPressedValue && wasPressed))
        {
            setPressed(newPressedValue);
            invalidate();
            if (action->isValid())
            {
                action->execute(*this, pressed);
            }
        }
    }
 
    
protected:
    bool pressed;        ///< True if pressed
    uint8_t alpha;       ///< The current alpha value. 255 denotes solid, 0 denotes completely transparent.
    Image buttonImage; ///< The button image
    Bitmap  up;        ///< The image to display when button is released.
    Bitmap  down;      ///< The image to display when button is pressed.
 
    GenericCallback< const CustomButtonContainer&, bool&>* action;  ///< The action
 
    /**
     * @fn virtual void CustomButtonContainer::handlePressedUpdated()
     *
     * @brief Handles the pressed updated.
     */
    virtual void handlePressedUpdated() 
    {
        buttonImage.setBitmap(pressed ? down : up);
    }
 
    /**
     * @fn virtual void CustomButtonContainer::handleAlphaUpdated()
     *
     * @brief Handles the alpha updated.
     */
    virtual void handleAlphaUpdated()
    {
        buttonImage.setAlpha(alpha);
    }
};
 
 
} // namespace touchgfx
 
#endif // CUSTOMBUTTONCONTAINER_HPP

Screen1View.hpp

#ifndef SCREEN1VIEW_HPP
#define SCREEN1VIEW_HPP
 
#include <gui_generated/screen1_screen/Screen1ViewBase.hpp>
#include <gui/screen1_screen/Screen1Presenter.hpp>
#include <gui/common/customButtonContainer.hpp>
 
class Screen1View : public Screen1ViewBase
{
public:
    Screen1View();
    virtual ~Screen1View() {}
    virtual void setupScreen();
    virtual void tearDownScreen();
 
    virtual void handleTickEvent();
protected:
    touchgfx::CustomButtonContainer customButton1, customButton2;
 
    uint16_t counter;
    bool buttonPressedFlag;
 
    Callback<Screen1View, const CustomButtonContainer&, bool&> buttonEventCallback;
 
    void handleButtonEvent(const CustomButtonContainer& element, bool& buttonState);
};
 
#endif // SCREEN1VIEW_HPP

Screen1View.cpp

#include <gui/screen1_screen/Screen1View.hpp>
#include "BitmapDatabase.hpp"
 
Screen1View::Screen1View():
    counter(0),
    buttonPressedFlag(false),
    buttonEventCallback(this, &Screen1View::handleButtonEvent)
{
    customButton1.setBitmaps(Bitmap(BITMAP_BLUE_BUTTONS_ROUND_EDGE_MEDIUM_ID), Bitmap(BITMAP_BLUE_BUTTONS_ROUND_EDGE_MEDIUM_PRESSED_ID));
    customButton1.setBitmapXY(0, 0);
    customButton1.setPosition(285, 200, 230, 60);
 
    customButton2.setBitmaps(Bitmap(BITMAP_BLUE_BUTTONS_ROUND_EDGE_MEDIUM_ID), Bitmap(BITMAP_BLUE_BUTTONS_ROUND_EDGE_MEDIUM_PRESSED_ID));
    customButton2.setBitmapXY(0, 0);
    customButton2.setPosition(20, 20, 230, 60);
 
    add(customButton1);
    add(customButton2);
 
    customButton1.setAction(buttonEventCallback);
    customButton2.setAction(buttonEventCallback);
}
 
void Screen1View::setupScreen()
{
    Screen1ViewBase::setupScreen();
}
 
void Screen1View::tearDownScreen()
{
    Screen1ViewBase::tearDownScreen();
}
 
void Screen1View::handleButtonEvent(const CustomButtonContainer& element, bool& buttonState)
{
    if(buttonState)
    {
        if(&element == &customButton1)
        {
            touchgfx_printf("pressed 1\n");
            buttonPressedFlag = true;
        }
        else if(&element == &customButton2)
        {
            touchgfx_printf("pressed 2\n");
        }
    }
    else
    {
        if(&element == &customButton1)
        {
            touchgfx_printf("released 1\n");
            buttonPressedFlag = false;
            counter = 0;
        }
        else if(&element == &customButton2)
        {
            touchgfx_printf("released 2\n");
        }
    }
}
 
void Screen1View::handleTickEvent()
{
   if(buttonPressedFlag)
   {
       counter++;
       if(counter%180 == 0) // 3 seconds has passed
       {
           //move to another screen
       }
   }
}

/Alexandre

Alexandre RENOUX
Principal

I forgot to mention that in the Screen1View.cpp, the initialization should be in the setupScreen() function. In this specific case, where I have only one screen it is the same behavior but in your case it should be in setupScreen() as follows

#include <gui/screen1_screen/Screen1View.hpp>
#include "BitmapDatabase.hpp"
#include <touchgfx/Color.hpp>
 
Screen1View::Screen1View():
    counter(0),
    buttonPressedFlag(false),
    buttonEventCallback(this, &Screen1View::handleButtonEvent)
{
}
 
void Screen1View::setupScreen()
{
    Screen1ViewBase::setupScreen();
 
    customButton1.setBitmaps(Bitmap(BITMAP_BLUE_BUTTONS_ROUND_EDGE_MEDIUM_ID), Bitmap(BITMAP_BLUE_BUTTONS_ROUND_EDGE_MEDIUM_PRESSED_ID));
    customButton1.setBitmapXY(0, 0);
    customButton1.setPosition(285, 200, 230, 60);
 
    customButton2.setBitmaps(Bitmap(BITMAP_BLUE_BUTTONS_ROUND_EDGE_MEDIUM_ID), Bitmap(BITMAP_BLUE_BUTTONS_ROUND_EDGE_MEDIUM_PRESSED_ID));
    customButton2.setBitmapXY(0, 0);
    customButton2.setPosition(20, 20, 230, 60);
 
    add(customButton1);
    add(customButton2);
 
    customButton1.setAction(buttonEventCallback);
    customButton2.setAction(buttonEventCallback);
}

prathima
Associate II

hello

what is customButtonContainer.hpp...how you taken it designer,,,

you have taken one custom container in that you have taken container and flex button eith image size.....can u Provide designer file....

prathima
Associate II

how do you done it in the touchgfx designer

You register timer widget from a widget, not a screen. For instance, if you're inheriting from AbstractButton, you will register timer widget when the button pressed handler is activated.

/Martin