如何在事件wxWidgets中传递自定义数据

2024-10-02 16:34:10 发布

您现在位置:Python中文网/ 问答频道 /正文

处境

我目前正在用wxPython(用于Python的wxWidgets)编写一个应用程序

在这个应用程序中,会显示一个对话列表,每行末尾都有一个“打开对话”按钮。让我们将此窗口称为“所有对话”

单击任意一个按钮调用函数“打开会话(self,event)”,该函数显示完整的会话

我想做的是,在生成“所有对话”窗口时,在每个“绑定”事件或每个“wxButton”对象中传递一些自定义数据,例如字符串(例如联系人的名称);之后,当单击按钮时,它将在“event”参数中传递所述数据,并在函数中使用类似contact = event.CustomData["recipient"]的内容进行访问

发行

参考documentation,我找到了“Bind”方法的“userData”关键字,但它似乎在Python中不起作用

self.openConversation_button.Bind(wx.EVT_BUTTON, self.open_conversation, userData="test")
TypeError: _EvtHandler_Bind() got an unexpected keyword argument 'userData'

更新

我已经将萨克森Rolf的解决方案标记为正确的,因为它最适合我的需要,但是我建议一般使用VZ建议的定制事件系统


Tags: 函数selfevent应用程序列表bindwxpython事件
3条回答

一般来说,定义自定义事件的建议绝对是正确的,但如果您只需要一个字符串和/或数字,还可以重新调整现有wxCommandEvent类的用途,并使用其SetString()SetInt()方法

将自定义数据传递到callback事件的一种简单方法是使用lambda函数。
e、 g

import wx

class ButtonFrame(wx.Frame):
    def __init__(self, value):
        wx.Frame.__init__(self,None)
        self.btn1 = wx.Button(self, -1, ("a"))
        self.btn2 = wx.Button(self, -1, ("b"))
        self.btn3 = wx.Button(self, -1, ("No flag"))
        self.btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.btnSizer.Add(self.btn1 , 0, wx.RIGHT, 10)
        self.btnSizer.Add(self.btn2 , 0, wx.RIGHT, 10)
        self.btnSizer.Add(self.btn3 , 0, wx.RIGHT, 10)
        self.btn1.Bind(wx.EVT_BUTTON,  lambda event: self.OnButton(event, flag="A"))
        self.btn2.Bind(wx.EVT_BUTTON,  lambda event: self.OnButton(event, flag="B"))
        self.btn3.Bind(wx.EVT_BUTTON,  self.OnButton)
        self.SetSizer(self.btnSizer)
        self.Show()

    def OnButton(self,event, flag=None):
        if flag:
            print ("Button pressed was "+flag)
        else:
            print ("A button got pressed")

if __name__ == "__main__":
    app = wx.App()
    ButtonFrame(None)
    app.MainLoop()

对于任何一个完全C++的人来说,这里是:

#include <wx/wx.h>

struct CustomData final : public wxClientData {
    std::string myString;
};

struct MyApp final : public wxApp {
    bool OnInit() final;
};

struct MyWindow final : public wxFrame {
    static constexpr int ID_MY_BUTTON{ 42 };

                MyWindow();
                MyWindow( MyWindow const & ) = delete;
    MyWindow &  operator=( MyWindow const & ) = delete;
    void        OnButton( wxCommandEvent & event );

    wxDECLARE_EVENT_TABLE();
};

bool MyApp::OnInit() {
    MyWindow * const window{ new MyWindow() };
    window->Show( true );
    return true;
}

MyWindow::MyWindow() {
    wxButton * const myButton{ new wxButton( this, ID_MY_BUTTON ) };
    CustomData * const myData{ new CustomData() };
    myData->myString = "Hello World!";
    myButton->SetClientObject( myData );
}

void MyWindow::OnButton( wxCommandEvent & event ) {
    wxEvtHandler const * const eventObject{ static_cast< wxEvtHandler * >( event.GetEventObject() ) };
    if ( eventObject == nullptr ) {
        return;
    }

    CustomData const * const myData{ static_cast< CustomData const * >( eventObject->GetClientObject() ) };
    if ( myData == nullptr ) {
        return;
    }

    std::cout << myData << "\n";
}

wxIMPLEMENT_APP( MyApp );

wxBEGIN_EVENT_TABLE( MyWindow, wxFrame )
EVT_BUTTON( MyWindow::ID_MY_BUTTON, MyWindow::OnButton )
wxEND_EVENT_TABLE()

不需要删除CustomData实例,wxWidgets会处理它。 这里的关键步骤是:

  • 继承wxClientData类以附加数据
  • 使用堆分配的自定义数据对象调用wxEvtHandler::SetClientObject()
  • 在回调中,使用wxCommandEvent::GetEventObject()检索按钮
  • 使用wxEvtHandler::GetClientObject()检索自定义数据

相关问题 更多 >