Jump to content

Pressed and unpressed Buttons


Sergey Kushnir

Recommended Posts

Hi, Joel!

I have been observing the effect associated with the button for a long time, as shown in the video. I fought it by switching the button or container to the hide or unvisible state. But perhaps this is wrong. This effect occurs when any button is pressed. As I understand it, the rendering sequence looks like this. 1. The "External connection" button is pressed and the pressed state is rendered. 2. The button is released and the released button is rendered (more precisely, it is queued for rendering). 3. The released button event is processed. Here, the function for creating a container with the OK button is called, which, when pressed, must be destroyed. 4. The container and its button are rendered. 5. Pressing the OK button first renders the "External connection" button, and then renders the OK button. Is the queue being "pushed"? 6. The container is destroyed. 7. The container with the "External connection" button is rendered.

How can I prevent this effect from occurring?

What am I doing wrong?

Main Window

#include "Screens.h"

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <limits.h>
#include <float.h>

#include "LT7381-HAL.h"
#include "WidgetStyles.h"
#include "StringsTableIDs.h"

#define Gray_80_			HTML2COLOR(0x808080)

extern GListener    glistener;
extern GHandle      _ghStatusbar, ActiveScreen;
extern font_t       dejavu_sans_con12,dejavu_sans_con16,dejavu_sans_con18,dejavu_sans_con20,dejavu_sans_con22,dejavu_sans_con24,dejavu_sans_con28, dejavu_sans_con36, dejavu_sans_con72;
static GHandle      mainAttestatButton, mainProductButton, mainExtConnectButton, mainSettingsButton, mainTitleLabel;
static GHandle      mainContainer;
gFont mainFont2x;
extern font_t dejavu_sans_12,dejavu_sans_16,dejavu_sans_18,dejavu_sans_20,dejavu_sans_22,dejavu_sans_24,dejavu_sans_32;

static gBool mainScreenIsCreated = gFalse;
GButtonObject *mainExtConnectButtonObj;

void MainScreenCreate(void)
{
	GWidgetInit	wi;
    gwinWidgetClearInit(&wi);
    wi.g.show = TRUE;

	wi.g.width = gdispGetWidth(); wi.g.height = gdispGetHeight() - _ghStatusbar->height; wi.g.x = 0, wi.g.y =0;
    wi.text = "mainContainer";
    mainContainer = gwinContainerCreate(0, &wi, GWIN_CONTAINER_BORDER);
	wi.g.parent = mainContainer;

	wi.g.width = 600;
	wi.g.height =  gdispGetFontMetric(dejavu_sans_con72, gFontHeight);
	wi.g.x = 260;
	wi.g.y = 0;
	wi.text = GSByID(SID_OperMode);
    mainTitleLabel = gwinLabelCreate(0, &wi);
    gwinSetFont(mainTitleLabel, dejavu_sans_con72);

    wi.g.y += wi.g.height + 10;
    wi.g.height = 100;
    wi.customDraw = gwinButtonDraw_Rounded;
    wi.text = GSByID(SID_Product);
    mainProductButton = gwinButtonCreate(0, &wi);
    gwinSetFont(mainProductButton, dejavu_sans_con36);
    
    wi.g.y += wi.g.height + 20;
    wi.text = GSByID(SID_ExConnect);
    mainExtConnectButton = gwinButtonCreate(0, &wi);
    gwinSetFont(mainExtConnectButton, dejavu_sans_con36);

    wi.g.y += wi.g.height + 20;
    wi.text = GSByID(SID_Attestat);
    mainAttestatButton = gwinButtonCreate(0, &wi);
    gwinSetFont(mainAttestatButton, dejavu_sans_con36);
    
    wi.g.y += wi.g.height + 20;
    wi.text = GSByID(SID_Settings);
    mainSettingsButton = gwinButtonCreate(0, &wi);
    gwinSetFont(mainSettingsButton, dejavu_sans_con36);
    
    mainScreenIsCreated = gTrue;
    ActiveScreen = mainContainer;
    
    mainExtConnectButtonObj = (GButtonObject *)mainExtConnectButton;
}

void mainScreenDestroy(void)
{
    gwinDestroy(mainContainer);
    mainScreenIsCreated = gFalse;
}

void mainScreenShow(void)
{
    gwinSetText(mainTitleLabel, GSByID(SID_OperMode), gFalse);
    gwinSetText(mainProductButton, GSByID(SID_Product), gFalse);
    gwinSetText(mainExtConnectButton, GSByID(SID_ExConnect), gFalse);
    gwinSetText(mainAttestatButton, GSByID(SID_Attestat), gFalse);
    gwinSetText(mainSettingsButton, GSByID(SID_Settings), gFalse);
    gwinShow(mainContainer);
}

void MainScreenEv(GEvent *pe)
{

//    if (!mainScreenIsCreated) return;
    switch(pe->type) {
    case GEVENT_GWIN_BUTTON:            ///(GEVENT_GWIN_CTRL_FIRST+0)
        if (((GEventGWinButton*)pe)->gwin == mainProductButton) {
            DummyScreenCreate(0);
        }
        if (((GEventGWinButton*)pe)->gwin == mainExtConnectButton) {
//            DummyScreenCreate(0);
            ManualScreenCreate(0);
        }
        if (((GEventGWinButton*)pe)->gwin == mainAttestatButton) {
            AttScreenCreate(0);
        }
        if (((GEventGWinButton*)pe)->gwin == mainSettingsButton) {
            SettingsScreenCreate();
        }
        break;
    }
}

Under Construction Window

#include "Screens.h"
#include "StringsTableIDs.h"

extern GHandle      _ghStatusbar, ActiveScreen;
extern GListener  glistener;
extern font_t       dejavu_sans_con12,dejavu_sans_con16,dejavu_sans_con18,dejavu_sans_con20,dejavu_sans_con22,dejavu_sans_con24,dejavu_sans_con28, dejavu_sans_con36, dejavu_sans_con72;

static GHandle dummyContainer = NULL, dummyTitleLabel = NULL, dummyCloseButton = NULL;
static gBool dummyScreenIsCreated = gFalse;
static retFunc_t dummyRetFunc = NULL;

void DummyScreenCreate(retFunc_t func)
{
    dummyRetFunc = func;

	GWidgetInit	wi;
    gwinWidgetClearInit(&wi);
    wi.g.show = TRUE;
	// Create the Container
	wi.g.width = gdispGetWidth(); wi.g.height = gdispGetHeight() - _ghStatusbar->height; wi.g.x = 0, wi.g.y =0;

    wi.text = "dummyContainer";
    dummyContainer = gwinContainerCreate(0, &wi, GWIN_CONTAINER_BORDER);
	wi.g.parent = dummyContainer;

	wi.g.width = 700;
	wi.g.height =  gdispGetFontMetric(dejavu_sans_con72, gFontHeight);
	wi.g.x = 175;
	wi.g.y = 200;
	wi.text = GSByID(SID_UnderConstraction);
    dummyTitleLabel = gwinLabelCreate(0, &wi);
    gwinSetFont(dummyTitleLabel, dejavu_sans_con72);

    wi.g.y = 450;
    wi.g.width = 500;
    wi.g.height = 100;
	wi.g.x = 260;
    wi.customDraw = gwinButtonDraw_Rounded;
    wi.text = GSByID(SID_Close);
    dummyCloseButton = gwinButtonCreate(0, &wi);
    gwinSetFont(dummyCloseButton, dejavu_sans_con36);

    dummyScreenIsCreated = gTrue;
    ActiveScreen = dummyContainer;
}

void DummyScreenDestroy(void)
{
    gwinDestroy(dummyContainer);
    dummyScreenIsCreated = gFalse;
}


void DummyScreenEv(GEvent *pe)
{
    if (!dummyScreenIsCreated) return;
    switch(pe->type) {
    case GEVENT_GWIN_BUTTON:            ///(GEVENT_GWIN_CTRL_FIRST+0)
        if (((GEventGWinButton*)pe)->gwin == dummyCloseButton) {
            DummyScreenDestroy();
        }
        break;
    }
}

Thak you for answer!

Buttons.zip

Link to comment
Share on other sites

Hey,

While I haven't studied your code yet: The way you'd typically do this is to have one container per "display page" which you use as the parent for any widget inside of that page. This allows you to show different display pages containing different UI elements / widgets. From what I can tell, you already have that up and running.
Then you simply hide all display pages except for the one you want to be visible. The GWIN module should take care of enabling/disabling widget visibility, events etc for you.

Whether or not you create/destroy the various display pages dynamically or whether you have enough memory to keep them around is an implementation detail.
 

On 07/09/2024 at 08:17, Sergey Kushnir said:

I fought it by switching the button or container to the hide or unvisible state. But perhaps this is wrong.

With the above, I do think that this is the correct approach. What leads you to believe that maybe it isn't?

I'll try to find some time to create a simple, minimal example.

Link to comment
Share on other sites

Here's a simple example which demonstrates the concept: It has three different pages and a menubar which is always visible. The pages contain buttons to switch to different pages.

I intentionally kept this very simple when it comes to managing the handles, display pages and events processing. A real application would likely introduce a new type/structure for a display page as well as a controller which can handle any number of display pages.
Furthermore, you'd typically setup a more generic way of handling "switch to display page N" events so you don´t  have that ugly per-button logic.

Example:

#include <gfx.h>

#define MENUBAR_HEIGHT 30;

// Menu bar (always visible)
GHandle ghMenubar;

// Display page 0
GHandle ghPage0;
GHandle ghPage0_Label;
GHandle ghPage0_ButtonA;
GHandle ghPage0_ButtonB;
GHandle ghPage0_ButtonGotoPage1;
GHandle ghPage0_ButtonGotoPage2;

// Display page 1
GHandle ghPage1;
GHandle ghPage1_Label;
GHandle ghPage1_ButtonGotoPage0;

// Display page 2
GHandle ghPage2;
GHandle ghPage2_Label;
GHandle ghPage2_ButtonGotoPage0;
GHandle ghPage2_ButtonGotoPage1;

static
void
createWidgets()
{
    GWidgetInit wi;

    // Menubar
    {
        gwinWidgetClearInit(&wi);

        // Menubar
        wi.g.show = TRUE;
        wi.g.width = gdispGetWidth();
        wi.g.height = MENUBAR_HEIGHT;
        wi.g.x = 0;
        wi.g.y = 0;
        wi.text = "MenuBar - Always visible!";
        ghMenubar = gwinLabelCreate(0, &wi);
    }

    // Display page 0
    {
        gwinWidgetClearInit(&wi);

        // Page container
        wi.g.show = FALSE;
        wi.g.width = gdispGetWidth();
        wi.g.height = gdispGetHeight() - MENUBAR_HEIGHT;
        wi.g.y = MENUBAR_HEIGHT;
        wi.g.x = 0;
        wi.text = "Display Page 1";
        ghPage0 = gwinContainerCreate(0, &wi, GWIN_CONTAINER_BORDER);

        wi.g.show = TRUE;

        // Label
        wi.g.width = 100;
        wi.g.height = 30;
        wi.g.x = 10;
        wi.g.y = 10;
        wi.text = "Page 0";
        wi.g.parent = ghPage0;
        ghPage0_Label = gwinLabelCreate(0, &wi);

        // Button A
        wi.g.width = 180;
        wi.g.height = 30;
        wi.g.x = 50;
        wi.g.y = 50;
        wi.text = "Button A";
        wi.g.parent = ghPage0;
        ghPage0_ButtonA = gwinButtonCreate(0, &wi);

        // Button B
        wi.g.width = 180;
        wi.g.height = 30;
        wi.g.x = 50;
        wi.g.y = 100;
        wi.text = "Button B";
        wi.g.parent = ghPage0;
        ghPage0_ButtonB = gwinButtonCreate(0, &wi);

        // Button GotoPage1
        wi.g.width = 180;
        wi.g.height = 30;
        wi.g.x = 50;
        wi.g.y = 150;
        wi.text = "Goto Page 1";
        wi.g.parent = ghPage0;
        ghPage0_ButtonGotoPage1 = gwinButtonCreate(0, &wi);

        // Button GotoPage1
        wi.g.width = 180;
        wi.g.height = 30;
        wi.g.x = 50;
        wi.g.y = 200;
        wi.text = "Goto Page 2";
        wi.g.parent = ghPage0;
        ghPage0_ButtonGotoPage2 = gwinButtonCreate(0, &wi);
    }

    // Display page 1
    {
        gwinWidgetClearInit(&wi);

        // Page container
        wi.g.show = FALSE;
        wi.g.width = gdispGetWidth();
        wi.g.height = gdispGetHeight() - MENUBAR_HEIGHT;
        wi.g.y = MENUBAR_HEIGHT;
        wi.g.x = 0;
        wi.text = "Display Page 1";
        ghPage1 = gwinContainerCreate(0, &wi, GWIN_CONTAINER_BORDER);

        wi.g.show = TRUE;

        // Label
        wi.g.width = 100;
        wi.g.height = 30;
        wi.g.x = 10;
        wi.g.y = 10;
        wi.text = "Page 1";
        wi.g.parent = ghPage1;
        ghPage1_Label = gwinLabelCreate(0, &wi);

        // Button GotoPage1
        wi.g.width = 180;
        wi.g.height = 30;
        wi.g.x = 50;
        wi.g.y = 150;
        wi.text = "Goto Page 0";
        wi.g.parent = ghPage1;
        ghPage1_ButtonGotoPage0 = gwinButtonCreate(0, &wi);
    }

    // Display page 2
    {
        gwinWidgetClearInit(&wi);

        // Page container
        wi.g.show = FALSE;
        wi.g.width = gdispGetWidth();
        wi.g.height = gdispGetHeight() - MENUBAR_HEIGHT;
        wi.g.y = MENUBAR_HEIGHT;
        wi.g.x = 0;
        wi.text = "Display Page 2";
        ghPage2 = gwinContainerCreate(0, &wi, GWIN_CONTAINER_BORDER);

        wi.g.show = TRUE;

        // Label
        wi.g.width = 100;
        wi.g.height = 30;
        wi.g.x = 10;
        wi.g.y = 10;
        wi.text = "Page 2";
        wi.g.parent = ghPage2;
        ghPage2_Label = gwinLabelCreate(0, &wi);

        // Button GotoPage0
        wi.g.width = 180;
        wi.g.height = 30;
        wi.g.x = 50;
        wi.g.y = 150;
        wi.text = "Goto Page 0";
        wi.g.parent = ghPage2;
        ghPage2_ButtonGotoPage0 = gwinButtonCreate(0, &wi);

        // Button GotoPage1
        wi.g.width = 180;
        wi.g.height = 30;
        wi.g.x = 50;
        wi.g.y = 150;
        wi.text = "Goto Page 1";
        wi.g.parent = ghPage2;
        ghPage2_ButtonGotoPage1 = gwinButtonCreate(0, &wi);
    }
}

static
void
showPage(const unsigned idx)
{
    // Hide all
    gwinHide(ghPage0);
    gwinHide(ghPage1);
    gwinHide(ghPage2);

    // Show
    switch (idx)
    {
        case 0:
            gwinShow(ghPage0);
            break;

        case 1:
            gwinShow(ghPage1);
            break;

        case 2:
            gwinShow(ghPage2);
            break;

        default:
            break;
    }
}

static GListener gl;

int
main()
{
    // Initialize µGFX
    gfxInit();

    // Setup widgets stuff
    gwinSetDefaultFont(gdispOpenFont("*"));
    gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE);
    gdispClear(White);

    // Create widgets
    createWidgets();

    // Listen for widget events
    geventListenerInit(&gl);
    gwinAttachListener(&gl);

    // Show first page
    showPage(0);

    while (1) {
        GEvent* evt;

        // Process events
        evt = geventEventWait(&gl, TIME_INFINITE);
        switch (evt->type)
        {
            case GEVENT_GWIN_BUTTON:
            {
                GHandle button = (GHandle)((GEventGWinButton*)evt)->gwin;

                // Goto Page 0
                if (button == ghPage1_ButtonGotoPage0 || button == ghPage2_ButtonGotoPage0)
                    showPage(0);

                // Goto Page 1
                else if (button == ghPage0_ButtonGotoPage1 || button == ghPage2_ButtonGotoPage1)
                    showPage(1);

                // Goto Page 2
                else if (button == ghPage0_ButtonGotoPage2)
                    showPage(2);

                break;
            }
        }
    }
}

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...