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]).
原文地址:https://www.cnblogs.com/ShankYan/p/4148755.html