wxPropertyGrid详解

本文详细介绍wxWidgets中的wxPropertyGrid控件的使用方法,包括创建、添加、删除属性,设置控件样式,以及如何处理属性的层次化显示和遍历。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PropertyGrid(属性控件)是一种表格控件,用来组织和显示“属性”。“属性”是“名字”和“数值”的组合,“名字”一般是字符串,“数值”可以是各种类型,整数、浮点数、字符串、颜色等。
属性控件可以以层次化的结构组织和显示多个“属性”,如下图所示。
这里写图片描述

创建控件

wxPropertyGrid的构造函数同其他wxWidgets控件相同,

wxPropertyGrid::wxPropertyGrid  (
    wxWindow * parent, /// 父窗口
    wxWindowID id = wxID_ANY, /// 窗口ID  
    const wxPoint &     pos = wxDefaultPosition, /// 窗口位置   
    const wxSize &  size = wxDefaultSize, /// 窗口尺寸  
    long    style = wxPG_DEFAULT_STYLE, /// 控件风格
    const wxString & name = wxPropertyGridNameStr /// 控件名称
    )

可用的PropertyGrid控件风格与其含义如下:

标志含义
wxPG_AUTO_SORT自动排序
wxPG_HIDE_CATEGORIES隐藏层次(如果有层次的话)
wxPG_ALPHABETIC_MODE既自动排序,又隐藏层次
wxPG_BOLD_MODIFIED粗体显示改动的数据
wxPG_SPLITTER_AUTO_CENTER列分割线自动居中
wxPG_TOOLTIPS显示完整提示(需设置wxUSE_TOOLTIPS才能起效)
wxPG_STATIC_SPLITTER使用户不能调整列分割线
wxPG_STATIC_LAYOUT使用户不能调整布局
wxPG_TOOLBAR显示工具栏(wxPropertyGridManager 中有效)
wxPG_DESCRIPTION显示描述区(wxPropertyGridManager 中有效)
wxPG_NO_INTERNAL_BORDER不显示内部边线(wxPropertyGridManager中有效)

此外,在创建控件后,还可以通过调用SetExtraStyle函数为PropertyGrid控件设置扩展风格。PropertyGrid可用的扩展风格如下表所示:

注:PropertyGrid的扩展风格均以wxPG_EX_xxx表示,必须通过SetExtraStyle()函数设置.

标志含义
wxPG_EX_INIT_NOCAT快速启用 wxPG_HIDE_CATEGORIES模式
wxPG_EX_NO_FLAT_TOOLBARwxPropertyGridManager 不使用平面风格工具栏
wxPG_EX_MODE_BUTTONS在工具栏显示“目录”、“排序”按钮
wxPG_EX_HELP_AS_TOOLTIPS将帮助文本按提示方式显示(不再在状态栏显示)
wxPG_EX_NATIVE_DOUBLE_BUFFERING使用本地双缓冲
wxPG_EX_AUTO_UNSPECIFIED_VALUES允许用户将属性的数值设置为非规定值
wxPG_EX_HIDE_PAGE_BUTTONS在工具栏上隐藏页面选择按钮
wxPG_EX_MULTIPLE_SELECTION允许用户选择多个属性(按SHIFT键同时选择,或者鼠标左键拖动)
wxPG_EX_NO_TOOLBAR_DIVIDER工具栏不显示分割线(Windows下有效)
wxPG_EX_TOOLBAR_SEPARATOR工具栏下显示分割线

下面是创建PropertyGrid的示例代码。

wxPropertyGrid * ctrl = new wxPropertyGrid(this, ctrlID, wxDefaultPosition, wxDefaultSize, wxPG_DEFAULT_STYLE);

ctrl->SetExtraStyle(wxPG_EX_HELP_AS_TOOLTIPS);

增加属性

用户可以通过AppendAppendInInsert等函数来添加属性。其中,最常用的是Append函数。
该函数将新属性添加至控件的结尾处,函数声明如下:

wxPGProperty* wxPropertyGridInterface::Append(
    wxPGProperty *  newProperty ///新属性。
 )

wxWidgets已经提供了一些预定义类型的wxPGProperty,包括字符串、数字、字体、颜色等等。
下面例子创建了一些常见的属性。
这里写图片描述

代码如下:

// 字符串属性
pg->Append(new wxStringProperty("StringProperty", wxPG_LABEL, "test_name"));

// 整数属性
pg->Append(new wxIntProperty("IntProperty", wxPG_LABEL, 12345678));

// 浮点数属性
pg->Append( new wxFloatProperty("FloatProperty", wxPG_LABEL, 12345.678) );

// 逻辑属性
pg->Append( new wxBoolProperty("BoolProperty", wxPG_LABEL, false) );

// 长字符串属性(用一个单独的对话框编辑)
pg->Append( new wxLongStringProperty("LongStringProperty", wxPG_LABEL, "This is much longer string than the "                                     "first one. Edit it by clicking the button."));

// 目录属性
pg->Append( new wxDirProperty("DirProperty", wxPG_LABEL, ::wxGetUserHome()) );

// 字符列表属性
pg->Append( new wxArrayStringProperty("Label of ArrayStringProperty", "NameOfArrayStringProp"));

// 文件属性.
pg->Append( new wxFileProperty("FileProperty", wxPG_LABEL, wxEmptyString) );
// 设置文件属性的参数.
pg->SetPropertyAttribute("FileProperty", wxPG_FILE_WILDCARD, "All files (*.*)|*.*" );

有两种类型的属性需要特别说明一下:

EnumProperty(枚举属性)

枚举属性可以通过下拉菜单选择若干选项之一。
作为选项的数据可以利用wxArrayString类型、字符串数组类型或者wxPGChoices类型。
这里写图片描述
示例如下:

/// 方法1,通过wxArrayString
wxArrayString items;
items.Add(wxT("item_value_1"));
items.Add(wxT("item_value_2"));
items.Add(wxT("item_value_3"));

pg->Append(new wxEnumProperty(wxT("item_name"), wxPG_LABEL, items));


/// 方法2,通过字符串数组
const wxChar* items[] = {
    wxT("item_value_1"), wxT("item_value_2"), wxT("item_value_3"), NULL 
};

pg->Append(new wxEnumProperty("item_name", wxPG_LABEL, items));

/// 方法3,通过wxPGChoices
wxPGChoices chs;
chs.Add("item_value_1");
chs.Add("item_value_2");
chs.Add("item_value_3");

pg->Append(new wxEnumProperty("item_name", wxPG_LABEL, chs));

此外,EnumProperty还支持“标签”和“数值”分离。即除指定可选的标签外,为每个标签另外指定整数数据,通过数据来设定当前选择的标签。
示例如下:

///通过wxPGChoices,也可通过其他两种办法设置.
wxPGChoices chs;
chs.Add("item_value_1", 11);
chs.Add("item_value_2", 22);
chs.Add("item_value_3", 33);

wxPGProperty * prop = pg->Append(new wxEnumProperty("item_name", wxPG_LABEL, chs));

prop->SetValue(11);
wxString value = prop->GetValueAsString(); // value = "item_value_1"

FlagProperty(标志属性)

标志属性与枚举属性类似,同样包含多个选项,可以实现多个选项的组合。运行效果如下图所示。
这里写图片描述

示例如下:

///通过wxPGChoices,也可通过其他两种办法设置.
wxPGChoices chs;
chs.Add("flag_1");
chs.Add("flag_2");
chs.Add("flag_3");

wxPGProperty * prop = pg->Append(new wxFlagsProperty("item_name", wxPG_LABEL, chs));

删除属性

删除属性的常用方法包括:

  • DeleteProperty():删除指定属性及其子属性。
  • Clear():删除所有属性。

示例代码如下:

wxPGProperty * prop1 =  pg->Append(new wxStringProperty("Property1", wxPG_LABEL));
wxPGProperty * prop2 =  pg->Append(new wxStringProperty("Property2", wxPG_LABEL));
wxPGProperty * prop3 =  pg->Append(new wxStringProperty("Property3", wxPG_LABEL));


/// 删除属性1
pg->DeleteProperty("Property1");    
/// 删除属性2
pg->DeleteProperty(prop2);          

/// 删除所有属性.
pg->Clear();

获取指定属性

通过PropertyGrid的成员函数GetPropertyGetPropertyByName可以获取指定的属性。
GetPropertyGetPropertyByName可以通过属性名称来获取指定的属性。
示例代码如下:

pg->Append(new wxStringProperty("StringProperty", wxPG_LABEL, "test_name"));

/// 获取前面添加的名为"StringProperty"的属性.
wxPGProperty * prop = pg->GetProperty("StringProperty");
……

获取属性的内容

通常,用户可以通过两种方法获取属性的数值:

  • 调用wxPGProperty的GetValue成员函数。
  • 调用wxPropertyGrid的GetPropertyValue成员函数。

上述函数均返回wxVariant类型的结果,需要将wxVariant转换为用户所需的类型,如整数、浮点数、字符串等。

……
wxPGProperty * prop1 = pg->Append(new wxStringProperty("name", wxPG_LABEL, "test value"));

wxString valStr;

wxAny value1 = prop1->GetValue();
valStr = value1.As<wxString>();

wxAny value2 = pg->GetPropertyValue("name");
valStr = value1.As<wxString>();

wxAny value3 = pg->GetPropertyValue(prop1);
valStr = value1.As<wxString>();

……

PropertyGrid还提供了一些获取属性数值的函数,省去用户进行类型转换。如:

  • GetPropertyValueAsArrayInt
  • GetPropertyValueAsArrayString
  • GetPropertyValueAsBool
  • GetPropertyValueAsDateTime
  • GetPropertyValueAsDouble
  • GetPropertyValueAsInt
  • ……

修改属性的数值

通常,用户可以通过两类方法设置属性的数值:
(1)SetValue方法

  • 调用wxPGProperty的SetValue成员函数。
  • 调用wxPropertyGrid的SetPropertyValue成员函数。

上述函数均进行了重载,以接受多种类型的输入参数。示例代码如下:

……
wxPGProperty * prop1 = pg->Append(new wxStringProperty("name", wxPG_LABEL));

prop1->SetValue("value set 1");
wxString valStr = prop1->GetValueAsString();

pg->SetPropertyValue("name", "value set 2");
valStr = pg->GetPropertyValueAsString("name");

……

(2)ChangeValue方法
还可以使用wxPropertyGrid的ChangePropertyValue成员函数改变指定属性的数值。
注意:ChangePropertyValue函数用法和SetPropertyValue函数相同,但效果不同。ChangePropertyValue会(a)执行输入验证过程,(b)发送属性改变事件,而SetPropertyValue则不会。

属性的层次化

可以将属性组织成类似“文件夹”的方式(树状层次结构)。下面是一个层次化属性的运行效果:
这里写图片描述
上述效果可以通过2种途径实现:
(1)通过wxPGPropertyGrid的AppendIn成员函数或Insert成员函数增加层次化的属性
wxPropertyGrid的AppendIn()和Insert()函数可以为指定属性添加子属性,形成树状结构的属性层次。该方法使用相对复杂,但更为灵活。
AppendIn函数将新的属性添加至父属性的结尾。
`

wxPGProperty* wxPropertyGridInterface::AppendIn(
    wxPGPropArg  parent, ///父属性.
    wxPGProperty *  newProperty ///新属性。
 )

Insert函数将新的属性添加至父属性的指定位置。

wxPGProperty* wxPropertyGridInterface::Insert(
    wxPGPropArg  parent, ///父属性.
    int  index,  ///添加位置. 0表示开始位置,-1表示结尾位置,。
    wxPGProperty *  newProperty ///新属性。
 )

为实现前面的效果,代码如下:

/// 1.添加一个“Group 1”属性
wxPGProperty * group1 = pg->Append(new wxPropertyCategory("Group 1"));

/// 为“Group 1”属性添加子属性
pg->AppendIn(group1, new wxStringProperty("Name1_1"));
pg->AppendIn(group1, new wxStringProperty("Name1_2"));
pg->AppendIn(group1, new wxStringProperty("Name1_3"));

/// 2.添加一个“Group 2”属性
wxPGProperty * group2 = pg->Append(new wxPropertyCategory("Group 2"));

/// 为“Group 2”属性添加子属性
pg->AppendIn(group2, new wxStringProperty("Name2_1"));
pg->AppendIn(group2, new wxStringProperty("Name2_2"));
pg->AppendIn(group2, new wxStringProperty("Name2_3"));

(2)通过wxPropertyCatagory来实现。
通过增加wxPropertyCategory类型的属性,可以为属性进行分类,实现简单的属性层次化。
在PropertyGrid中增加wxPropertyCatagory属性,该属性将自动成为当前目录属性,后续添加的属性将作为该属性的子属性,直至添加另一个wxPropertyCatagory属性。
代码如下:

/// 1.添加一个“Group 1”目录
pg->Append(new wxPropertyCategory("Group 1"));

/// 后续的属性都将添加至“Group 1”目录
pg->Append(new wxStringProperty("Name1_1"));
pg->Append(new wxStringProperty("Name1_2"));
pg->Append(new wxStringProperty("Name1_3"));

/// 2.添加一个“Group 2”目录
pg->Append(new wxPropertyCategory("Group 2"));

/// 后续的属性都将添加至“Group 1”目录
pg->Append(new wxStringProperty("Name2_1"));
pg->Append(new wxStringProperty("Name2_2"));
pg->Append(new wxStringProperty("Name2_3"));

遍历属性

PropertyGrid控件提供了类似STL迭代器(iterator)的属性遍历方法。
PropertyGrid控件提供的迭代器有两类:

  • wxPropertyGridIterator
  • wxPropertyGridConstIterator(const类型迭代器)

PropertyGrid迭代器的主要成员函数如下:

  • Next():向后迭代,等价于operator ++();
  • Prev():向前迭代,等价于operator –();
  • AtEnd():判断是否迭代结束。

ProperyGrid通过GetIterator函数来获取迭代器.
该函数的声明如下:

wxPropertyGridIterator wxPropertyGridInterface::GetIterator(
    int  flags = wxPG_ITERATE_DEFAULT, 
    wxPGProperty *  firstProp = NULL  
)

wxPropertyGridIterator wxPropertyGridInterface::GetIterator(
    int  flags, 
    int  startPos 
)

其中, flags标志了获取的迭代器的位置和类型。

其通常使用方法如下:

for (wxPropertyGridIterator it = ctrl->GetIterator(); ! it.AtEnd(); it++)
{
    wxPGProperty * prop = * it;
    …
}

通过设置GetIterator的参数,可以获得不同类型的迭代器。

/// 针对可见的属性,获取结尾位置的迭代器.
wxPropertyGridIterator it1 = ctrl->GetIterator(wxPG_ITERATE_VISIBLE, wxBOTTOM);
…
/// 针对所有属性,获取结尾位置的迭代器.
wxPropertyGridIterator it2 = ctrl->GetIterator(wxPG_ITERATE_ALL, wxBOTTOM);
…

常用消息

PropertyGrid控件消息处理函数类型是:

void XXX(wxPropertyGridEvent & event)

PropertyGrid控件的常见消息及其含义如下:

消息含义
EVT_PG_SELECTED (id, func)属性被选中
EVT_PG_CHANGED(id, func)属性已经发生改变
EVT_PG_CHANGING(id, func)属性打算发生改变。可以利用wxPropertyGridEvent::GetValue()先观察修改后的值,(可否决,即利用 wxPropertyGridEvent::Veto()防止发生改变)
EVT_PG_RIGHT_CLICK(id, func)属性被鼠标右击
EVT_PG_DOUBLE_CLICK(id, func)属性被鼠标双击
EVT_PG_ITEM_COLLAPSED(id, func)属性收起子属性
EVT_PG_ITEM_EXPANDED(id, func)属性展开子属性
EVT_PG_COL_BEGIN_DRAG(id, func)用户开始改变列尺寸(可否决)
EVT_PG_COL_DRAGGING, (id, func)用户正在改变列尺寸
EVT_PG_COL_END_DRAG(id, func)用户完成改变列尺寸
EVT_PG_LABEL_EDIT_BEGIN(id, func)用户开始编辑属性标签(可否决)
EVT_PG_LABEL_EDIT_ENDING(id, func)用户结束编辑属性标签(可否决)
EVT_PG_HIGHLIGHTED(id, func)鼠标经过属性。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值