Skip to main content

Command Palette

Search for a command to run...

多列wxListCtrl使用技巧

Updated
2 min read

以官方Wiki的minimal example为例:

// Example uses fictive class "Item" and fictive getters to access them. Adapt for your needs

class MyFrame : public wxFrame
{
    wxListCtrl* m_item_list;

public:
    MyFrame() : wxFrame(NULL, wxID_ANY,  wxT("Hello wxWidgets"), wxPoint(50,50), wxSize(800,600))
    {
        wxPanel* mainPane = new wxPanel(this);
        wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);

        m_item_list = new wxListCtrl(mainPane, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT);

        // Add first column       
        wxListItem col0;
        col0.SetId(0);
        col0.SetText( _("Foo") );
        col0.SetWidth(50);
        m_item_list->InsertColumn(0, col0);

        // Add second column
        wxListItem col1;
        col1.SetId(1);
        col1.SetText( _("Name") );
        m_item_list->InsertColumn(1, col1);

        // Add third column     
        wxListItem col2;
        col2.SetId(2);
        col2.SetText( _("Comments") );
        m_item_list->InsertColumn(2, col2);


        const int item_amount = getItemAmount();
        for (int n=0; n<item_amount; n++)
        {
            Item* curritem = getItem(n);

            wxListItem item;
            item.SetId(n);
            item.SetText( curritem->getName() );

            m_item_list->InsertItem( item );

            // set value in first column
            if (!curritem->isFoo())
            {
                m_item_list->SetItem(n, 0, wxT("Foo"));
            }
            else
            {
                m_item_list->SetItem(n, 0, wxT("Bar"));
            }

            // set value in second column
            m_item_list->SetItem(n, 1, curritem->getName());

            // set value in third column
            m_item_list->SetItem(n, 2, curritem->getDescription());

        }

        sizer->Add(m_item_list,1, wxEXPAND | wxALL, 10);
        mainPane->SetSizer(sizer);
    }
};

class MyApp: public wxApp
{
    wxFrame* m_frame;
public:

    bool OnInit()
    {
        m_frame = new MyFrame();
        m_frame->Show();
        return true;
    } 

};

IMPLEMENT_APP(MyApp)

由于官方的API文档描述的比较简单,整理一下使用时的注意事项:

  • 要使用带表头的多列List,初始化时,需有wxLC_REPORT的flag(注意不同flag会有冲突)

  • 使用ClearAll清除表格时,表头(Columns)也会一起被清除,需要重新添加

  • 添加表头有两种方式:

  1. AppendColumn,简单方便

  2. 构造一个wxListItem后,再InsertColumn(官方Minimal Example的方式)

  • 添加数据的方式有点奇怪,需分为两步:
  1. 先获取到索引(可用GetItemCount方法取当前Item的数量作为index),再使用InsertItem插入一个Item,这个方法会返回新Item的index,作为下一步使用

  2. 插入Item后,使用SetItem(index,column,label,imageIndex=-1)方法,给刚才的Item设置各列显示的数据,如需设置自定义数据、图片、字体等高级功能,可用wxListItem的重载版本

新增Item的示例代码如下:

int TrayThem::MainWidget::cbReloadPrograms(void *argument, int argc,
                                           char **argv, char **azColName) {
  if (argument == nullptr) {
    return -1;
  }
  auto mw = static_cast<TrayThem::MainWidget *>(argument);
  auto programs = mw->m_lvPrograms;
  int index = programs->GetItemCount();
  programs->InsertItem(index, "");
  for (int i = 0; i < argc; i++) {
    programs->SetItem(index, i, argv[i] == nullptr ? "" : argv[i]);
  }
  return 0;
}

关于事件,常用的事件主要有wxEVT_LIST_ITEM_SELECTED和wxEVT_LIST_ITEM_DESELECTED,分别对应选中和取消选中Item,对应的事件处理函数原型为:

void handler(wxListEvent &event);

其中,event.GetItem可取到选中的Item,GetText可取到对应的Label,如果是单行选择模式的List(初始化时,设置了wxLC_SINGLE_SEL的flag),则GetText会返回第一列的Label

获取同一行中其它列的Text,可使用GetItemLabel方法,示例代码如下:

void TrayThem::MainWidget::OnProgramSelected(wxListEvent &event) {
  wxListItem item = event.GetItem();
  this->m_SelectedId = item.GetText();
  this->m_SelectedProgram.program_id = this->m_SelectedId;
  int col = item.GetColumn();
  this->m_SelectedProgram.running_status =
      this->m_lvPrograms->GetItemText(item, ++col);
  this->m_SelectedProgram.program_name =
      this->m_lvPrograms->GetItemText(item, ++col);
  this->m_SelectedProgram.autostart =
      this->m_lvPrograms->GetItemText(item, ++col) == "1" ? true : false;
  this->m_SelectedProgram.execution =
      this->m_lvPrograms->GetItemText(item, ++col);
  this->m_SelectedProgram.working_directory =
      this->m_lvPrograms->GetItemText(item, ++col);
  this->m_SelectedProgram.parameters =
      this->m_lvPrograms->GetItemText(item, ++col);
}

More from this blog

解决QWidget用winId获取HWND而导致Qt程序无事件消息的问题

问题原因: 当对一个QWidget调用winId时,默认情况下,Qt会对该窗口进行Native化,从而导致如鼠标等事件被其它原生窗口接管,表现出来的现像就是窗口不响应任何事件 解决思路: 防止Qt窗口Native化 解决办法: 第一步,在创建QApplication对象之前设置: QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); //注意:Qt::AA_NativeWindows受环境变量 QT_USE_NATI...

Jul 7, 20251 min read

解决因OpenGL渲染窗口高宽比导致图形变形

在 OpenGL 中,由于窗口的 宽高比(aspect ratio) 与绘制内容的坐标系统不一致,图像会出现拉伸、压缩等变形现象。为了解决这个问题,可根据窗口的大小调整投影矩阵,确保图像在视觉上保持原始比例。 先通过glViewPort调整视口 void resizeGL(int w, int h) { glViewport(0, 0, w, h); } 再根据窗口高宽比,计算出合适的投影矩阵,这样体现出来的样式,就是截掉了宽高比之外的内容,显示的内容不变形,正圆就是正圆,不会被拉伸成...

Jun 18, 20251 min read

雷的部落格威力缩小版

29 posts

雷的部落格威力缩小版