• wxListCtrl 例子 二


    wxListCtrl 事例代码:

    关于list 中添加一个 Report 头,可以给头,类似toobar,可以给其中添加控件;但是添加控件的方式有两种:

    一: 我认为有控件可以放在左中右,用一个参数或 integer 或 tuple 告诉toobar 左面几个,中间几个,剩下的都是右边的
    这只需要一个 Sizer 就可以了,
    这样:

    case Align of
      undefined ->
          %%All controls AlignLeft
      right ->
          %% All contrils AlignRight
      center ->
          %% All controls AlignCenter
      Integer  ->
          %% put the first Integer s of controls AlignLeft , the remaining right
      {Integer, right} ->
          %% put the fitst Integers of controls  AlignCenter, the remaining right
      {Left, Center} ->
          %% put the first Integers of controls AlignLeft, then the Centers of controls AlignCenter, the remaining right
     

    实际上,当前需要用两个Sizer, 需要说明这个是左边第一个,这个是右边第一个,我不明白的是为什么不直接按照顺序来?这样人
    写着也感觉不顺啊

    本例子中有两个wxListCtrl,一个是基本方式添加行和列,一种是用maps 实现按照预先设置的行列位置映射添加数据所在的行和列,

    实现了消息注册,在module 只有一个消息处理 handle_event, 大致实现动态消息处理

    -module(list).
    -include_lib("wx/include/wx.hrl").
    -behaviour(wx_object).
    -export([new/1,
             tbar/2, 
             columns/2, 
             load_data/2]).
    -export([update/1,
             reg_handlers/2, 
             stop/0,]).
    -export([init/1, 
             terminate/2,  
             code_change/3,
             handle_info/2, 
             handle_call/3, 
             handle_cast/2, 
             handle_event/2]).
    
    -define(FIRST_COL, 0).
    -define(SECOND_COL, 1).
    -define(THIRD_COL, 2).
    
    -record(state,
    	{
    	  panel,
    	  config,
        report,
        tbar_items,
        selected_rows = [],
        list_relative_complex,
        event_function_map,
        header_pos,
        columns
    	 }).
    
    -record(col_def, { text ,
                       data_index,
                       align = ?wxLIST_FORMAT_LEFT,
                       sortable = false,
                       width = ?wxLIST_AUTOSIZE,
                       colour = ?wxBLACK 
                     }).
    %%%===================================================================
    %%% API
    %%%===================================================================
    %%--------------------------------------------------------------------
    %% @doc
    %% @spec
    %% @end
    %%-------------------------------------------------------------------- 
    new(Config) ->
        wx:new(),
        start(Config).
    
    %%--------------------------------------------------------------------
    %% @doc
    %% @spec
    %% @end
    %%--------------------------------------------------------------------
    start(Config) ->
        wx_object:start_link(?MODULE, Config, []).
    
    tbar(This, Items) ->
        wx_object:call(This, {tbar, Items}).
    
    update(This) ->
        wx_object:call(This, update).
    
    reg_handlers(This, EventAndHandler) ->
        wx_object:call(This, {reg_handlers, EventAndHandler}).
    
    columns(This, Columns) ->
        wx_object:call(This, {columns, Columns}).
    
    load_data(This, Data) ->
        wx_object:call(This, {load_data, Data}).
    
    stop() ->
        wx_object:call(?MODULE, shutdown).
    %%--------------------------------------------------------------------
    %% @doc
    %% @spec
    %% @end
    %%--------------------------------------------------------------------
    init(Config) ->
            wx:batch(fun() -> do_init(Config) end).
    
    handle_event(#wx{id = Id,  event = Event}, #state{report = ListView}  = State) ->
                 #state{event_function_map = EventFunctionMap, selected_rows = SelectedRows} = State,
        FunctionResult = 
        case Event of
          #wxCommand{type = Type}  ->
              Function = maps:get({Id, Type}, EventFunctionMap, not_matched),
                 case Function of
                    not_matched ->
                        [];
                    Fun ->
                        Fun(SelectedRows),
                        []
                 end;
          #wxList{itemIndex = Item, type = Type} ->
              Function = maps:get({?wxID_ANY, Type}, EventFunctionMap, not_matched),
                 case Function of
                    not_matched ->
                        [];
                    Fun ->
                        Fun(ListView, Item)
                 end;
          _ ->
              []
        end,
        ReSelect =
        case FunctionResult of
          [] ->
              [];
          FunctionResult when is_list(FunctionResult)->
              [FunctionResult | SelectedRows];
          _ ->
              SelectedRows
        end,
        {noreply, State#state{selected_rows = ReSelect}}.
    
    handle_call({columns, Columns}, _From, #state{list_relative_complex = ComplexList} = State) ->
        HeaderPos = set_headers(ComplexList, Columns),
        {reply, ok,  State#state{columns = Columns, header_pos = HeaderPos}};
    
    handle_call({load_data, Data}, _From, State) ->
        #state{header_pos = HeaderPos, list_relative_complex = ComplexList} = State,
        HeaderPosMap = insert_rows_to_report(ComplexList, HeaderPos, Data),
        {reply, ok, State#state{header_pos = HeaderPosMap}};        
    
    handle_call({reg_handlers, EventAndHandler}, _From, State) ->
        EventFunctionMap = 
        lists:foldl(fun({Event, Fun},  RegMap) ->
                        maps:put(Event, Fun, RegMap)
                    end, #{}, EventAndHandler),
        {reply, ok, State#state{event_function_map = EventFunctionMap}};
    
    handle_call({tbar, TbarItems}, _From, State) ->
        [First | _Remaining] = TbarItems,
        wxButton:connect(First, command_button_clicked),
        {reply, ok, State#state{tbar_items = TbarItems}}; 
    
    handle_call(update, _From, #state{panel = Panel} = State) ->
        #state{tbar_items = TbarItems,  report = ListView,
               list_relative_complex = ComplexList} = State,
        Tbar = 
        case  TbarItems of
            TbarItems  when is_list(TbarItems), length(TbarItems) =:= 0 ->
                wxFlexGridSizer:new(0, 0, 0, 0);
            TbarItems when is_list(TbarItems) ->
                create_tbar(Panel, TbarItems);
            _ ->
                wxFlexGridSizer:new(0, 0, 0, 0)
        end,
        MainSizer = wxBoxSizer:new(?wxVERTICAL),
        wxSizer:add(MainSizer, Tbar,  [{flag, ?wxEXPAND}]),
        ReportSizer = wxBoxSizer:new(?wxHORIZONTAL),
        wxSizer:add(ReportSizer, ListView, [{flag, ?wxEXPAND}, {proportion, 1}]),
        wxSizer:add(ReportSizer, ComplexList, [{flag, ?wxEXPAND}, {proportion, 1}]),
        wxSizer:add(MainSizer, ReportSizer, [{flag, ?wxEXPAND}, {proportion, 1}]),
        wxPanel:setSizer(Panel, MainSizer),
        wxSizer:fit(MainSizer, Panel), 
        {reply, ok, State}; 
    
    handle_call(shutdown, _From, State=#state{panel=Panel}) ->
        wxPanel:destroy(Panel),
        {stop, normal, ok, State};
    
    handle_call(Msg, _From, State) ->
        io:format("Got Call ~p
    ",[Msg]),
        {reply,ok,State}.
    
    handle_cast(Msg, State) ->
        io:format("Got cast ~p~n",[Msg]),
        {noreply,State}.
    
    handle_info(Msg, State) ->
        io:format("Got Info ~p~n",[Msg]),
        {noreply,State}.
    
    code_change(_, _, State) ->
        {stop, ignore, State}.
    
    terminate(_Reason, _State) ->
        ok.
    
    %%--------------------------------------------------------------------
    %% @doc
    %% @spec
    %% @end
    %%--------------------------------------------------------------------
    do_init(Config) ->
        Parent = proplists:get_value(parent, Config),
        Panel = wxPanel:new(Parent, []),
        %% Setup sizers
        ListCtrl = create_list_ctrl(Panel, [{style, ?wxLC_REPORT }]),
        ComplexList = wxListCtrl:new(Panel, [{style, ?wxLC_REPORT }]),
        wxListCtrl:connect(ListCtrl, command_list_item_selected, []),
        {Panel, #state{panel = Panel, config = Config, report = ListCtrl,
                       list_relative_complex = ComplexList}}.
    
    %% 简单方式插入数据
    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, "First "++Name),
    		    wxListCtrl:setItem(ListCtrl, Int, ?SECOND_COL, "Second "++Name),
    		    wxListCtrl:setItem(ListCtrl, Int, ?THIRD_COL, "Third "++Name)
    	  end,
        wx:foreach(Fun, lists:seq(0,20)),
        ListCtrl.
    
    %% 创建Report 头
    create_tbar(Panel, Items) ->
        ItemNumber = length(lists:flatten(Items)),
        LeftSizer  = wxFlexGridSizer:new(1, ItemNumber, 0, 0),  
        RightSizer = wxFlexGridSizer:new(1, ItemNumber, 0, 0), 
        [insert_control_to_bar(Item, Panel, LeftSizer, RightSizer) || Item <- Items],
        MainSizer = wxBoxSizer:new(?wxHORIZONTAL),
        wxSizer:add(MainSizer, LeftSizer),
        wxSizer:add(MainSizer, 60 ,20, [{proportion, 1}, {flag, ?wxEXPAND}]),
        wxSizer:add(MainSizer, RightSizer),
        MainSizer.
    
    %% 给Report 头tbar插入控件
    insert_control_to_bar(Item, NewParent, LeftSizer, RightSizer) ->
        case Item of
          {Control, left} ->
              wxWindow:reparent(Control, NewParent), 
              wxSizer:add(LeftSizer, Control, [{proportion, 0}, {flag, ?wxALIGN_CENTER}]);
          {Control, right} ->
              wxWindow:reparent(Control, NewParent), 
              wxSizer:add(RightSizer, Control, [{proportion, 0}, {flag, ?wxALIGN_CENTER}]);
          Item ->
              wxWindow:reparent(Item, NewParent), 
              wxSizer:add(LeftSizer, Item, [{proportion, 0}, {flag, ?wxALIGN_CENTER}])
        end.
    
    %% 设置Report 头
    set_headers(Report, Columns) ->
      [_LastIndex , HeaderPosMap] = 
            lists:foldl(
              fun(Column, [Index, HeaderPos]) ->
                      #col_def{text = Text, data_index = DataIndex, sortable = Sortable, 
                               align = Align, width = Width, colour = Color} = Column,
                      % validate DataIndex, it should exist!
                      HeaderCol = create_one_column_header(Align, Width, Text),
                      wxListCtrl:insertColumn(Report, Index, HeaderCol),
                      [Index + 1, maps:put(DataIndex, Index, HeaderPos)]    
              end, [0, #{}], Columns),
        HeaderPosMap.
    
    %% 
    create_one_column_header(Align, Width, Text) ->
        HeaderCol = wxListItem:new(),
        wxListItem:setAlign(HeaderCol, Align),
        wxListItem:setWidth(HeaderCol, Width),
        wxListItem:setText(HeaderCol, Text),
         %wxListItem:setTextColour(Item, Color),
        HeaderCol.
    
    insert_rows_to_report(ListView, undefined, Data) ->
        [FirstRow | _RemainingRows] = Data,
        case FirstRow of
            {struct, RowData} when is_list(RowData)->
                create_header_and_insert_rows(ListView, RowData, Data);
            {obj, RowData} when is_list(RowData)->
                create_header_and_insert_rows(ListView, RowData, Data);
            Row when is_list(Row)  ->
                create_header_and_insert_rows(ListView, Row, Data);
            _Row  ->
                ok
        end;
    
    insert_rows_to_report(ListView, HeaderPos, Data) ->
        % LastRowNo = 0, % TODO: should append to
        LastRowNo =  wxListCtrl:getItemCount(ListView),
        lists:foldl(
          fun(Row, [RIndex]) ->
                  % fill up cells
                case Row of 
                   {struct, RowData} when is_list(RowData)->
                           insert_a_row_to_report(ListView, HeaderPos, RIndex, RowData),
                           [RIndex + 1];
                   {obj, RowData} when is_list(RowData)->
                           insert_a_row_to_report(ListView, HeaderPos, RIndex, RowData),
                           [RIndex + 1];
                   Row when is_list(Row)  ->
                           insert_a_row_to_report(ListView, HeaderPos, RIndex, Row),
                           [RIndex + 1];
                   _Row  ->
                       [RIndex]
                end
          end, [LastRowNo], Data),
        HeaderPos.
    
    create_header_and_insert_rows(ListView, FirstRowDataObject, Data) ->
        {ListViewWidth, _ListViewHeight} = wxListCtrl:getSize(ListView),
        ColumnWidth = ListViewWidth div length(FirstRowDataObject),
        [_LastIndex , HeaderPosMap] = 
        lists:foldl(
              fun({DataIndex, _DataObject}, [Index, HeaderPos]) ->
                      HeaderCol = create_column_header(?wxLIST_FORMAT_LEFT, ColumnWidth, 
                                                      any_to_list(DataIndex)),
                      wxListCtrl:insertColumn(ListView, Index, HeaderCol),
                      [Index + 1, maps:put(any_to_atom(DataIndex), Index, HeaderPos)]    
              end, [0, #{}], FirstRowDataObject),
        insert_rows_to_report(ListView, HeaderPosMap, Data).
    
    insert_a_row_to_report(ListView, HeaderPos, RIndex, RowDataObject) ->
      wxListCtrl:insertItem(ListView, RIndex, ""),
      lists:foldl(
                  fun({DataIndex, Val} = _Cell, _Bool) ->
                      case maps:get(any_to_atom(DataIndex), HeaderPos, -1) of
                          -1      ->  
                              false;
                          CIndex ->
                              Cell = wxListItem:new(),
                              wxListItem:setId(Cell, RIndex),
                              wxListItem:setColumn(Cell, CIndex),
                              wxListItem:setText(Cell, any_to_list(Val)),
                              wxListCtrl:setItem(ListView, Cell)
                      end
                  end, true, RowDataObject).
    
    %%--------------------------------------------------------------------
    %% @doc
    %% 类型转化
    %% @spec
    %% @end
    %%--------------------------------------------------------------------
    any_to_list(undefined) ->
        "";
    any_to_list(List) when is_list(List) ->
        List;
    any_to_list(Bin) when is_binary(Bin) ->
        case unicode:characters_to_binary(Bin, utf8, utf8) of
            Bin -> unicode:characters_to_list(Bin);
            _ -> binary_to_list(Bin)
        end;
    any_to_list(Atom) when is_atom(Atom) ->
        atom_to_list(Atom);
    any_to_list(Number) when is_integer(Number) ->
        integer_to_list(Number);
    any_to_list(Number) when is_float(Number) ->
        float_to_list(Number, [{decimals, 2}]);
    any_to_list(_) ->
        throw(badarg).
    
    any_to_atom(Atom) when is_atom(Atom) ->
        Atom;
    any_to_atom(List) when is_list(List) ->
        list_to_atom(List);
    any_to_atom(Bin) when is_binary(Bin) ->
        list_to_atom(any_to_list(Bin));
    any_to_atom(_) ->
        throw(badarg).
    

    wxListCtrl 测试代码

    -module(testlist).
    
    -behaviour(wx_object).
    
    -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]).
    -export([button_one_clicked/1, 
             report_items_selected/2]).
    
    -include_lib("wx/include/wx.hrl").
    -define(APPEND, 1).
    -define(CLEAR, 2).
    -define(INSERTIONPOSITION, 3).
    -define(BREAKLINE, 4).
    -define(TESTSTRING, 5).
    -record(state,
      {
          frame,
          parent,
          config
       }).
    
    -record(col_def, { text ,
                       data_index,
                       align = ?wxLIST_FORMAT_LEFT,
                       sortable = false,
                       width = ?wxLIST_AUTOSIZE,
                       colour = ?wxBLACK 
                     }).
    %%%===================================================================
    %%% API
    %%%===================================================================
    
    
    %%--------------------------------------------------------------------
    %% @doc
    %% @spec
    %% @end
    %% wxclient_position_select:new(Config)
    %%--------------------------------------------------------------------
    new() ->
        _WX = wx:new(),
        Size = {size, {800, 600}},
        Pos = {pos, {200, 300}},
        Style = {style, ?wxDEFAULT_FRAME_STYLE},
        NOptions = [Pos, Size, Style],
        Frame = makeFrame("wxTextCtrl Text", NOptions),
        new([{parent, Frame}]).
    
    new(Config) ->
        start(Config).
    
    start(Config) ->
        wx_object:start_link({local, ?MODULE}, ?MODULE, Config, []).
    
    %%--------------------------------------------------------------------
    %% @doc
    %% @spec
    %% @end
    %% wxclient_position_select:destroy()
    %%--------------------------------------------------------------------
    destroy() ->
        wx_object:call(?MODULE, shutdown).
    
    show() ->
        wx_object:call(?MODULE, show).
    
    init(Config) ->
        wx:batch(fun() -> do_init(Config) end).
    
    handle_info(Info, State) ->
        io:format("Got Info ~p
    ",[Info]),
        {noreply, State}.
    
    handle_call(CallMsg, _From, State) ->
        io:format("Got Call ~p
    ",[CallMsg]),
        {reply, ok, State}.
    
    handle_cast(CastMsg, State) ->
        io:format("Got cast ~p~n",[CastMsg]),
        {noreply,State}.
    
    code_change(_,  _, State) ->
        {stop, ignore, State}.
    
    terminate(_Reason, _State) ->
        ok.
    
    handle_event(#wx{},  State) ->
        {noreply, State}.
    
    %%%===================================================================
    %%% API
    %%%===================================================================
    do_init(Config) ->
        %% define parent Panel
        Parent = proplists:get_value(parent, Config),
        Panel = wxPanel:new(Parent, []),  
        Report = list:new([{parent, Panel}]),
        ButtonOne   = wxButton:new(Panel, 15, [{label, "Button1"}, {size, {80, 25}}]),
        ButtonTwo   = wxButton:new(Panel, 16, [{label, "Button2"}, {size, {80, 25}}]),
        ButtonThree = wxButton:new(Panel, 17, [{label, "Button3"}, {size, {80, 25}}]),
        ButtonFour  = wxButton:new(Panel, 18, [{label, "Button4"}, {size, {80, 25}}]),
        ButtonFive  = wxButton:new(Panel, 19, [{label, "Button5"}, {size, {80, 25}}]),
        TbarItems = [ButtonOne, {ButtonTwo, left}, {ButtonThree, right},
                     {ButtonFour, left}, {ButtonFive, right}],
        list:tbar(Report, TbarItems),
        list:update(Report),
        EventButtonClicked = {15, command_button_clicked},
        EventReportSelected = {?wxID_ANY, command_list_item_selected},
        list:reg_handlers(Report, 
              [{EventButtonClicked, fun ?MODULE:button_one_clicked/1},
               {EventReportSelected, fun ?MODULE:report_items_selected/2}]),
    
         Data =[
        [{<<"student_id">>,100010},{<<"department">>,<<"math">>},{<<"name">>,<<"nancy">>},
         {<<"ppp">>, <<"ddd">>}],
        [{<<"student_id">>,100005},{<<"department">>,<<"computer">>},{<<"name">>,<<"shank">>}, 
         {<<"ppp">>, <<"bbb">>}],
        [{<<"student_id">>,100009},{<<"department">>,<<"georraphy">>},{<<"name">>,<<"kobe">>}, 
         {<<"ppp">>, <<"1235">>}]],
        Columns = 
         [#col_def{text = "第1列", data_index = student_id, width = 100,         sortable = false, 
                   align = ?wxLIST_FORMAT_RIGHT },
          #col_def{text = "第2列", data_index = department,  width = 100,   sortable = false, 
                   align = ?wxLIST_FORMAT_RIGHT },
          #col_def{text = "第3列", data_index = name, width = 100,sortable = false,
                   align = ?wxLIST_FORMAT_RIGHT }],
        list:columns(Report, Columns),
        list:load_data(Report, Data),
        list:load_data(Report, Data),          
        MainSizer = wxBoxSizer:new(?wxVERTICAL),
        wxSizer:add(MainSizer, Report, [{flag, ?wxEXPAND}, {proportion, 1}]),
        wxPanel:setSizer(Panel, MainSizer),
        wxFrame:show(Parent),
        {Panel, #state{frame = Parent, parent = Panel}}.
    
    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.
    
    report_items_selected(Report, Item) ->
        ColumnNumber = wxListCtrl:getColumnCount(Report),
        Cell = wxListItem:new(),
        wxListItem:setId(Cell, Item),
        lists:foldl(fun(Column, Result) ->
                       wxListItem:setColumn(Cell, ColumnNumber - 1 - Column),
                       wxListCtrl:getItem(Report, Cell), 
                       ColumnText = wxListItem:getText(Cell) ,
                       [ColumnText | Result]
                    end, [], lists:seq(0, ColumnNumber - 1)).
    
    button_one_clicked(Result) -> 
        io:format("Selected Items is ~p~n", [Result]).
    
  • 相关阅读:
    Redis源码分析(十二)--- redis-check-dump本地数据库检测
    Redis源码分析(十二)--- redis-check-dump本地数据库检测
    Redis源码分析(十二)--- redis-check-dump本地数据库检测
    Redis源码分析(十三)--- redis-benchmark性能测试
    Redis源码分析(十四)--- rdb.c本地数据库操作
    Redis源码分析(十三)--- redis-benchmark性能测试
    Redis源码分析(十四)--- rdb.c本地数据库操作
    Redis源码分析(十四)--- rdb.c本地数据库操作
    去除移动端点击事件出现的背景框 tap-highlight-color
    php源码分析之PHPAPI宏的作用
  • 原文地址:https://www.cnblogs.com/ShankYan/p/4148755.html
Copyright © 2020-2023  润新知