首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有必要为wxErlang小部件发明Is吗?

有必要为wxErlang小部件发明Is吗?
EN

Stack Overflow用户
提问于 2010-11-19 06:52:18
回答 3查看 1.8K关注 0票数 3

我一直在研究Erlang的wx模块和this教程。我以前没有使用过wxwidgets,所以也许这就是它的工作方式,但这段代码对我来说似乎真的很糟糕:

代码语言:javascript
复制
%% create widgets
    T1001 = wxTextCtrl:new(Panel, 1001,[]),
    ST2001 = wxStaticText:new(Panel, 2001,"Output Area", []),
    B101  = wxButton:new(Panel, 101, [{label, "&Countdown"}]),
    B102  = wxButton:new(Panel, ?wxID_EXIT, [{label, "E&xit"}]),
    wxFrame:show(Frame),

在创建小部件时,人们真的需要为它们分配小部件ID吗?以小部件的ID命名指向小部件的变量是否正常?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-11-20 01:15:03

我不知道Erlang,但在C++ (以及我知道的其他绑定)中,使用wxID_ANY作为小部件id通常更可取,这意味着您不关心它的特定值,然后使用Connect()处理来自小部件的事件。如果您需要稍后通过id查找小部件(尽管您也可以使用小部件名称),或者如果您需要id的连续范围(例如,使用id 100,101,...,109作为计算器的按钮,因为您可以很容易地从其id推断出每个按钮的值),显式id可能会很方便,但没有必要总是使用它们。

至于命名,当然,没有必要使用这种奇怪的约定(快速浏览一下教程就会发现,这是作者的个人喜好--不用说,我不会分享)。

票数 8
EN

Stack Overflow用户

发布于 2010-11-22 07:03:33

像上面提到的VZ一样,如果以后不需要根据小部件的id查找小部件,则可以使用wxID_ANY。

然而,我认为用it来命名变量不仅是不正常的,而且是一个非常糟糕的想法。根据变量的含义来命名它们,而不是使用一些晦涩难懂的id

另外,你最好定义你需要的‘d,并给它们适当的(语义)名称,这样它们只在一个地方定义,以后你就可以很容易地更改’d,而不会影响你的程序,如下所示:

代码语言:javascript
复制
-define(ID_TEXT_CTRL, 1001).
-define(ID_OUTPUT_AREA, 2001).
-define(ID_COUNTDOWN_BUTTON, 101).
-define(ID_EXIT_BUTTON, ?wxID_EXIT).

TextCtrl = wxTextCtrl:new(Panel, ?ID_TEXT_CTRL,[]),
OutputArea = wxStaticText:new(Panel, ?ID_OUTPUT_AREA,"Output Area", []),
CountdownButton  = wxButton:new(Panel, ?ID_COUNTDOWN_BUTTON, [{label, "&Countdown"}]),
ExitButton  = wxButton:new(Panel, ?ID_EXIT_BUTTON, [{label, "E&xit"}])

您可以将定义放在.erl文件中(如果只有一个),也可以放在一个.hrl文件中,所有与图形用户界面相关的.erl文件都必须包含该文件。

票数 5
EN

Stack Overflow用户

发布于 2015-12-31 14:53:25

不是的。您希望通过ID查找内容的情况与您希望在C++中通过ID查找内容的情况大致相同。这适用于我能想到的任何小部件库--每次响应信号编码的some_standard_button_name并匹配像?wxID_OK这样的标签时,您都在等待一个由宏隐藏的标签表示的数字ID。大多数图形用户界面库都做了很多预处理来消除这个问题,所以你通常不会注意到它(对于像Qt这样的sooper-dooper库,它仍然在后台运行,所有的代码在成为“真正的”C++之前都是run through a precompiler的……)。

那么,你如何获得一个已经创建的wx东西呢?通过使用其返回的引用。

几乎每个wx*:new()调用都返回一个对象referencenote1。这是一个抽象引用(内部是一个元组,但不要依赖于此),它有足够的信息供Erlang绑定和Wx系统进程明确地讨论已创建的特定Wx对象。传递这些引用是稍后访问Wx对象的典型方式:

代码语言:javascript
复制
GridSz = wxFlexGridSizer:new(2, 2, 4, 4),
ok = wxFlexGridSizer:setFlexibleDirection(GridSz, ?wxHORIZONTAL),
ok = wxFlexGridSizer:addGrowableCol(GridSz, 1),

然而,一种不太明显的情况是,当您想要像输入字段网格这样的东西时,您可以循环或按键值拖动:

代码语言:javascript
复制
Scripts = [katakana, hiragana, kanji, latin],
Ilks    = [family, given, middle, maiden],
Rows    = [{Tag, j(J, Tag)} || Tag <- Scripts],
Cols    = [{Tag, j(J, Tag)} || Tag <- Ilks],
{GridSz, Fields} = zxw:text_input_grid(Dialog, Rows, Cols),

% Later on, extracting only present values as

Keys = [{S, I} || S <- Scripts, I <- Ilks],
Extract =
    fun(Key, Acc) ->
        case wxTextCtrl:getValue(proplists:get_value(Key, Fields)) of
            ""  -> Acc;
            Val -> [{Key, Val} | Acc]
        end
    end,
NewParts = lists:foldl(Extract, [], Keys),

诸若此类。(zxw:text_input_grid/3 definitiondocs)

只有一次你确实想要通过它的ID而不是它的对象引用来引用一个对象,这和在C++中是一样的:当你在监听一个特定的单击事件时:

代码语言:javascript
复制
{AddressPicker, _, _, AddressSz} =
    zxw:list_picker(Frame,
                    ?widgetADDRESS, ?addADDRESS, ?delADDRESS,
                    AddressHeader, Addresses, j(J, address)),

然后在通用wx_object的消息处理循环中:

代码语言:javascript
复制
handle_event(Wx = #wx{id    = Id,
                      event = #wxCommand{type = command_button_clicked}},
             State) ->
    case Id of
        ?editNAME     -> {noreply, edit_name(State)};
        ?editDOB      -> {noreply, edit_dob(State)};
        ?editPORTRAIT -> {noreply, edit_portrait(State)};
        ?addCONTACT   -> {noreply, add_contact_info(State)};
        ?delCONTACT   -> {noreply, del_contact_info(State)};
        ?addADDRESS   -> {noreply, add_address_info(State)};
        ?delADDRESS   -> {noreply, del_address_info(State)};
        _ ->
            ok = unexpected(Wx),
            {noreply, State}
    end;
handle_event(Wx = #wx{id    = Id,
                      event = #wxList{type      = command_list_item_selected,
                                      itemIndex = Index}},
             State) ->
    case Id of
        ?widgetCONTACT -> {noreply, update_selection(contact, Index, State)};
        ?widgetADDRESS -> {noreply, update_selection(address, Index, State)};
        _ ->
            ok = unexpected(Wx),
            {noreply, State}
    end;

第一个子句专门处理非标准按钮上的单击,第二个子句处理列表控件小部件选择事件,以便在界面中执行一些任意操作。虽然展开#wx{}事件记录在视觉上不是很吸引人,但在子句结构中使用匹配使得这段图形用户界面代码在维护期间比缺乏匹配的语言中所需的检查、异常捕获和后续if elif elif elif elif...switchcase..break等类型代码的级联更容易理解。

在上面的例子中,所有特定的In都被标记为宏,这与C++和其他C++小部件工具包中的Wx中的方法完全相同。大多数情况下,您的需求只是通过使用标准的预定义Wx按钮类型并相应地做出反应来满足的;上面的示例来自由于某些特定接口要求而被迫略低于Wx按钮类型的代码(并且等效的C++代码在本质上是相同的,但要完成相同的任务却要冗长得多)。

一些使用稍高级别语言的平台有不同的方法来处理身份问题。iOS和Android widget工具包(就这一点而言,还有QtQuick )将这个细节隐藏在某种更通用的对象引用后面,而不是依赖于ID。也就是说,这些小部件工具包基本上存储了在{ID => ObjReference}散列中创建的所有小部件,从每个信号中提取ID,在将控制传递给处理回调之前检索对象引用,并返回存储在散列中的引用,而不是直接传递ID。

这很巧妙,但这不是绑定到C样式枚举即标签代码的旧小部件工具包的工作方式。当一切都说完了,计算机仍然只有一种真正的类型:整数--我们在此基础上发明了各种各样的其他东西,并享受类型的幻觉和其他乐趣。

我们也可以在Erlang中做这个ID- to -reference的事情,但是通常编写WxErlang代码的方式是遵循C++的传统,在宏标签后面使用对象ID,对于您无法避免唯一标识的事件,使用对象引用和标准标签来处理其他所有事件。

上面使用的zx_widgets库是一组预定义的元小部件,涵盖了一些最常见的样板字段构造和返回数据结构的情况,这些数据结构在功能上易于处理。Wx的OOP风格在某些方面并不适合Erlang (由于这个原因,您用Erlang编写的最好的函数很可能是GUI代码),因此有时需要额外的一层,以使逻辑承载的代码与Erlang的其余部分保持一致。然而,在任何语言和环境中,GUI代码都是相当烦人的。

note1:有一些奇怪的,令人不舒服的情况,一些C++风格的奥秘通过绑定泄漏到您的Erlang代码中,例如使用2D图形DC画布和诸如此类的神奇环境创建过程。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4220462

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档