除了迈克尔关于使用connect/3 来侦听菜单命令的回答之外,几乎任何框架都需要一些标准事件连接才能按照您期望它们在关闭时的行为方式,以及您正在进行的任何特定事情。请注意,这是连接到close_window 事件并使用选项{skip, true}。这样一来,信号在到达 Wx 部分之前不会停止传播,Wx 将以您期望的方式处理它(单击关闭),而不是在某些平台上需要单击两次关闭框架。
基本骨架通常如下所示:
init(Args) ->
Wx = wx:new(),
Frame = wxFrame:new(Wx, ?wxID_ANY, ""),
% Generate whatever state the process represents
State = some_state_initializer(Args),
% Go through the steps to create your widget layout, etc.
WidgetReferences = make_ui(Frame),
% The standardish connects nearly any frame will need.
ok = wxFrame:connect(Frame, close_window, [{skip, true}]),
ok = wxFrame:connect(Frame, command_button_clicked),
ok = wxFrame:connect(Frame, command_menu_selected),
% Add more connects here depending on what you need.
% Adjust the frame size and location, if necessary
Pos = initial_position(Args),
Size = initial_size(Args),
ok = wxFrame:move(Frame, Pos),
ok = wxFrame:setSize(Frame, Size),
wxFrame:show(Frame),
% Optional step to add this frame to a UI state manager if you're
% writing a multi-window application.
ok = gui_manager:add_live(self()),
% Required return for wx_object behavior
{Frame, State}.
与原作有点离题,但强烈相关...
许多 wxWidgets 应用程序都非常与此类似,根据需要进行自定义,而不是通过重新编写所有内容,而是通过定义您自己的回调模块并将其作为参数传递:
init({Mod, Args}) ->
% ...
PartialState = blank_state([{mod, Mod}, {frame, Frame}, {wx, Wx}]),
State = Mod:finalize(PartialState, Args),
blank_state/1 接受一个 proplist 并返回以后的实际数据结构(通常是此级别的记录,类似于 #s{mod, frame, wx, widgets, data}),Mod:finalize/2 采用不完整状态和初始参数和返回一个完整的 GUI 框架以及它应该管理的任何程序状态——特别是 widgets 数据结构,它携带对您稍后需要侦听、匹配或操作的任何 GUI 元素的引用。
稍后您将拥有一些非常基本的通用处理程序,所有帧都可能需要处理,并将任何其他消息传递给特定的Mod:
handle_call(Message, From, State = #s{mod = Mod}) ->
Mod:handle_call(Message, From, State).
handle_cast(blit, State) ->
{ok, NewState} = do_blit(State),
{noreply, NewState};
handle_cast(show, State) ->
ok = do_show(State),
{noreply, State};
handle_cast(Message, State = #s{mod = Mod}) ->
Mod:handle_cast(Message, State).
在这种情况下,do_blit/1 最终在回调模块中调用 Mod:blit/1,该模块重建和刷新 GUI,通过调用在 wx:batch/1 内执行此操作的函数从零开始重建它,以使其对用户立即显示:
blit(State) ->
wx:batch(fun() -> freshen_ui(State) end).
如果您要在 GUI 中一次更改大量元素,从用户的角度来看,blitting 比在您移动时逐渐改变或隐藏/显示元素要平滑和快速得多——而且 很多 更确定跨平台和各种计算机速度和用户空间负载感觉相同(一些 Wx 后端会产生很多闪烁或中间显示异常)。
do_show/1 函数通常看起来像
do_show(#s{frame = Frame}) ->
ok = wxFrame:raise(Frame),
wxFrame:requestUserAttention(Frame).
(我一直想写一个基本的“这是构建多窗口 wxErlang 应用程序的一种方法”教程/示例,但还没有完成,所以这里缺少很多细节,但是你'编写几个程序后,您会自己偶然发现它们。)