如何更改我的代码,以便我可以调用`Bind()`函数,而不是使用事件表?

huangapple go评论83阅读模式
英文:

How should I change my code so that I can call the Bind() function instead of using the event table?

问题

I am using WxWidgets 3.2 for my C++ Windows application.

I need to pass data (eg login) from one class to another. To do this, I create a custom event and use the event table to bind the event to the handler.

For example, I have a LoginPanel class and I want to pass the login entered by the user to another class - MainFrame.

LoginPanel.h

DECLARE_EVENT_TYPE(LOGIN_ENTERED, wxCommandEvent)

enum class Buttons_ID {
    ID_CONNECT_BUTTON = wxID_HIGHEST + 1,
};

class LoginPanel : public wxPanel {
public:
    LoginPanel(wxWindow* parent, wxWindowID id = wxID_ANY);

private:
    void OnConnectButton(wxCommandEvent& event);
    wxTextCtrl* usernameInput;
};

LoginPanel.cpp

DEFINE_EVENT_TYPE(LOGIN_ENTERED)
LoginPanel::LoginPanel(wxWindow* parent, wxWindowID id)
    : wxPanel(parent, id) {
	wxButton* connectButton = new wxButton(loginTab, wxID_ANY, "Connect");
    connectButton->Bind(wxEVT_BUTTON, &LoginPanel::OnConnectButton, this);
}

void LoginPanel::OnConnectButton(wxCommandEvent& event) {
    wxString username = usernameInput->GetValue();
    wxCommandEvent loginEvent(LOGIN_ENTERED, GetId());
    loginEvent.SetString(username);
    GetParent()->GetEventHandler()->ProcessEvent(loginEvent);
}

MainFrame.h

class MainFrame : public wxFrame {
public:
    MainFrame(const wxString& title);
    ~MainFrame();

private:
    LoginPanel * loginPanel;           

public:
    void ShowLoginPanel();
    void OnLoginEntered(wxCommandEvent& event);
    wxDECLARE_EVENT_TABLE(); 
};

MainFrame.cpp

wxBEGIN_EVENT_TABLE(MainFrame, wxFrame)                             
    EVT_COMMAND(wxID_ANY, LOGIN_ENTERED, MainFrame::OnLoginEntered) 
wxEND_EVENT_TABLE()                                                  

MainFrame::MainFrame(const wxString& title)
    : wxFrame(nullptr, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE & ~wxRESIZE_BORDER) {
    wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);

    loginPanel = new LoginPanel(this, wxID_ANY);
    mainSizer->Add(loginPanel, 1, wxEXPAND);
    SetSizer(mainSizer);
    ShowLoginPanel();
}

void MainFrame::OnLoginEntered(wxCommandEvent& event) {
    auto login = event.GetString();
}

This is how the code works and the LOGIN_ENTERED event is normally passed from the LoginPanel class to the OnConnectButton() handler of the MainFrame class.

Since using the event table is not very modern now, I want to use the Bind() function. I call the Bind() function in the constructor of the MainFrame class:

loginPanel->Bind(LOGIN_ENTERED, &MainFrame::OnLoginEntered, this);

However, the problem is that an error occurs:

C2664: 'void wxEventFunctorMethod<EventTag,MainFrame,EventArg,EventHandler>::CheckHandlerArgument(EventArg *)': cannot convert argument 1 from 'wxEvent *' to 'EventArg *'

How should I change my code so that I can call the Bind() function instead of using the event table?

英文:

I am using WxWidgets 3.2 for my C++ Windows application.

I need to pass data (eg login) from one class to another. To do this, I create a custom event and use the event table to bind the event to the handler.

For example, I have a LoginPanel class and I want to pass the login entered by the user to another class - MainFrame.

LoginPanel.h

DECLARE_EVENT_TYPE(LOGIN_ENTERED, wxCommandEvent)

enum class Buttons_ID {
    ID_CONNECT_BUTTON = wxID_HIGHEST + 1,
};

class LoginPanel : public wxPanel {
public:
    LoginPanel(wxWindow* parent, wxWindowID id = wxID_ANY);

private:
    void OnConnectButton(wxCommandEvent&amp; event);
    wxTextCtrl* usernameInput;
};

LoginPanel.cpp

DEFINE_EVENT_TYPE(LOGIN_ENTERED)
LoginPanel::LoginPanel(wxWindow* parent, wxWindowID id)
    : wxPanel(parent, id) {
	wxButton* connectButton = new wxButton(loginTab, wxID_ANY, &quot;Connect&quot;);
    connectButton-&gt;Bind(wxEVT_BUTTON, &amp;LoginPanel::OnConnectButton, this);
}

void LoginPanel::OnConnectButton(wxCommandEvent&amp; event) {
    wxString username = usernameInput-&gt;GetValue();
    wxCommandEvent loginEvent(LOGIN_ENTERED, GetId());
    loginEvent.SetString(username);
    GetParent()-&gt;GetEventHandler()-&gt;ProcessEvent(loginEvent);
}

MainFrame.h

class MainFrame : public wxFrame {
public:
    MainFrame(const wxString&amp; title);
    ~MainFrame();

private:
    LoginPanel * loginPanel;           

public:
    void ShowLoginPanel();
    void OnLoginEntered(wxCommandEvent&amp; event);
    wxDECLARE_EVENT_TABLE(); 
};

MainFrame.cpp

wxBEGIN_EVENT_TABLE(ChessFrame, wxFrame)                             
    EVT_COMMAND(wxID_ANY, LOGIN_ENTERED, ChessFrame::OnLoginEntered) 
wxEND_EVENT_TABLE()                                                  

MainFrameFrame::MainFrameFrame(const wxString&amp; title)
    : wxFrame(nullptr, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE &amp; ~wxRESIZE_BORDER) {
    wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);

    loginPanel = new LoginPanel(this, wxID_ANY);
    mainSizer-&gt;Add(loginPanel, 1, wxEXPAND);
    SetSizer(mainSizer);
    ShowLoginPanel();
}

void MainFrameFrame::OnLoginEntered(wxCommandEvent&amp; event) {
    auto login = event.GetString();
}

This is how the code works and the LOGIN_ENTERED event is normally passed from the LoginPanel class to the OnConnectButton() handler of the MainFrame class.

Since using the event table is not very modern now, I want to use the Bind() function. I call the Bind() function in the constructor of the MainFrame class:

loginPanel-&gt;Bind(LOGIN_ENTERED, &amp;ChessFrame::OnLoginEntered, this);

However, the problem is that an error occurs:

C2664: &#39;void wxEventFunctorMethod&lt;EventTag,ChessFrame,EventArg,EventHandler&gt;::CheckHandlerArgument(EventArg *)&#39;: cannot convert argument 1 from &#39;wxEvent *&#39; to &#39;EventArg *&#39;

How should I change my code so that I can call the Bind() function instead of using the event table?

答案1

得分: 1

我认为主要问题是您用于声明/定义新事件的宏。您应该使用 wxDECLARE_EVENTwxDEFINE_EVENT

简而言之,将以下代码更改为:

wxDECLARE_EVENT(LOGIN_ENTERED, wxCommandEvent);

wxDEFINE_EVENT(LOGIN_ENTERED, wxCommandEvent);

此外,我建议将以下代码更改为:

ProcessWindowEvent(loginEvent);

如果窗口本身未处理命令事件,这些事件将向上过滤到父窗口。

英文:

I think the main issue is the macro you're using to declare/define your new events. You should use wxDECLARE_EVENT and wxDEFINE_EVENT instead.

In short, change

DECLARE_EVENT_TYPE(LOGIN_ENTERED, wxCommandEvent)

to

wxDECLARE_EVENT(LOGIN_ENTERED, wxCommandEvent);

and

DEFINE_EVENT_TYPE(LOGIN_ENTERED)

to

wxDEFINE_EVENT(LOGIN_ENTERED, wxCommandEvent);

Also, I would suggest changing

GetParent()-&gt;GetEventHandler()-&gt;ProcessEvent(loginEvent);

to simply

ProcessWindowEvent(loginEvent);

Command events will filter up to the parent windows if not handled by the window itself.

huangapple
  • 本文由 发表于 2023年7月31日 23:43:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76805182.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定