动态更新 wxWidgets 单选项

Updating wxWidgets Radio Item Dynamically

本文关键字:选项 单选项 更新 wxWidgets 动态      更新时间:2023-10-16

我正在尝试动态更改一组无线电项目的状态,但我不知道该怎么做。我在下面附上了我的代码和 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();
}

您不应该直接从wxEVT_UPDATE_UI处理程序更改任何内容的状态,这不是它的工作方式。您需要改为调用event.Check()以指示是否应检查正在处理事件的项目。因此,您不能对所有项重用相同的处理程序 - 除非您希望同时启用或禁用所有项。

一方面,它比你想象的要简单得多,但另一方面也非常不同。更新 UI 机制本质上是"功能性"的:您不会更改状态,只需定义状态应该是什么。

阅读文档,也许更有用的是,查看示例代码中使用wxUpdateUIEvent的示例(只需 grep 它们)以了解应该如何使用它。