erlang 中wxListCtrl的 使用总结


-module(list_ctrl).
-behaviour(wx_object).
%% wx_object callbacks
-export([new/0, start/1, destroy/0]).
-export([init/1,
         terminate/2,
         code_change/3,
         handle_info/2,
         handle_call/3,
         handle_cast/2,
         handle_event/2]).

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

-define(FIRST_COL,  0).
-define(SECOND_COL, 1).
-define(THIRD_COL,  2).
-record(state, {frame,
                panel,
                list
                }).

%%%===================================================================
%%% API
%%%===================================================================

%%--------------------------------------------------------------------
%% @doc
%% @spec
%% @end
%%--------------------------------------------------------------------
new() ->
    _WX = wx:new(),
    Size = {size, {400, 600}},
    Pos = {pos, {200, 300}},
    Style = {style, ?wxDEFAULT_FRAME_STYLE bor ?wxMAXIMIZE},
    NOptions = [Pos, Size, Style],
    Frame = makeFrame("wxListCtrl 总结", NOptions),
    start([{parent, Frame}]).

start(Config) ->
    wx_object:start_link({local, ?MODULE}, ?MODULE, Config, []).

destroy() ->
    wx_object:call(?MODULE, shutdown).

%%--------------------------------------------------------------------
%% @doc
%% @spec
%% @end
%%--------------------------------------------------------------------
init(Config) ->
    wx:batch(fun() -> do_init(Config) end).   

handle_info(_Msg, State) ->
    {noreply, State}.

handle_call(shutdown, _From, #state{panel = Panel} = State) ->
    wxFrame:destroy(Panel),
    {stop, normal, ok, State};

handle_call(_Msg, _From, State) ->
    {reply, {error, ?MODULE},State}.

handle_cast(_Msg, State) ->
    {noreply,State}.

%%单击选中某一行,默认情况下可以多选
handle_event(#wx{event = #wxList{itemIndex = Item, type = command_list_item_selected}}, State) ->
    io:format("Item ~p selected.\n",[Item]),
    {noreply, State};

%%windows下单击第二次是编辑状态,但Linux下是dselect,而且即使有图标window下是可以编辑的
handle_event(#wx{event = #wxList{itemIndex = Item, type = command_list_item_deselected}}, State) ->
    io:format("Item ~p command_list_item_deselected.\n",[Item]),
    {noreply, State};

%%双击左键
handle_event(#wx{event = #wxList{itemIndex = Item, type = command_list_item_activated}}, State) ->
    io:format("Item ~p command_list_item_activated.\n",[Item]),
    {noreply, State};

%%单击右键,事件处理首先获取编辑前的item的label
handle_event(#wx{event = #wxList{itemIndex = Item, type = command_list_item_right_click}}, 
             #state{list = ListCtrl2} = State) ->
    io:format("Item ~p, Text = ~p, command_list_item_right_click.\n",
               [Item, wxListCtrl:getItemText(ListCtrl2, Item)]),
    {noreply, State};

%%开始用左键拖拽item
handle_event(#wx{event = #wxList{itemIndex = Item, type = command_list_begin_drag}}, State) ->
    io:format("Item ~p command_list_begin_drag.\n",[Item]),
    {noreply, State};

%%开始用右键拖拽item,事件处理:删除拖拽的item
handle_event(#wx{event = #wxList{itemIndex = Item, type = command_list_begin_rdrag}}, 
             #state{list = ListCtrl2} = State) ->
    io:format("Item ~p command_list_begin_rrrrrdrag.\n",[Item]),
    wxListCtrl:deleteItem(ListCtrl2, Item),
    {noreply, State};

%%删除item
handle_event(#wx{event = #wxList{itemIndex = Item, type = command_list_delete_item}}, State) ->
    io:format("Item ~p command_list_delete_item.\n",[Item]),
    {noreply, State};

%%开始编辑某个item的labl
handle_event(#wx{event = #wxList{itemIndex = Item, type = command_list_begin_label_edit}}, State) ->
    io:format("Item ~p command_list_begin_label_edit.\n",[Item]),
    {noreply, State};

%%item的label编辑完成,点击Enter之后
handle_event(#wx{event = #wxList{itemIndex = Item, type = command_list_end_label_edit}}, 
             #state{list = ListCtrl2} = State) ->
    io:format("the Item data now is ~p~n", [wxListCtrl:getItemData(ListCtrl2, Item)]),
    io:format("Item ~p command_list_end_label_edit.\n",[Item]),
    {noreply, State};

%%插入item
handle_event(#wx{event = #wxList{itemIndex = Item, type = command_list_insert_item}}, 
             #state{list = ListCtrl2} = State) ->
    io:format("Item ~p command_list_insert_item.\n",[Item]),
    {noreply, State};

%%左键选择某一列
handle_event(#wx{event = #wxList{itemIndex = Item, col = Col, type = command_list_col_click}}, State) ->
    io:format("Item ~p, Col = ~p command_list_col_click.\n",[Item, Col]),
    {noreply, State};

%%右键选择某一列
handle_event(#wx{event = #wxList{itemIndex = Item, type = command_list_col_right_click}}, State) ->
    io:format("Item ~p command_list_col_right_click.\n",[Item]),
    {noreply, State};

%%在list中按下按键,并捕获按键
handle_event(#wx{event = #wxList{itemIndex = Item, code = Code, type = command_list_key_down}}, 
             #state{list = ListCtrl2} = State) ->
    io:format("Item ~p ,Text = ~p, Code = ~p.\n", [Item, Code, wxListCtrl:getItemText(ListCtrl2, Item)]),
    case Code of
        %%重新按照item关联的数据排序
        $a ->
            io:format("begin resort_accord_to_integer_item~n"),
            resort_accord_to_integer_item(ListCtrl2);
        $d ->
            io:format("delete allItems~n"),
            %%删除所有的item
            % wxListCtrl:deleteAllItems(ListCtrl2);
            % wxListCtrl:deleteColumn(ListCtrl2, 1);
            %%删除item
            % wxListCtrl:deleteItem (ListCtrl2, 1);
            %%给第五行item重新设置label
            wxListCtrl:clearAll(ListCtrl2),
            wxListCtrl:insertColumn(ListCtrl2, ?FIRST_COL, "First New", []),
            wxListCtrl:insertColumn(ListCtrl2, ?SECOND_COL, "Second New", []),
            wxListCtrl:insertColumn(ListCtrl2, ?THIRD_COL, "Third New", []);
        $i  ->
            io:format("setLabel"),
            wxListCtrl:setItemText(ListCtrl2, 5, "setItemText");
        %%给所选择行,第一列设置关联图标列表中第二个图标
        $s  ->
            io:format("setItemColumnImage"),
            wxListCtrl:setItemColumnImage(ListCtrl2, Item, 1, 2);
        %%新加入一行和一列
        $n  ->
            ListItem = wxListItem:new(),
            wxListItem:setId(ListItem, wxListCtrl:getItemCount(ListCtrl2)),
            wxListItem:setBackgroundColour(ListItem, {0, 0, 0, 255}),
            wxListItem:setText(ListItem, "wxListItem"),
            wxListCtrl:insertItem (ListCtrl2, ListItem),

            ListColumn = wxListItem:new(),
            wxListItem:setText (ListColumn, "wxListItem:setText"), 
            io:format("getColumnCount = ~p~n", [wxListCtrl:getColumnCount(ListCtrl2)]),
            wxListCtrl:insertColumn(ListCtrl2, wxListCtrl:getColumnCount(ListCtrl2), "NewColumn", []),
            wxListCtrl:setColumn(ListCtrl2, wxListCtrl:getColumnCount(ListCtrl2), ListColumn);
        %%获取每一页中item个数,以及给list设置为黑色
        $c  ->
            Re = wxListCtrl:getCountPerPage(ListCtrl2),
            io:format("getCountPerPage = ~p~n", [Re]),
            wxListCtrl:setBackgroundColour(ListCtrl2, {0,0,0,255});
        %%从第三个item开始查找label为“4”的item
        $f  ->
            Result = wxListCtrl:findItem(ListCtrl2, 3, "4", [{partial, true}]),
            io:format("find Result = ~p~n", [Result]);
        %5设置第三个item可以编辑
        $e  ->
            io:format("Editable~n"),
            wxListCtrl:editLabel(ListCtrl2, 3);
        %%获取item空间大小,并设置第一个item的label为蓝色
        $p  ->
            io:format("Rect = ~p~n", [wxListCtrl:getItemRect(ListCtrl2, 1)]),
            io:format("getColumnWidth = ~p~n", [wxListCtrl:getColumnWidth(ListCtrl2, 1)]),
            io:format("getColumnCount = ~p~n", [wxListCtrl:getColumnCount(ListCtrl2)]),
            io:format("Spacing = ~p~n", [wxListCtrl:getItemSpacing(ListCtrl2)]),
            wxListCtrl:setItemTextColour(ListCtrl2, 1, ?wxBLUE),
            io:format("position = ~p~n", [wxListCtrl:getItemPosition(ListCtrl2, 1)]);
        _ ->
            ok
    end,
    {noreply, State};

handle_event(#wx{}, #state{} = State) ->
    {noreply, State}.

code_change(_, _, State) ->
    {stop, ignore, State}.

terminate(_Reason, _State) ->
    ok.
%%%===================================================================
%%% Internal functions
%%%===================================================================

do_init(Config) ->
    Parent = proplists:get_value(parent, Config),
    Panel = wxPanel:new(Parent, []),
    MainSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
             [{label, "wxListCtrl "}]),
    Notebook = wxNotebook:new(Panel, 1, [{style, ?wxBK_DEFAULT}]),
    %% style 1: wxLC_LIST风格的wxListCtrl,
    ListCtrl1 = wxListCtrl:new(Notebook, [{style, ?wxLC_LIST bor ?wxLC_EDIT_LABELS}]),
    [wxListCtrl:insertItem(ListCtrl1, Int, "Item "++integer_to_list(Int)) ||
                                                    Int <- lists:seq(0,50)],
    %% style 2: 行和列之间有间隔线的report view
    ListCtrl2 = create_list_ctrl(Notebook, [{style, ?wxLC_REPORT bor ?wxLC_HRULES                 
                                                    bor ?wxLC_EDIT_LABELS}]),
    insert_image(ListCtrl2),
    %% style 3: small icon view 是图标和Lable 纵向排列的
    ListCtrl3 = wxListCtrl:new(Notebook, [{style, ?wxLC_SMALL_ICON}]),
    [wxListCtrl:insertItem(ListCtrl3, Int, "Item "++integer_to_list(Int)) ||
                                                    Int <- lists:seq(0,50)],
    insert_image(ListCtrl3)  ,  
    wxListCtrl:setTextColour(ListCtrl3, ?wxBLUE),                                  
    
    %% style 4 :virtual report(with millions of items without consuming much memory)
    ListCtrlOpts = virtual_control_options(),
    ListCtrl4 = wxListCtrl:new(Notebook, ListCtrlOpts),
    %% actual setIamgeList is equal to assignImageList
    wxListCtrl:setImageList(ListCtrl4, get_image_list(), ?wxIMAGE_LIST_SMALL),
    wxListCtrl:insertColumn(ListCtrl4, 0, "Column 1"),
    wxListCtrl:insertColumn(ListCtrl4, 1, "Column 2"),
    wxListCtrl:setColumnWidth(ListCtrl4, 0, 200),
    wxListCtrl:setColumnWidth(ListCtrl4, 1, 200),
    wxListCtrl:setItemCount(ListCtrl4, 1000000),

    wxListCtrl:connect(ListCtrl2, command_list_item_selected, []),
    wxListCtrl:connect(ListCtrl2, command_list_item_deselected, []),
    wxListCtrl:connect(ListCtrl2, command_list_item_right_click, []),
    wxListCtrl:connect(ListCtrl2, command_list_begin_drag, []),
    wxListCtrl:connect(ListCtrl2, command_list_begin_rdrag, []),
    wxListCtrl:connect(ListCtrl2, command_list_begin_label_edit, []),
    wxListCtrl:connect(ListCtrl2, command_list_end_label_edit, []),
    wxListCtrl:connect(ListCtrl2, command_list_delete_item, []),
    wxListCtrl:connect(ListCtrl2, command_list_key_down, []),
    wxListCtrl:connect(ListCtrl2, command_list_col_click, []),
    wxListCtrl:connect(ListCtrl2, command_list_col_right_click, []),
    wxListCtrl:connect(ListCtrl2, command_list_insert_item, []),
    wxListCtrl:connect(ListCtrl2, command_list_item_activated, []),
    
    wxNotebook:addPage(Notebook, ListCtrl2, "normal Report", []),
    wxNotebook:addPage(Notebook, ListCtrl1, "List", []), 
    wxNotebook:addPage(Notebook, ListCtrl3, "Small icon view", []),
    wxNotebook:addPage(Notebook, ListCtrl4, "Virtual Report", []),
    %% Add to sizers  
    wxSizer:add(MainSizer, Notebook, [{proportion, 1},
              {flag, ?wxEXPAND}]),
    wxPanel:setSizer(Panel, MainSizer),
    wxFrame:show(Parent),
    {Panel, #state{panel = Panel, list = ListCtrl2}}.

create_list_ctrl(Win, Options) ->
    ListCtrl = wxListCtrl:new(Win, Options),
    wxListCtrl:insertColumn(ListCtrl, ?FIRST_COL, "First Col", []),
    wxListCtrl:insertColumn(ListCtrl, ?SECOND_COL, "Second Col", []),
    wxListCtrl:insertColumn(ListCtrl, ?THIRD_COL, "Third Col", []),
    Fun =
        fun(Int) ->
            Name = integer_to_list(Int),
            wxListCtrl:insertItem(ListCtrl, Int, ""),
            wxListCtrl:setItem(ListCtrl, Int, ?FIRST_COL, Name),
            wxListCtrl:setItem(ListCtrl, Int, ?SECOND_COL, "Second "++Name),
            wxListCtrl:setItem(ListCtrl, Int, ?THIRD_COL, "Third "++Name),
            wxListCtrl:setItemData(ListCtrl, Int, Int + 10)
        end,
    wx:foreach(Fun, lists:seq(0, 50)),
    ListCtrl.


get_image_list() ->
    ImageList = wxImageList:new(16,16),
    wxImageList:add(ImageList, wxArtProvider:getBitmap("wxART_COPY", [{size, {16,16}}])),
    wxImageList:add(ImageList, wxArtProvider:getBitmap("wxART_MISSING_IMAGE", [{size, {16,16}}])),
    wxImageList:add(ImageList, wxArtProvider:getBitmap("wxART_QUESTION", [{size, {16,16}}])),
    wxImageList:add(ImageList, wxArtProvider:getBitmap("wxART_WARNING", [{size, {16,16}}])),
    ImageList.

insert_image(ListCtrl) ->
    ImageList = get_image_list(),
    wxListCtrl:assignImageList(ListCtrl, ImageList, ?wxIMAGE_LIST_SMALL),
    Fun =
        fun(Item) ->
            case Item rem 4 of
                0 ->
                    wxListCtrl:setItemBackgroundColour(ListCtrl, Item, {240,240,240,255}),
                    wxListCtrl:setItemImage(ListCtrl, Item, 0);
                1 -> 
                    wxListCtrl:setItemImage(ListCtrl, Item, 1);
                2 ->
                    wxListCtrl:setItemImage(ListCtrl, Item, 2),
                    wxListCtrl:setItemBackgroundColour(ListCtrl, Item, {240,240,240,255});
                _ -> 
                    wxListCtrl:setItemImage(ListCtrl, Item, 3)
            end
        end,
    wx:foreach(Fun, lists:seq(0, wxListCtrl:getItemCount(ListCtrl) -1)),
    ListCtrl.

%%--------------------------------------------------------------------
%% @doc
%% @spec
%% @end
%%--------------------------------------------------------------------
resort_accord_to_integer_item(ListCtrl)  ->
    Fun =
        fun(Int) ->
            Id = list_to_integer(wxListCtrl:getItemText(ListCtrl, Int)),
            io:format("Id = ~p~n", [Id]),
            wxListCtrl:setItemData(ListCtrl, Int, 100 - Id)
        end,
    wx:foreach(Fun, lists:seq(0, wxListCtrl:getItemCount(ListCtrl) -1)),
    wxListCtrl:sortItems(ListCtrl, fun(Item1, Item2) ->
                                      case Item1 - Item2 < 0 of
                                        false  ->
                                            1;
                                        true   ->
                                            -1
                                      end 
                                    end).

virtual_control_options()  ->
    ImageAttr = wxListItemAttr:new(),
    wxListItemAttr:setTextColour(ImageAttr, {190, 25, 25}),
    ListCtrlOpts = [{style, ?wxLC_REPORT bor ?wxLC_VIRTUAL },
               {onGetItemText, fun(_This, Item, 0) ->
                                    "Row " ++ integer_to_list(Item);
                                  (_, Item, 1) when Item rem 5 == 0 ->
                                    "Column 2";
                                  (_, _, _) -> 
                                    ""
                                end},
                {onGetItemAttr, fun(_This, Item) when Item rem 3 == 0 ->
                                    ImageAttr;
                                   (_This, _Item)  ->
                                        wx:typeCast(wx:null(), wxListItemAttr)
                                end},
                {onGetItemColumnImage, fun(_This, Item, 1) ->
                                            Item rem 4;
                                          (_, _, _) ->
                                            -1
                                        end}
               ],
    ListCtrlOpts.



makeFrame(Title, Options) ->
    Frame = wxFrame:new(wx:null(), ?wxID_ANY, Title, Options),
    MenuSet  = wxMenu:new(),
    MenuHelp = wxMenu:new(),
    wxMenu:append(MenuHelp, 1, "关于..."),
    MenuBar = wxMenuBar:new(),
    wxMenuBar:append(MenuBar, MenuSet, "设置"),
    wxMenuBar:append(MenuBar, MenuHelp, "帮助"),
    wxFrame:setMenuBar(Frame, MenuBar),
    wxFrame:createStatusBar(Frame),
    wxFrame:setStatusText(Frame,"Erlang wxListCtrl"),
    wxFrame:connect(Frame, command_menu_selected),
    Frame.

获取某一行某一列的cell数据方法(因为在wxErlang 中获取某一列的参数默认是0, 不能直接获取任意一行一列的Cell数据):

    Cell = wxListItem:new(),
    wxListItem:setId(Cell, Index),
    wxListItem:setColumn(Cell, Column),
    wxListItem:setMask(Cell, ?wxLIST_MASK_TEXT),
    wxListCtrl:getItem(ListView, Cell),
    N = wxListItem:getText(Cell),
posted @ 2014-11-24 23:35  ShankYan  阅读(1259)  评论(0编辑  收藏  举报