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

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

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

  1. DECLARE_EVENT_TYPE(LOGIN_ENTERED, wxCommandEvent)
  2. enum class Buttons_ID {
  3. ID_CONNECT_BUTTON = wxID_HIGHEST + 1,
  4. };
  5. class LoginPanel : public wxPanel {
  6. public:
  7. LoginPanel(wxWindow* parent, wxWindowID id = wxID_ANY);
  8. private:
  9. void OnConnectButton(wxCommandEvent& event);
  10. wxTextCtrl* usernameInput;
  11. };

LoginPanel.cpp

  1. DEFINE_EVENT_TYPE(LOGIN_ENTERED)
  2. LoginPanel::LoginPanel(wxWindow* parent, wxWindowID id)
  3. : wxPanel(parent, id) {
  4. wxButton* connectButton = new wxButton(loginTab, wxID_ANY, "Connect");
  5. connectButton->Bind(wxEVT_BUTTON, &LoginPanel::OnConnectButton, this);
  6. }
  7. void LoginPanel::OnConnectButton(wxCommandEvent& event) {
  8. wxString username = usernameInput->GetValue();
  9. wxCommandEvent loginEvent(LOGIN_ENTERED, GetId());
  10. loginEvent.SetString(username);
  11. GetParent()->GetEventHandler()->ProcessEvent(loginEvent);
  12. }

MainFrame.h

  1. class MainFrame : public wxFrame {
  2. public:
  3. MainFrame(const wxString& title);
  4. ~MainFrame();
  5. private:
  6. LoginPanel * loginPanel;
  7. public:
  8. void ShowLoginPanel();
  9. void OnLoginEntered(wxCommandEvent& event);
  10. wxDECLARE_EVENT_TABLE();
  11. };

MainFrame.cpp

  1. wxBEGIN_EVENT_TABLE(MainFrame, wxFrame)
  2. EVT_COMMAND(wxID_ANY, LOGIN_ENTERED, MainFrame::OnLoginEntered)
  3. wxEND_EVENT_TABLE()
  4. MainFrame::MainFrame(const wxString& title)
  5. : wxFrame(nullptr, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE & ~wxRESIZE_BORDER) {
  6. wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
  7. loginPanel = new LoginPanel(this, wxID_ANY);
  8. mainSizer->Add(loginPanel, 1, wxEXPAND);
  9. SetSizer(mainSizer);
  10. ShowLoginPanel();
  11. }
  12. void MainFrame::OnLoginEntered(wxCommandEvent& event) {
  13. auto login = event.GetString();
  14. }

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:

  1. 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

  1. DECLARE_EVENT_TYPE(LOGIN_ENTERED, wxCommandEvent)
  2. enum class Buttons_ID {
  3. ID_CONNECT_BUTTON = wxID_HIGHEST + 1,
  4. };
  5. class LoginPanel : public wxPanel {
  6. public:
  7. LoginPanel(wxWindow* parent, wxWindowID id = wxID_ANY);
  8. private:
  9. void OnConnectButton(wxCommandEvent&amp; event);
  10. wxTextCtrl* usernameInput;
  11. };

LoginPanel.cpp

  1. DEFINE_EVENT_TYPE(LOGIN_ENTERED)
  2. LoginPanel::LoginPanel(wxWindow* parent, wxWindowID id)
  3. : wxPanel(parent, id) {
  4. wxButton* connectButton = new wxButton(loginTab, wxID_ANY, &quot;Connect&quot;);
  5. connectButton-&gt;Bind(wxEVT_BUTTON, &amp;LoginPanel::OnConnectButton, this);
  6. }
  7. void LoginPanel::OnConnectButton(wxCommandEvent&amp; event) {
  8. wxString username = usernameInput-&gt;GetValue();
  9. wxCommandEvent loginEvent(LOGIN_ENTERED, GetId());
  10. loginEvent.SetString(username);
  11. GetParent()-&gt;GetEventHandler()-&gt;ProcessEvent(loginEvent);
  12. }

MainFrame.h

  1. class MainFrame : public wxFrame {
  2. public:
  3. MainFrame(const wxString&amp; title);
  4. ~MainFrame();
  5. private:
  6. LoginPanel * loginPanel;
  7. public:
  8. void ShowLoginPanel();
  9. void OnLoginEntered(wxCommandEvent&amp; event);
  10. wxDECLARE_EVENT_TABLE();
  11. };

MainFrame.cpp

  1. wxBEGIN_EVENT_TABLE(ChessFrame, wxFrame)
  2. EVT_COMMAND(wxID_ANY, LOGIN_ENTERED, ChessFrame::OnLoginEntered)
  3. wxEND_EVENT_TABLE()
  4. MainFrameFrame::MainFrameFrame(const wxString&amp; title)
  5. : wxFrame(nullptr, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE &amp; ~wxRESIZE_BORDER) {
  6. wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
  7. loginPanel = new LoginPanel(this, wxID_ANY);
  8. mainSizer-&gt;Add(loginPanel, 1, wxEXPAND);
  9. SetSizer(mainSizer);
  10. ShowLoginPanel();
  11. }
  12. void MainFrameFrame::OnLoginEntered(wxCommandEvent&amp; event) {
  13. auto login = event.GetString();
  14. }

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:

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

However, the problem is that an error occurs:

  1. 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

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

  1. wxDECLARE_EVENT(LOGIN_ENTERED, wxCommandEvent);

  1. wxDEFINE_EVENT(LOGIN_ENTERED, wxCommandEvent);

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

  1. 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

  1. DECLARE_EVENT_TYPE(LOGIN_ENTERED, wxCommandEvent)

to

  1. wxDECLARE_EVENT(LOGIN_ENTERED, wxCommandEvent);

and

  1. DEFINE_EVENT_TYPE(LOGIN_ENTERED)

to

  1. wxDEFINE_EVENT(LOGIN_ENTERED, wxCommandEvent);

Also, I would suggest changing

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

to simply

  1. 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:

确定