提问人:joe_dowson 提问时间:7/31/2023 更新时间:8/1/2023 访问量:32
我应该如何更改我的代码,以便我可以调用 Bind() 函数而不是使用事件表?
How should I change my code so that I can call the Bind() function instead of using the event table?
问:
我正在将WxWidgets 3.2用于我的C++ Windows应用程序。
我需要将数据(例如登录)从一个类传递到另一个类。为此,我创建了一个自定义事件,并使用事件表将事件绑定到处理程序。
例如,我有一个 LoginPanel 类,我想将用户输入的登录名传递给另一个类 - 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;
};
登录面板.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(ChessFrame, wxFrame)
EVT_COMMAND(wxID_ANY, LOGIN_ENTERED, ChessFrame::OnLoginEntered)
wxEND_EVENT_TABLE()
MainFrameFrame::MainFrameFrame(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 MainFrameFrame::OnLoginEntered(wxCommandEvent& event) {
auto login = event.GetString();
}
这就是代码的工作方式,LOGIN_ENTERED事件通常从 LoginPanel 类传递到 MainFrame 类的 OnConnectButton() 处理程序。
由于现在使用事件表不是很现代,因此我想使用 Bind() 函数。我在 MainFrame 类的构造函数中调用 Bind() 函数:
loginPanel->Bind(LOGIN_ENTERED, &ChessFrame::OnLoginEntered, this);
但是,问题是发生错误:
C2664: 'void wxEventFunctorMethod<EventTag,ChessFrame,EventArg,EventHandler>::CheckHandlerArgument(EventArg *)': cannot convert argument 1 from 'wxEvent *' to 'EventArg *'
我应该如何更改我的代码,以便我可以调用 Bind() 函数而不是使用事件表?
答:
1赞
New Pagodi
8/1/2023
#1
我认为主要问题是您用来声明/定义新事件的宏。您应该改用 wxDECLARE_EVENT 和 wxDEFINE_EVENT。
简而言之,改变
DECLARE_EVENT_TYPE(LOGIN_ENTERED, wxCommandEvent)
自
wxDECLARE_EVENT(LOGIN_ENTERED, wxCommandEvent);
和
DEFINE_EVENT_TYPE(LOGIN_ENTERED)
自
wxDEFINE_EVENT(LOGIN_ENTERED, wxCommandEvent);
另外,我建议改变
GetParent()->GetEventHandler()->ProcessEvent(loginEvent);
简单地说
ProcessWindowEvent(loginEvent);
如果窗口本身未处理命令事件,则命令事件将筛选到父窗口。
评论
0赞
Igor
8/1/2023
谢谢更好的解释。最有可能的是,这些宏以某种方式来自旧版本的 wx......
0赞
joe_dowson
8/1/2023
@new-pagodi,您能否澄清一下如何以相反的方向传递事件:从类 MainFrame 传递到类 LoginPanel ?现在我使用表达式:loginPanel->GetEventHandler()->ProcessEvent(event_fromMainFrame)
0赞
New Pagodi
8/1/2023
如果你想这样做,该代码应该可以工作。但通常你不会将事件从父母传递给孩子。如果需要根据父项中检测到的某些事件以某种方式更新子项,通常只需让父项调用子项的任何方法来执行更新。
评论