Динамическое обновление элемента радио wxWidgets

Я пытаюсь динамически изменить состояние группы радиоэлементов, и я не мог понять, как это сделать. Я приложил свой код и файл CMakeLists.txt ниже. Когда вызывается метод Test, я ожидаю, что пункт 3 радио будет проверен, но пункт 1 радио остается проверенным. Может кто-нибудь показать мне, где я делаю неправильно?

Спасибо.

#CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
project(menu_radio_item)
find_package(wxWidgets REQUIRED core)
if(wxWidgets_FOUND)
include(${wxWidgets_USE_FILE})
add_executable(radio_item main.cpp)
target_link_libraries(radio_item ${wxWidgets_LIBRARIES})
endif(wxWidgets_FOUND)

Код:

#include <wx/wx.h>

// Application class declaration
class MyApp : public wxApp {
public:
virtual bool OnInit();
};
DECLARE_APP(MyApp)

// Frame class declaration
#define wxID_RADIO_ITEM_1 wxID_HIGHEST + 1
#define wxID_RADIO_ITEM_2 wxID_HIGHEST + 2
#define wxID_RADIO_ITEM_3 wxID_HIGHEST + 3
#define wxID_TEST         wxID_HIGHEST + 4

class MyFrame : public wxFrame {
public:
MyFrame(const wxString& title);
void OnQuit(wxCommandEvent& event);
void OnRadioItemPressed(wxCommandEvent& event);
void OnTest(wxCommandEvent& event);
void OnRadioItemUpdate(wxUpdateUIEvent& event);
private:
wxMenuBar *menubar;
wxMenu *file;
int item_controller;
DECLARE_EVENT_TABLE()
};

// Application class implementation
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit() {
MyFrame *frame = new MyFrame(wxT("Simple Menu and Toolbar"));
frame->Show();
return true;
}

// Frame class definition
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(wxID_EXIT, MyFrame::OnQuit)
EVT_MENU(wxID_RADIO_ITEM_1, MyFrame::OnRadioItemPressed)
EVT_MENU(wxID_RADIO_ITEM_2, MyFrame::OnRadioItemPressed)
EVT_MENU(wxID_RADIO_ITEM_3, MyFrame::OnRadioItemPressed)
EVT_MENU(wxID_TEST, MyFrame::OnTest)
EVT_UPDATE_UI(wxID_RADIO_ITEM_1, MyFrame::OnRadioItemUpdate)
EVT_UPDATE_UI(wxID_RADIO_ITEM_2, MyFrame::OnRadioItemUpdate)
EVT_UPDATE_UI(wxID_RADIO_ITEM_3, MyFrame::OnRadioItemUpdate)
END_EVENT_TABLE()

MyFrame::MyFrame(const wxString& title) :
wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(280, 180)),
item_controller(1) {
menubar = new wxMenuBar;
file = new wxMenu;
file->Append(wxID_EXIT, wxT("&Quit"));
file->AppendSeparator();
file->AppendRadioItem(wxID_RADIO_ITEM_1, wxT("One"));
file->AppendRadioItem(wxID_RADIO_ITEM_2, wxT("Two"));
file->AppendRadioItem(wxID_RADIO_ITEM_3, wxT("Tree"));
file->AppendSeparator();
file->Append(wxID_TEST, wxT("Test"));
menubar->Append(file, wxT("&File"));
SetMenuBar(menubar);
Centre();
}

void MyFrame::OnQuit(wxCommandEvent& event) {
Close(true);
}

void MyFrame::OnRadioItemPressed(wxCommandEvent& event) {
if(event.GetId() == wxID_RADIO_ITEM_1) {
std::cout << "Item 1 is pressed" << std::endl;
}
else if(event.GetId() == wxID_RADIO_ITEM_2) {
std::cout << "Item 2 is pressed" << std::endl;
}
else if(event.GetId() == wxID_RADIO_ITEM_3) {
std::cout << "Item 3 is pressed" << std::endl;
}
else {
std::cout << "No match!" << std::endl;
}
}

void MyFrame::OnRadioItemUpdate(wxUpdateUIEvent& event) {
std::cout << "OnRadioItemUpdate" << std::endl;
wxMenuItem* item;
switch(item_controller) {
case 1:
item = GetMenuBar()->FindItem(wxID_RADIO_ITEM_1);
item->Check(true);
break;
case 2:
item = GetMenuBar()->FindItem(wxID_RADIO_ITEM_2);
item->Check(true);
break;
case 3:
item = GetMenuBar()->FindItem(wxID_RADIO_ITEM_3);
item->Check(true);
break;
}
/*
std::cout << "OnRadioItemUpdate" << std::endl;
switch(event.GetId()) {
case wxID_RADIO_ITEM_1:
event.Check(item_controller == 1);
break;
case wxID_RADIO_ITEM_2:
event.Check(item_controller == 2);
break;
case wxID_RADIO_ITEM_3:
event.Check(item_controller == 3);
break;
}
*/
}void MyFrame::OnTest(wxCommandEvent& event) {
item_controller = 3;
UpdateWindowUI();
}

0

Решение

Вы не должны изменять состояние чего-либо непосредственно из wxEVT_UPDATE_UI обработчики, это не так, как это работает. Вам нужно позвонить event.Check() вместо этого, чтобы указать, должен ли быть проверен элемент, для которого обрабатывается событие. Как следствие этого, вы не можете повторно использовать один и тот же обработчик для всех элементов — если только вы не хотите, чтобы все они были включены или отключены одновременно, то есть.

Это, с одной стороны, намного проще, чем вы думаете, но с другой стороны, тоже совсем другое. Механизм обновления пользовательского интерфейса носит «функциональный» характер: вы не меняете состояние, вы просто определяете, каким оно должно быть.

Прочитайте документация и, может быть, более полезно, посмотрите на примеры использования wxUpdateUIEvent в примере кода (просто grep их для этого), чтобы увидеть, как он должен использоваться.

0

Другие решения


По вопросам рекламы [email protected]