wxAcceleratorTable doesn't work on Linux

38 views
Skip to first unread message

Vanta White

unread,
Apr 10, 2021, 9:27:59 AMApr 10
to wx-users
Hi all.

It looks like wxAcceleratorTable doesn't work on Xubuntu 20.04
I istalled wxWidgets from Ubuntu repos.
Here is my demo code:

//------------------- begin----------------------
#include <wx/app.h>
#include <wx/frame.h>
#include <wx/button.h>
#include <wx/msgdlg.h>
#include <wx/accel.h>

#define wxID_BUTTON_1 1000
#define wxID_BUTTON_2 1001

class MyFrame : public wxFrame
{
    wxButton *m_button1;
    wxButton *m_button2;
public:
    MyFrame(wxWindow *parent, int id = wxID_ANY, wxString title = wxT("AccelDemo")) : wxFrame(parent, id, title)
    {
        m_button1 = new wxButton( this, wxID_BUTTON_1, wxT("Button1"), wxPoint(10,10), wxSize(80,35), 0 );
        m_button2 = new wxButton( this, wxID_BUTTON_2, wxT("Button2"), wxPoint(10,60), wxSize(80,35), 0 );
        m_button1->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MyFrame::OnButton1Click ), NULL, this );
        m_button2->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MyFrame::OnButton2Click ), NULL, this );

        wxAcceleratorEntry entries[2];
        entries[0].Set(wxACCEL_NORMAL, WXK_F2, wxID_BUTTON_1);
        entries[1].Set(wxACCEL_NORMAL, WXK_F3, wxID_BUTTON_2);
        wxAcceleratorTable accel(2, entries);
        this->SetAcceleratorTable(accel);
    }

    virtual void OnButton1Click( wxCommandEvent& event )
    {
        wxMessageBox("Button1 Clicked");
        event.Skip();
    }

    virtual void OnButton2Click( wxCommandEvent& event )
    {
        wxMessageBox("Button2 Clicked");
        event.Skip();
    }

    ~MyFrame()
    {
        m_button1->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MyFrame::OnButton1Click ), NULL, this );
        m_button2->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MyFrame::OnButton2Click ), NULL, this );
    }
};

class MyApp : public wxApp
{
public:
    virtual bool OnInit()
    {
        MyFrame* frame = new MyFrame(0L);
        frame->Show(true);
        return true;
    }
};

IMPLEMENT_APP(MyApp);
// ----------------- End -------------------------------------

On press F2-F3 buttons nothing happens
Is it wxBug?

Vadim Zeitlin

unread,
Apr 10, 2021, 7:31:04 PMApr 10
to wx-u...@googlegroups.com
On Sat, 10 Apr 2021 06:27:59 -0700 (PDT) Vanta White wrote:

VW> It looks like wxAcceleratorTable doesn't work on Xubuntu 20.04

It does work, but it doesn't generate the events that you expect.

VW> I istalled wxWidgets from Ubuntu repos.
VW> Here is my demo code:
VW>
VW> //------------------- begin----------------------
VW> #include <wx/app.h>
VW> #include <wx/frame.h>
VW> #include <wx/button.h>
VW> #include <wx/msgdlg.h>
VW> #include <wx/accel.h>
VW>
VW> #define wxID_BUTTON_1 1000
VW> #define wxID_BUTTON_2 1001
VW>
VW> class MyFrame : public wxFrame
VW> {
VW> wxButton *m_button1;
VW> wxButton *m_button2;
VW> public:
VW> MyFrame(wxWindow *parent, int id = wxID_ANY, wxString title =
VW> wxT("AccelDemo")) : wxFrame(parent, id, title)
VW> {
VW> m_button1 = new wxButton( this, wxID_BUTTON_1, wxT("Button1"),
VW> wxPoint(10,10), wxSize(80,35), 0 );
VW> m_button2 = new wxButton( this, wxID_BUTTON_2, wxT("Button2"),
VW> wxPoint(10,60), wxSize(80,35), 0 );
VW> m_button1->Connect( wxEVT_COMMAND_BUTTON_CLICKED,
VW> wxCommandEventHandler( MyFrame::OnButton1Click ), NULL, this );
VW> m_button2->Connect( wxEVT_COMMAND_BUTTON_CLICKED,
VW> wxCommandEventHandler( MyFrame::OnButton2Click ), NULL, this );

Here you're connecting to the event handlers on the buttons.

VW> wxAcceleratorEntry entries[2];
VW> entries[0].Set(wxACCEL_NORMAL, WXK_F2, wxID_BUTTON_1);
VW> entries[1].Set(wxACCEL_NORMAL, WXK_F3, wxID_BUTTON_2);
VW> wxAcceleratorTable accel(2, entries);
VW> this->SetAcceleratorTable(accel);

But the accelerator table is associated with the frame itself, so the
events these accelerators generate are only sent to the frame, which
doesn't have any handlers for them.

The simplest fix is to call Connect() on the frame itself, as it will get
all wxEVT_COMMAND_BUTTON_CLICKED events from the buttons anyhow, because
they are bubbled up to it, being command events.


In addition to this, there is a number of other things I'd change in your
code when using recent (i.e. < 10 year old) wx versions:

1. Use wxEVT_BUTTON instead of wxEVT_COMMAND_BUTTON_CLICKED for clarity.
2. Use Bind() instead of Connect() for too many reasons to list here.

VW> virtual void OnButton1Click( wxCommandEvent& event )
VW> {
VW> wxMessageBox("Button1 Clicked");
VW> event.Skip();
VW> }

3. Do not call Skip() in command event handlers, this may well be harmless
but is almost never what you want to do.

VW> ~MyFrame()
VW> {
VW> m_button1->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED,
VW> wxCommandEventHandler( MyFrame::OnButton1Click ), NULL, this );
VW> m_button2->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED,
VW> wxCommandEventHandler( MyFrame::OnButton2Click ), NULL, this );
VW> }

4. Don't do this at all, it is again harmless but just useless.

VW> IMPLEMENT_APP(MyApp);

5. Use wx-prefixed version of the macro.

Regards,
VZ

--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/

Vanta White

unread,
Apr 11, 2021, 5:53:22 AMApr 11
to wx-users
Thanks Vadim.
I changed my code as you said, and now it works OK.
I am happy.
For students and beginners here is my code:
//------------------- The begin of code ----------------------------------
#include <wx/app.h>
#include <wx/frame.h>
#include <wx/button.h>
#include <wx/msgdlg.h>
#include <wx/accel.h>

#define wxID_BUTTON_1 1000
#define wxID_BUTTON_2 1001

class MyFrame : public wxFrame
{
    wxButton *m_button1;
    wxButton *m_button2;
public:
    MyFrame(wxWindow *parent, int id = wxID_ANY, wxString title = wxT("AccelDemo")) : wxFrame(parent, id, title)
    {
        m_button1 = new wxButton( this, wxID_BUTTON_1, wxT("Button1"), wxPoint(10,10), wxSize(80,35), 0 );
        m_button2 = new wxButton( this, wxID_BUTTON_2, wxT("Button2"), wxPoint(10,60), wxSize(80,35), 0 );
        this->Bind( wxEVT_BUTTON, &MyFrame::OnButton1Click, this, wxID_BUTTON_1 );
        this->Bind( wxEVT_BUTTON, &MyFrame::OnButton2Click, this, wxID_BUTTON_2 );

        wxAcceleratorEntry entries[2];

        entries[0].Set(wxACCEL_NORMAL, WXK_F2, wxID_BUTTON_1);
        entries[1].Set(wxACCEL_NORMAL, WXK_F3, wxID_BUTTON_2);
        wxAcceleratorTable accel(2, entries);
        this->SetAcceleratorTable(accel);
    }

    virtual void OnButton1Click( wxCommandEvent& event )
    {
        wxMessageBox("Button1 Clicked");

    }

    virtual void OnButton2Click( wxCommandEvent& event )
    {
        wxMessageBox("Button2 Clicked");
    }

    ~MyFrame(){}


};

class MyApp : public wxApp
{
public:
    virtual bool OnInit()
    {
        MyFrame* frame = new MyFrame(0L);

        frame->Show(true);

        return true;

    }

};

wxIMPLEMENT_APP(MyApp);
//---------------------The end of code --------------------------------------

wxWidgets is the best toolkit for crossplatform applications.

Good luck.
воскресенье, 11 апреля 2021 г. в 02:31:04 UTC+3, Vadim Zeitlin:
Reply all
Reply to author
Forward
0 new messages