如何使用WxWidgets关闭Erlang中的程序?

如何使用WxWidgets关闭Erlang中的程序?,erlang,wxwidgets,Erlang,Wxwidgets,我在关闭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 = wxFr

我在关闭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.

但是这个项目没有结束;退出图标和退出菜单都不起任何作用。

您就快到了,但是有一些错误

首先,您提到的退出选择从未生成任何事件,您需要再次使用
connect
,如下所示:

Quit = wxMenuItem:new ([{id,400},{text, "&Quit"}]),
wxFrame:connect(Frame, command_menu_selected),
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.
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}.
现在,每个quit方法都有一个事件,但它们都不能正常工作

退出图标的事件不匹配,因为模式匹配中的事件类型错误,而菜单退出选择的事件不匹配,因为您正在查找?EXIT的ID,该ID定义为?wxID_EDIT,该ID定义为。。显然不是400,你创建退出菜单项时使用的ID。因此,您的receive子句需要更改为如下内容:

Quit = wxMenuItem:new ([{id,400},{text, "&Quit"}]),
wxFrame:connect(Frame, command_menu_selected),
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.
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}.

除了Michael关于使用监听菜单命令的回答外,几乎任何帧都需要一些标准的事件连接,以便在结束时按照您所期望的方式进行操作,此外,还需要进行任何特定的操作。请注意,这是连接到
close_窗口
事件并使用选项
{skip,true}
。这是为了在信号到达Wx部分之前不会停止传播,Wx部分将按照您期望的方式处理信号(单击一次即可关闭),而不是在某些平台上单击两次即可关闭帧

基本骨架通常如下所示:

Quit = wxMenuItem:new ([{id,400},{text, "&Quit"}]),
wxFrame:connect(Frame, command_menu_selected),
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.
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框架加上它应该管理的任何程序状态——特别是
小部件
数据结构,该结构包含对您以后需要侦听、匹配或操作的任何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
中执行此操作的函数,从零开始重建GUI,以使用户即时看到:

blit(State) ->
    wx:batch(fun() -> freshen_ui(State) end).
如果一次在GUI中有很多元素需要更改,那么从用户的角度来看,blitting要比渐进式地四处移动或隐藏/显示元素更平滑、更快,而且在不同的平台、不同的计算机速度和用户负载中,blitting肯定会有相同的感受(有些Wx后端会出现大量闪烁或中间显示异常)

do_show/1
函数通常看起来像

do_show(#s{frame = Frame}) ->
    ok = wxFrame:raise(Frame),
    wxFrame:requestUserAttention(Frame).

(我一直想写一个基本的“这是构造多窗口wxErlang应用程序的一种方法”教程/示例,但还没有开始,所以这里缺少很多细节,但在编写了几个程序后,您会自己偶然发现它们。)

非常感谢您的回答,我从中学到了很多!但在这里,“退出文件”菜单工作正常,但图标关闭windoe,但程序不关闭,提示被阻止。好的,我还认为问题一定来自我的代码的其余部分,但我不认为是哪里:是的,我忘了取消此功能,但这不是问题所在m、 如果我打开窗口,通过图标或菜单退出,效果很好,但是如果我在菜单图形中单击,然后在第一个项目中单击Ajour-sommet,那么我既不能通过图标退出,也不能通过退出菜单退出。