Clear a WxTextCtrl after few seconds

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
marcusbarnet
Experienced Solver
Experienced Solver
Posts: 71
Joined: Sat Jul 27, 2019 3:45 pm

Clear a WxTextCtrl after few seconds

Post by marcusbarnet »

I have an application that reads data from a magnetic card reader.
It starts with a WxTextCtrl with focus ON so the cursor is already in position and when the user swipes the card, all the characters are automatically typed in the text control.

The problem is that sometimes the swiping is not correct and so the characters filled in the text control are not correct.
I would like to have a timer so the text control is automatically cleared after 2 seconds.

Is it possible to do that in WxWidgets?

At the moment, I read the Text control content with:

Code: Select all

wxString stringa_tessera = tessera->GetValue();
Thank you!
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: Clear a WxTextCtrl after few seconds

Post by PB »

If I understood you correctly, that should be trivial?

For example this code for a simple yet complete program shows how to start a timer that clears a text control (m_dataCtrl). After clicking the button, (1) the data in the text control is set to the current time and (2) a 2-second one-shot timer is fired: see OnSetValueAndStartTimer() method. In the timer handler OnClearValue() the value in the text control is cleared.

Code: Select all

#include <wx/wx.h>

class MyDialog : public wxDialog
{
public:
    MyDialog() : wxDialog(NULL, wxID_ANY, "Test")
    {
        wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);

        m_dataCtrl = new wxTextCtrl(this, wxID_ANY);        
        mainSizer->Add(m_dataCtrl, wxSizerFlags().Expand().DoubleBorder());

        wxButton* button = new wxButton(this, wxID_ANY, "Set value and start timer");
        mainSizer->Add(button, wxSizerFlags().Expand().Border());
        button->Bind(wxEVT_BUTTON, &MyDialog::OnSetValueAndStartTimer, this);

        m_timer.Bind(wxEVT_TIMER, &MyDialog::OnClearValue, this);
        
        SetSizerAndFit(mainSizer);
    }
private:
    wxTextCtrl* m_dataCtrl;
    wxTimer     m_timer;

    void OnSetValueAndStartTimer(wxCommandEvent&)
    {
        m_dataCtrl->SetValue(wxDateTime::Now().FormatTime());
        m_timer.StartOnce(2000);
    }

    void OnClearValue(wxTimerEvent&)
    {
        wxBell();
        m_dataCtrl->Clear();
    }    
};

class MyApp : public wxApp
{
public:
    bool OnInit()
    {
        MyDialog().ShowModal();
        return false;
    }
}; wxIMPLEMENT_APP(MyApp);
marcusbarnet
Experienced Solver
Experienced Solver
Posts: 71
Joined: Sat Jul 27, 2019 3:45 pm

Re: Clear a WxTextCtrl after few seconds

Post by marcusbarnet »

I can't click a button in order to make the timer starts.

The timer should starts automatically when the first character is typed in the text control.

I do not know how to do that.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: Clear a WxTextCtrl after few seconds

Post by PB »

marcusbarnet wrote: Wed Oct 02, 2019 5:54 pm I can't click a button in order to make the timer starts.

The timer should starts automatically when the first character is typed in the text control.
I thought it obvious that starting the timer with a button in my code was just an example of how to start a timer in response to some event...

You would need to start the timer in response to wxEVT_TEXT from your wxTextCtrl.
marcusbarnet
Experienced Solver
Experienced Solver
Posts: 71
Joined: Sat Jul 27, 2019 3:45 pm

Re: Clear a WxTextCtrl after few seconds

Post by marcusbarnet »

Can you please show me a simple example on how to use it?

I'm not an expert so I'm not figuring out how to use it.

Thank you
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: Clear a WxTextCtrl after few seconds

Post by PB »

I am not an expert either but it should be simple.

I do not know how exactly your card scanner works but I would expect that it sends the characters to wxTextCtrl quickly one after another. I would just (re)start the one-shot timer in response to each wxEVT_TEXT event. So the two seconds would be after the last character arrived and the interval between the first and last character is expected to less than 2 seconds. wxTimerEvent handler invoked after those two seconds would just process the data, the code Clear()s them.

So essentially something like this

Code: Select all

#include <wx/wx.h>

class MyDialog : public wxDialog
{
public:
    MyDialog() : wxDialog(NULL, wxID_ANY, "Test")
    {
        wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);

        m_dataCtrl = new wxTextCtrl(this, wxID_ANY);        
        mainSizer->Add(m_dataCtrl, wxSizerFlags().Expand().DoubleBorder());
        m_dataCtrl->Bind(wxEVT_TEXT, &MyDialog::OnDataText, this);

        mainSizer->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), wxSizerFlags().DoubleBorder());

        m_clearDataTimer.Bind(wxEVT_TIMER, &MyDialog::OnClearData, this);
        
        SetSizerAndFit(mainSizer);
    }
private:
    wxTextCtrl* m_dataCtrl;
    wxTimer     m_clearDataTimer;

    void OnDataText(wxCommandEvent&)
    {        
        m_clearDataTimer.StartOnce(2000);
    }

    void OnClearData(wxTimerEvent&)
    {        
        m_dataCtrl->Clear();
    }    
};

class MyApp : public wxApp
{
public:
    bool OnInit()
    {
        MyDialog().ShowModal();
        return false;
    }
}; wxIMPLEMENT_APP(MyApp);
If your car reader can take 2 or more seconds between the characters, you need to account for this in the code. Once again, it should be simple, no expertise needed.
marcusbarnet
Experienced Solver
Experienced Solver
Posts: 71
Joined: Sat Jul 27, 2019 3:45 pm

Re: Clear a WxTextCtrl after few seconds

Post by marcusbarnet »

Thank you a lot for you tip.
I was able to successfully use the wxTimerEvent.

I just have a problem because I tried to set a timeout on my second frame in order to reloads the first frame when there is no user action for more than 5 minutes.
It seems to work, but when it returns to the first frame, it reloads it again by opening another window, so it reloads the first frame for two times and I get two instances of the same program.

For example, if I set a timeout for t = 2 seconds, than the second frame reloads the first frame but after t=2 seconds the first frame load a new application instance and I can see two different programs. It keeps reloading both first frame and second frame each 2 seconds.

This is very weird to me. How can I solve it? And why this happens?

This is the code for the second frame:

Code: Select all

BEGIN_EVENT_TABLE(SecondPage,wxFrame)
	//(*EventTable(SecondPage)
	//*)
END_EVENT_TABLE()
//void SecondPage::SetPage(ProjectFrame* page)
void SecondPage::SetPage(ThirdPage* page)
{
    int w = 1024, h = 768;
    but_prev->SetPosition(wxPoint(w / 2 - 300, h / 2 - 150));
    but_prev->SetSize(600, 300);
    but_exit->SetPosition(wxPoint(w - 40, 0));
    but_exit->SetSize(40, 40);
    thirdpage = page;
    thirdpage->Refresh();
    thirdpage->Update();
}
SecondPage::SecondPage(wxWindow* parent,wxWindowID id)
{
	//(*Initialize(SecondPage)
	Create(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("wxID_ANY"));
	SetClientSize(wxSize(1314,769));
	SetBackgroundColour(wxColour(175,253,202));
	// .... several objects declared .... //

//	
	Connect(ID_BITMAPBUTTON7,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&SecondPage::OncancelClick);
	//*)
	 m_reboot.Bind(wxEVT_TIMER, &SecondPage::Reboot, this);
         m_reboot.StartOnce(2000);  // <- I make the timer starts here
}

void SecondPage::Reboot(wxTimerEvent&){
    printf("Reboot the whole system! Timeout!\n");
    firstpage = new ProjectFrame(nullptr, 1);
    firstpage ->SetClientSize(wxSize(1323,768));
    firstpage->ShowFullScreen(true);
    firstpage->Show(true); //show it
    this->Destroy(); //and destroy page3
    //then you do not need to modify destructors.
}
This is the code for the first frame:

Code: Select all

#include "ProjectMain.h"
#include <wx/msgdlg.h>
#include <wx/tokenzr.h>
#include <mysql++.h>
#include <stdlib.h>
#include <string.h>
//(*InternalHeaders(ProjectFrame)
#include <wx/font.h>
#include <wx/intl.h>
#include <wx/string.h>
//*)
using namespace mysqlpp;


//helper functions
enum wxbuildinfoformat {
    short_f, long_f };

wxString wxbuildinfo(wxbuildinfoformat format)
{
    wxString wxbuild(wxVERSION_STRING);

    if (format == long_f )
    {
#if defined(__WXMSW__)
        wxbuild << _T("-Windows");
#elif defined(__UNIX__)
        wxbuild << _T("-Linux");
#endif

#if wxUSE_UNICODE
        wxbuild << _T("-Unicode build");
#else
        wxbuild << _T("-ANSI build");
#endif // wxUSE_UNICODE
    }

    return wxbuild;
}

//(*IdInit(ProjectFrame)

const long ProjectFrame::ID_STATICTEXT8 = wxNewId();
//*)

void prova(){
printf("ciao\n");
}

BEGIN_EVENT_TABLE(ProjectFrame,wxFrame)
    //(*EventTable(ProjectFrame)
    //*)

END_EVENT_TABLE()

ProjectFrame::ProjectFrame(wxWindow* parent,wxWindowID id)
{
    //(*Initialize(ProjectFrame)
    Create(parent, wxID_ANY, _("Isola 01"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("wxID_ANY"));
    SetClientSize(wxSize(1311,486));
    SetBackgroundColour(wxColour(176,253,203));
    // .. several text controls and buttons ...
    m_clearDataTimer.Bind(wxEVT_TIMER, &ProjectFrame::OnClearData, this);
}
void ProjectFrame::SetPage(SecondPage* page)
{
    int w = 1024, h = 768;
//    icon_butt->SetPosition(wxPoint(w / 2 - 300, h / 2 - 150));
//    icon_butt->SetSize(600, 300);
    but_exit->SetPosition(wxPoint(w - 40, 0));
    but_exit->SetSize(40, 40);
    secondpage = page;
}
ProjectFrame::~ProjectFrame()
{
    //(*Destroy(ProjectFrame)
    //*)
}

void ProjectFrame::OnQuit(wxCommandEvent& event)
{
    Close(true);
}
marcusbarnet
Experienced Solver
Experienced Solver
Posts: 71
Joined: Sat Jul 27, 2019 3:45 pm

Re: Clear a WxTextCtrl after few seconds

Post by marcusbarnet »

I can't understand why the first frame keeps reloading if the timer is set only in the second frame.
Post Reply