c – PropertyGrid中的按钮
有没有办法将属性设置为按钮或向属性添加按钮?通过网格示例,我注意到你可以做一些事情
wxPGEditor* editorButton = wxPropertyGrid::RegisterEditorClass(someButton); propertyGrid->SetPropertyEditor(wxT("Name"),editorButton ); 但是,我希望有不同的按钮,而不仅仅是一种类型,这将支持. 编辑: 编辑2:要清楚,我希望属性字段只能是一个按钮. 解决方法
您必须创建一个自定义wxPGEditor,它根据存储在属性中的数据来中继按钮事件.
wxPGProperty可以存储用户定义的数据(wxClientData),该数据可用于存储回调函数. 首先,您必须定义将在按钮事件上调用的处理程序的函数签名. typedef bool (wxEvtHandler::*ButtonEventMethod)(wxPGProperty*); 处理程序接收附加属性作为参数,如果属性被修改,则应返回true. 现在需要一个基于wxClientData的类来存储回调: struct ButtonData : wxClientData { ButtonData(ButtonEventMethod method,wxEvtHandler* handler) : _method(method),_handler(handler) {} bool call(wxPGProperty* property) { return (*_handler.*_method)(property); } private: ButtonEventMethod _method; wxEvtHandler* _handler; }; 该类只存储方法的地址及其所属的类.编辑器将从属性中提取此对象并执行call()方法,该方法依次执行回调: class ButtonEventEditor : public wxPGTextCtrlAndButtonEditor { protected: virtual bool OnEvent(wxPropertyGrid* propgrid,wxPGProperty* property,wxWindow* wnd_primary,wxEvent& event) const { // handle the button event if( event.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED ) // extract the client data from the property if( ButtonData* btn = dynamic_cast<ButtonData*>(property->GetClientObject()) ) // call the method return btn->call(property); return wxPGTextCtrlAndButtonEditor::OnEvent(propgrid,property,wnd_primary,event); } }; 要将它包装起来,可以编写一个将方法“绑定”到属性的函数: void BindButton(wxPGProperty* property,ButtonEventMethod method,wxEvtHandler* handler) { property->SetClientObject(new ButtonData(method,handler)); } 还有一个宏,使它更简单: #define BIND_BUTTON(property,method,handler,editor) property->SetEditor(editor); BindButton(property,static_cast<ButtonEventMethod>(method),handler) 现在您可以将成员函数绑定到属性: // register the editor wxPGEditor* editor = propertyGrid->RegisterEditorClass(new ButtonEventEditor()); // create a property wxPGProperty* prop = propertyGrid->Append(new wxStringProperty("StringProperty")); // bind method foo to the property BIND_BUTTON(prop,&Frame::foo,this,editor); 方法foo可能如下所示: bool Frame::foo(wxPGProperty* p) { p->SetValue("foo"); return true; } 这只是一个示例,用于演示wxPGProperty如何存储回调(而不是创建多个wxPGEditors).可以修改回调存储(此处为ButtonData)以存储 另一种方法是将回调信息存储在wxPGEditor实例中.但是,这需要多个编辑器实例,每个不同的回调函数一个. UPDATE
在选择属性之前,不会激活编辑器. 虽然可以让自定义属性创建一个按钮并忽略编辑器系统,但属性网格不是设计为以这种方式工作而且这种“黑客”可能会导致一些问题.但是,我最后加入了黑客攻击.
这只是我用作示例基类的编辑器的副作用,并且很容易更改.由于不需要wxTextCtrl,只需基于 class ButtonEventEditor : public wxPGEditor { protected: virtual wxPGWindowList CreateControls(wxPropertyGrid* propgrid,const wxPoint& pos,const wxSize& size) const { // create and return a single button to be used as editor // size and pos represent the entire value cell: use that to position the button return wxPGWindowList(new wxButton(propgrid,wxPG_SUBID1,"Edit",pos,size)); } // since the editor does not need to change the primary control (the button) // to reflect changes,UpdateControl is just a no-op virtual void UpdateControl(wxPGProperty* property,wxWindow* ctrl) const {} // and here we remove the call to the base class because it is abstract virtual bool OnEvent(wxPropertyGrid* propgrid,wxEvent& event) const { if( event.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED ) if( ButtonData* btn = dynamic_cast<ButtonData*>(property->GetClientObject()) ) return btn->call(property); return false; } };
如果你的意思是总:wxPropertyGrid :: RegisterEditorClass只是注册一个带有属性网格的编辑器(网格将取得编辑器的所有权,并在销毁属性网格时自动删除它).您可以根据需要注册任意数量的编辑器.您将编辑器设置为特定属性,而不是整个属性网格. 如果您的意思是同时:是的,遗憾的是,在任何给定时间只有一个属性编辑器可以处于活动状态. 黑客 让我用前面提到的黑客来完成这个任务. 首先,我们需要一个自定义的wxPGCellRenderer来定位属性网格上的按钮: class ButtonMover : public wxPGCellRenderer { public: // pointer to the button from the property ButtonMover(wxButton* btn) : _btn(btn) {} protected: virtual bool Render(wxDC &dc,const wxRect &rect,const wxPropertyGrid *propertyGrid,wxPGProperty *property,int column,int item,int flags) const { if( column == 0 ) { // 0 = label,1 = value // instead of actually drawing the cell,// move the button to the cell position: wxRect rc(rect); // calculate the full property width rc.SetWidth(propertyGrid->GetClientRect().width-rect.GetX()); _btn->SetSize(rc); // move button _btn->Show(); // initially hidden,show once 'rendered' (moved) } return true; } private: wxButton* _btn; }; 现在我们可以创建自定义属性: class ButtonProperty : public wxPGProperty { public: // [parent] should be the property grid // [func] is the event handler // [button] is the button label // [label] is the property display name (sort name with autosort) // [name] is the internal property name ButtonProperty(wxWindow* parent,wxObjectEventFunction func,const wxString& button,const wxString& label=wxPG_LABEL,const wxString& name=wxPG_LABEL) : wxPGProperty(label,name),_btn(new wxButton(parent,wxID_ANY,button)),_renderer(_btn) { // connect the handler to the button _btn->Connect(wxEVT_COMMAND_BUTTON_CLICKED,func); _btn->Hide(); // when it's off the grid,it's not rendered // (thus not moved properly) } protected: virtual wxPGCellRenderer* GetCellRenderer(int column) const { return &_renderer; // return button mover } virtual const wxPGEditor* DoGetEditorClass () const { return 0; // not using an editor } private: wxButton* _btn; // the button attached to the property mutable ButtonMover _renderer; // the button mover }; 删除了对编辑器的需求后,您现在可以将事件处理程序直接附加到属性: propertyGrid->Append( new ButtonProperty( propertyGrid,// parent window wxCommandEventHandler(Frame::OnClick1),// event handler "Click me!") // button label ); propertyGrid->Append( new ButtonProperty( propertyGrid,wxCommandEventHandler(Frame::OnClick2),"Edit this!") ); 处理程序看起来像这样: void OnClick1(wxCommandEvent& event) { //TODO ... } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 如何使用VS2008编译二进制文件不需要.NET?
- xml.etree.ElementTree — The ElementTree XML API
- cocos2dx RichText关于字符串截取的bug
- oracle存储过程学习经典[语法+实例+调用]
- SQlite数据库的C编程接口(四) 绑定参数(Bound Parameter
- AJAX 自学练习 请求与显示
- postgresql – 向中国插入内容时的延迟问题
- ruby-on-rails – RESTful网站与RESTful API – 有什么区别
- QDomNode与QDomElement的关系整理
- postgresql – 尽管用户名正确,但连接到Azure postgres服务