【问题标题】:How to close a programm in Erlang with WxWidgets?如何使用 WxWidgets 关闭 Erlang 中的程序?
【发布时间】:2015-12-17 15:40:38
【问题描述】:

我在关闭 Erlang 中的程序时遇到问题。我使用 wxWidgets。

-module(g).
-compile(export_all).
-define(height, 500).
-define(width, 500).  
-include_lib("wx/include/wx.hrl").
-define(EXIT,?wxID_EXIT).

init() ->
    start().

start() ->
    Wx = wx:new(),
    Frame = wxFrame:new(Wx, -1, "Line", [{size, {?height, ?width}}]),   
    setup(Frame),
    wxFrame:show(Frame),
    loop(Frame).

setup(Frame) ->
    menuBar(Frame),
    wxFrame:connect(Frame, close_window).

menuBar(Frame) ->
    MenuBar = wxMenuBar:new(),
    File = wxMenu:new(),
    wxMenuBar:append(MenuBar,File,"&Fichier"),
    wxFrame:setMenuBar(Frame,MenuBar),  
    Quit = wxMenuItem:new ([{id,400},{text, "&Quit"}]),
    wxMenu:append (File, Quit).

loop(Frame) ->
    receive
        #wx{event=#wxCommand{type=close_window}} ->
            io:format("quit icon"),
            wxWindow:close(Frame,[]);       

        #wx{id=?EXIT, event=#wxCommand{type=command_menu_selected}} ->
            io:format("quit file menu"),
            wxWindow:close(Frame,[])
    end.

但是程序没有关闭;退出图标或从菜单中退出都不做任何事情。

【问题讨论】:

    标签: erlang wxwidgets


    【解决方案1】:

    你快到了,但有一些错误。

    首先,您的退出选择永远不会生成任何事件,您需要再次使用connect,如下所示:

    Quit = wxMenuItem:new ([{id,400},{text, "&Quit"}]),
    wxFrame:connect(Frame, command_menu_selected),
    

    现在每个退出方法都有一个事件,但它们都没有工作。

    您的退出图标的事件不匹配,因为您的模式匹配中有错误的事件类型,并且菜单退出选择的事件不匹配,因为您正在寻找一个 ID ?EXIT,哪个被定义为 ?wxID_EDIT,它被定义为.. 显然不是 400,这是您在创建退出菜单项时使用的 ID。所以你的接收子句需要改成这样:

    receive
        #wx{event=#wxClose{type=close_window}} ->
            io:format("quit icon"),
            wxFrame:destroy(Frame);
        #wx{id=400, event=#wxCommand{type=command_menu_selected}} ->
            io:format("quit file menu"),
            wxFrame:destroy(Frame)
        end.
    

    【讨论】:

    • 非常感谢您的所有回答,我从中学到了很多!但是这里,退出文件菜单可以正常工作,但是图标关闭windoe,而不是程序,提示被阻止。
    • 好的,我也认为问题一定来自我的代码的其余部分,但我不认为在哪里:codeshare.io/iEitn
    • 是的,我忘了取消注释,但这不是问题。如果我打开窗口,然后通过图标或菜单退出,那效果很好,但是如果我单击菜单 Graph 中的示例,然后单击第一项 Ajouter un sommet。然后我既不能通过图标退出,也不能退出菜单。
    【解决方案2】:

    除了迈克尔关于使用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 应用程序的一种方法”教程/示例,但还没有完成,所以这里缺少很多细节,但是你'编写几个程序后,您会自己偶然发现它们。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-19
      • 2011-01-29
      • 2022-09-13
      • 2012-12-14
      相关资源
      最近更新 更多