EVT_BUTTON problem

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
martin.martinec
In need of some credit
In need of some credit
Posts: 6
Joined: Sun May 24, 2020 1:56 pm

EVT_BUTTON problem

Post by martin.martinec »

Hello,

I am trying to write a small app, which is capable of changing the system time.
Being new to wxWidgets, I stuck at the beginning trying to set the time to a fixed value.
Unfortunately, the button (button1) event doesn't respond to my click as anticipated.

Could you please help me?

Regards,
MM

Code: Select all

// ============================================================================
// declarations
// ============================================================================

#include <wx/wx.h>
#include <wx/button.h>
#include <wx/timectrl.h>
#include <sysinfoapi.h>

class MyApp : public wxApp
{
public:

    virtual bool OnInit() wxOVERRIDE;
    virtual void OnLaunched() wxOVERRIDE;

    wxPanel* m_panel;
    wxTimePickerCtrl* m_picker;
    wxSizer* m_sizer;
    wxButton* m_button;
    wxWindow* m_window;
    wxTextCtrl* m_textctrl;
};


class MyFrame : public wxFrame
{
public:
    MyFrame(const wxString& title);
//private:
    int OnSettings(wxCommandEvent& event);
    void OnButton1(wxCommandEvent& event);
    int OnPort(wxCommandEvent& event);
    void OnQuit(wxCommandEvent& event);
    void OnAbout(wxCommandEvent& event);

    wxDECLARE_EVENT_TABLE();
};

enum
{
    //    Minimal_Settings = wxID_SETTINGS,
    Minimal_Settings,
    Minimal_Port,
    Minimal_Quit = wxID_EXIT,
    Minimal_About = wxID_ABOUT,
    Minimal_Button1 = 1
};

wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
//EVT_MENU(Minimal_Settings, MyFrame::OnSettings)
//EVT_MENU(Minimal_Port, MyFrame::OnPort)
EVT_MENU(Minimal_Quit, MyFrame::OnQuit)
EVT_MENU(Minimal_About, MyFrame::OnAbout)

EVT_BUTTON(Minimal_Button1, MyFrame::OnButton1)

wxEND_EVENT_TABLE()

wxIMPLEMENT_APP(MyApp);

// ============================================================================
// implementation
// ============================================================================

bool MyApp::OnInit()
{
    if (!wxApp::OnInit())
        return false;
    MyFrame* frame = new MyFrame("NetClock");
    frame->SetSize(330, 200);
    frame->SetWindowStyle(wxDEFAULT_FRAME_STYLE & ~(wxRESIZE_BORDER | wxMAXIMIZE_BOX));
    m_panel = new wxPanel(frame, wxID_ANY, wxDefaultPosition, wxSize(10, 10));
    m_picker = new wxTimePickerCtrl(m_panel, wxID_ANY, wxDefaultDateTime, wxPoint(40, 20));
    m_button = new wxButton(m_panel, wxID_ANY, "set", wxPoint(40, 60));
    m_textctrl = new wxTextCtrl(m_panel, wxID_ANY, "listening on port 80...", wxPoint(150, 10), wxSize(150, 100), 0 | wxTE_READONLY | wxTE_MULTILINE | wxTE_BESTWRAP);
    wxStreamToTextRedirector redirect(m_textctrl);

    //   m_sizer = new wxBoxSizer(wxHORIZONTAL);
    //   wxLogWindow* w = new wxLogWindow(m_sizer, wxT("log"));
    //   m_sizer->Add(m_window, 5 , wxGROW | (wxALL & ~wxRIGHT), 5);
    frame->Show(true);
  //  TcpIp();
    return true;
}

void MyApp::OnLaunched()
{

}

MyFrame::MyFrame(const wxString& title)
    : wxFrame(NULL, wxID_ANY, title)
{
    //    SetIcon(wxICON(sample));

    wxMenu* fileMenu = new wxMenu;

    fileMenu->Append(Minimal_Settings, "&Settings\tAlt-S", "Settings");

    //    wxFrame* port_frame = new wxFrame;
    //    fileSettings->Append(Minimal_Port, "&Port #\tAlt-P", "Port #");

    //    wxArrayString numberArray;
    //    for (size_t i = 1; i <= 9; ++i) numberArray.Add(wxString::Format(wxT("%d"), i));
    //    wxChoice* choice = new wxChoice(port_frame, wxID_ANY, wxPoint(0,0), wxSize (100,100), numberArray);
    //    m_choice = new wxChoice(wxTheApp->GetTopWindow(), wxID_ANY,
    //        wxDefaultPosition, wxDefaultSize, 0, 0,
    //        wxCB_SORT);
    //    Minimal_Settings->Append(Minimal_Port, "&Port #", "Port #");
    //        wxChoice * choice = new wxChoice(fileMenu, numberArray);
    //    wxChoice* choice = new wxChoice(fileMenu, numberArray);


    fileMenu->Append(Minimal_Quit, "E&xit\tAlt-X", "Quit this program");

    wxMenu* helpMenu = new wxMenu;
    helpMenu->Append(Minimal_About, "&About\tF1", "Show about dialog");


    wxMenuBar* menuBar = new wxMenuBar();
    menuBar->Append(fileMenu, "&File");
    menuBar->Append(helpMenu, "&Help");
    SetMenuBar(menuBar);

    CreateStatusBar(2);
    const wxString current_time = wxNow();
    SetStatusText(current_time);
    SetStatusText("  status: online", 1);
}

int MyFrame::OnSettings(wxCommandEvent& WXUNUSED(event))
{
    // true is to force the frame to close

  //  wxFrame* portframe = new wxFrame(this, wxID_ANY, "port");
//    wxArrayString numberArray;
//    for (size_t i = 1; i <= 9; ++i)
//        numberArray.Add(wxString::Format(wxT("%d"), i));

//    wxChoice(new wxFrame(NULL, wxID_ANY, "port"), wxID_ANY, wxPoint(0, 0), wxSize(30, 30), numberArray,0,wxDefaultValidator,"port");

    std::cout << "settings";
    return 0; //port_number
}

void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
    // true is to force the frame to close
    Close(true);
}

void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
    wxMessageBox(wxString::Format
    (
        "Welcome to NetClock\n"
        "\n"
        "This application...
    ),
        "About NetClock",
        wxOK | wxICON_INFORMATION,
        this);
}

void MyFrame::OnButton1(wxCommandEvent& WXUNUSED(event))
{
    SYSTEMTIME st;
    st.wYear = 2000;
    st.wMonth = 5;
    st.wDay = 12;
    st.wHour = 16;
    st.wMinute = 8;
    st.wSecond = 31;
    st.wMilliseconds = 55;
    ::SetSystemTime(&st);
    std::cout << "ok";
}
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: EVT_BUTTON problem

Post by PB »

It is because you map the event with ID Minimal_Button1 but create the actual button with wxID_ANY. You should have

Code: Select all

m_button = new wxButton(m_panel, Minimal_Button1, "set", wxPoint(40, 60));
But honestly, your code is a mess. The frame creation code should be in the MyFrame constructor, not in the MyApp::OnInit().

I would also use Bind() instead of message maps, where you do not need to care about IDs, but I understand that the code comes from the hello world example.

Code: Select all

m_button = new wxButton(m_panel, wxID_ANY, "set", wxPoint(40, 60));
m_button->Bind(wxEVT_BUTTON, &MyFrame::OnButton1Click, frame);
martin.martinec
In need of some credit
In need of some credit
Posts: 6
Joined: Sun May 24, 2020 1:56 pm

Re: EVT_BUTTON problem

Post by martin.martinec »

Dear PB,

Thank you for your answer and feedback.
I am going to change it as per your recommendation.

Have a pleasant day,
MM
martin.martinec
In need of some credit
In need of some credit
Posts: 6
Joined: Sun May 24, 2020 1:56 pm

Re: EVT_BUTTON problem

Post by martin.martinec »

I have cleaned the code and although it is not perfect yet, it works and looks much better.
Thank you again.

Code: Select all

// ============================================================================
// declarations
// ============================================================================

#include <wx/wx.h>
#include <wx/button.h>
#include <wx/timectrl.h>
#include <sysinfoapi.h>

class MyApp : public wxApp
{
public:
    virtual bool OnInit() wxOVERRIDE;
    virtual void OnLaunched() wxOVERRIDE;
};


class NetClockFrame : public wxFrame
{
public:
    NetClockFrame();
private:
    wxPanel* m_panel;
    wxTimePickerCtrl* m_picker;
    wxSizer* m_sizer;
    wxButton* m_button;
    wxWindow* m_window;
    wxTextCtrl* m_textctrl;

    int OnSettings(wxCommandEvent& event);
    void ButtonSetTime(wxCommandEvent& event);
    int OnPort(wxCommandEvent& event);
    void OnQuit(wxCommandEvent& event);
    void OnAbout(wxCommandEvent& event);

    wxDECLARE_EVENT_TABLE();
};


wxBEGIN_EVENT_TABLE(NetClockFrame, wxFrame)
//EVT_MENU(Minimal_Settings, MyFrame::OnSettings)
//EVT_MENU(Minimal_Port, MyFrame::OnPort)
EVT_MENU(wxID_EXIT, NetClockFrame::OnQuit)
EVT_MENU(wxID_ABOUT, NetClockFrame::OnAbout)

// EVT_BUTTON(Minimal_Button1, MyFrame::OnButton1)

wxEND_EVENT_TABLE()

wxIMPLEMENT_APP(MyApp);

// ============================================================================
// implementation
// ============================================================================

bool MyApp::OnInit()
{
    if (!wxApp::OnInit())
        return false;
    NetClockFrame* frame = new NetClockFrame();
    return true;
}

void MyApp::OnLaunched()
{

}

NetClockFrame::NetClockFrame()
    : wxFrame(NULL, wxID_ANY, "NetClock")
{
    this->SetSize(330, 200);
    this->SetWindowStyle(wxDEFAULT_FRAME_STYLE & ~(wxRESIZE_BORDER | wxMAXIMIZE_BOX));
    m_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(10, 10));
    m_picker = new wxTimePickerCtrl(m_panel, wxID_ANY, wxDefaultDateTime, wxPoint(40, 20));
    m_button = new wxButton(m_panel, wxID_ANY, "set", wxPoint(40, 60));
    m_button->Bind(wxEVT_BUTTON, &NetClockFrame::ButtonSetTime, this);
    m_textctrl = new wxTextCtrl(m_panel, wxID_ANY, "listening on port 80...", wxPoint(150, 10), wxSize(150, 100), 0 | wxTE_READONLY | wxTE_MULTILINE | wxTE_BESTWRAP);
    wxStreamToTextRedirector redirect(m_textctrl);
    this->Show(true);


    wxMenu* fileMenu = new wxMenu;
    fileMenu->Append(wxID_SETUP, "&Settings\tAlt-S", "Settings");
    fileMenu->Append(wxID_EXIT, "E&xit\tAlt-X", "Quit this program");

    wxMenu* helpMenu = new wxMenu;
    helpMenu->Append(wxID_ABOUT, "&About\tF1", "Show about dialog");

    wxMenuBar* menuBar = new wxMenuBar();
    menuBar->Append(fileMenu, "&File");
    menuBar->Append(helpMenu, "&Help");
    SetMenuBar(menuBar);


    CreateStatusBar(2);
    const wxString current_time = wxNow();
    SetStatusText(current_time);
    SetStatusText("  status: online", 1);
}

int NetClockFrame::OnSettings(wxCommandEvent& WXUNUSED(event))
{
    std::cout << "settings";
    return 0; //port_number
}

void NetClockFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
    Close(true);
}

void NetClockFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
    wxMessageBox(wxString::Format
    (
        "Welcome to NetClock\n"
        "\n"
        "This application ..."
    ),
        "About NetClock",
        wxOK | wxICON_INFORMATION,
        this);
}

void NetClockFrame::ButtonSetTime(wxCommandEvent& WXUNUSED(event))
{
    int h, m, s;
    m_picker->GetTime(&h, &m, &s);

    SYSTEMTIME st;
    GetSystemTime(&st);

    st.wHour = h;
    st.wMinute = m;
    st.wSecond = s;

    ::SetSystemTime(&st);
}
I would have just two more questions.
* I wanted to redirect the cout stream to textctrl window (line 78, 79), but it doesn't work.
* Is there different way how to make in the statusbar updated (line 98) than using another thread?

Regards,
MM
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: EVT_BUTTON problem

Post by doublemax »

I wanted to redirect the cout stream to textctrl window (line 78, 79), but it doesn't work.
You're creating wxStreamToTextRedirector on the stack, it gets destroyed when it goes out of scope and the redirection stops.
Is there different way how to make in the statusbar updated (line 98) than using another thread?
Using a wxTimer event handler.
Use the source, Luke!
martin.martinec
In need of some credit
In need of some credit
Posts: 6
Joined: Sun May 24, 2020 1:56 pm

Re: EVT_BUTTON problem

Post by martin.martinec »

Dear doublemax,

Thank you very much for your advice.

Have a nice day
MM
Post Reply