在wxErlang中,如何获取XRC加载的对象层次结构中的子控件引用?

后端开发 2026-07-09

我是刚接触Erlang、wxWidgets和 wxErlang。我已经有一个示例在运行,它可以从xrc文件加载一个wxFrame,并显示这个框架及其所有子面板/控件等。如何获取到这些子对象的引用,以便将它们的命令消息连接到处理函数?

我能够用构造函数等手动创建一切,但不知道如何在从xrc文件加载的对象层次结构中进入这些子对象。

Slimmed-down start of code:

-module(xt4).

-export([start/0]).

-include_lib("wx/include/wx.hrl").

start() ->
    wx:new(),
    WxXmlResource = wxXmlResource:new(),
    wxXmlResource:load(WxXmlResource, "TryMyLayout1.xrc"),
    MyXrcFrame = wxXmlResource:loadFrame(WxXmlResource, wx:null(), "ID_MAINFRAME"),
    wxFrame:show(MyXrcFrame),

...
handle_click_dlg(#wx{userData = #{frame := Frame, env := Env}}, _Event) ->
    wx:set_env(Env),
    MsgDlg = wxMessageDialog:new(Frame, "Inside handle_click_dlg"),
    wxDialog:showModal(MsgDlg).

在这里,我将如何引用从这个XRC的 XML节点创建的按钮(如下所列):

<object class="wxButton" name="ID_BUTTON_CONNECT_TO_SERVER">

以便我可以做出像下面这样的操作?...

    wxButton:connect(MyXrcButton, 
                         command_button_clicked, 
                         [{callback, fun handle_click_dlg/2}, 
             {userData, #{frame => MyXrcFrame, env => wx:get_env()}}]),

Start of TryMyLayout1.xrc:

<?xml version="1.0" encoding="UTF-8"?>
<resource version="2.3.0.1" xmlns="http://www.wxwidgets.org/wxxrc">
    <object class="wxFrame" name="ID_MAINFRAME">
        <style>wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX</style>
        <size>400,300</size>
        <title>MainFrame</title>
        <centered>1</centered>
        <object class="wxPanel" name="ID_PANEL">
            <style>wxSUNKEN_BORDER|wxTAB_TRAVERSAL</style>
            <exstyle>wxWS_EX_VALIDATE_RECURSIVELY</exstyle>
            <object class="wxBoxSizer" name="MainSizer">
                <orient>wxHORIZONTAL</orient>
                <object class="sizeritem">
                    <flag>wxGROW|wxALL</flag>
                    <border>5</border>
                    <object class="wxSplitterWindow" name="ID_MAINSPLITTERWINDOW">
                        <style>wxSP_3DBORDER|wxSP_3DSASH|wxNO_BORDER</style>
                        <orientation>vertical</orientation>
                        <sashpos>50</sashpos>
                        <minsize>0</minsize>
                        <object class="wxPanel" name="ID_PANEL1">
                            <style>wxSUNKEN_BORDER|wxTAB_TRAVERSAL</style>
                            <exstyle>wxWS_EX_VALIDATE_RECURSIVELY</exstyle>
                            <object class="wxBoxSizer">
                                <orient>wxVERTICAL</orient>
                                <object class="sizeritem">
                                    <flag>wxALIGN_CENTER_HORIZONTAL|wxALL</flag>
                                    <border>5</border>
                                    <object class="wxButton" name="ID_BUTTON_CREATE_SERVER">
                                        <label>Create Server</label>
                                    </object>
                                </object>
                                <object class="sizeritem">
                                    <flag>wxALIGN_CENTER_HORIZONTAL|wxALL</flag>
                                    <border>5</border>
                                    <object class="wxButton" name="ID_BUTTON_CONNECT_TO_SERVER">
                                        <label>Connect To Server</label>
                                    </object>
                                </object>

解决方案

可以将父窗口绑定到控件将要发送的消息(如果没有附加回调的话?)。这种方法的一个重要方面,可能也适用于问题中的代码,是使用wxXmlResource:getXRCID(从xrc xml的控件 @name获取)来获取从xrc文件加载的对象的ID。这些ID可以传给函数,或者应该能够用于检索它们所引用的对象。

注:上面的问题提到的xml按钮,@name=ID_BUTTON_CREATE_SERVER和 ID_BUTTON_CONNECT_TO_SERVER,而下面的代码引用的对象的 @name为 ID_FILE_NEW和 ID_HELP_ABOUT,但原理是一致的。

    WxXmlResource = wxXmlResource:new(),
    wxXmlResource:initAllHandlers(WxXmlResource),
    wxXmlResource:load(WxXmlResource, "TryMyLayout1.xrc"),
    MyXrcFrame = wxXmlResource:loadFrame(WxXmlResource, wx:null(), "ID_MAINFRAME"),

% Gather the IDs of the objects loaded from the XRC file 
%(Are there better techniques?)
    MenuIdFileNew = wxXmlResource:getXRCID("ID_FILE_NEW"),
    MenuIdHelpAbout = wxXmlResource:getXRCID("ID_HELP_ABOUT"),
    IDs={{"ID_FILE_NEW",MenuIdFileNew},{"ID_HELP_ABOUT",MenuIdHelpAbout}},

wxFrame:connect(MyXrcFrame, command_menu_selected),


loop(Frame,IDs) ->
    {{"ID_FILE_NEW",ID_FILE_NEW},{"ID_HELP_ABOUT",ID_HELP_ABOUT}} = IDs,

    receive
            #wx{id=ID_FILE_NEW, event=#wxCommand{}} ->
            io:format("Received XRC command id ID_FILE_NEW (~p)~n",[ID_FILE_NEW]),
                loop(Frame,IDs);
            #wx{id=ID_HELP_ABOUT, event=#wxCommand{}} ->
            io:format("Received XRC command id ID_HELP_ABOUT(~p)~n",[ID_HELP_ABOUT]),
                loop(Frame,IDs)
        end.
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章