2015-01-12 1 views
0

라디오 항목 그룹의 상태를 동적으로 변경하려고하는데 어떻게해야하는지 알 수 없습니다. 아래 코드와 CMakeLists.txt 파일을 첨부했습니다. Test 메서드가 호출되면 라디오 항목 3이 체크되지만 라디오 항목 1은 체크 된 상태로 유지됩니다. 누구든지 내가 어디에서 잘못했는지 보여 줄 수 있습니까?wxWidgets 라디오 항목 업데이트하기 동적으로

감사합니다.

#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()으로 전화해야합니다. 따라서 모든 항목에 대해 동일한 핸들러를 다시 사용할 수는 없습니다. 즉, 모든 항목을 동시에 활성화 또는 비활성화하려는 경우는 예외입니다.

한편으로는 생각보다 훨씬 간단하지만 다른 한편으로는 매우 다릅니다. 업데이트 UI 메커니즘은 본질적으로 "기능적"입니다. 상태를 변경하지 않고 상태를 정의해야합니다.

documentation을 읽고 더 유용하게 사용하는 방법을 보려면 샘플 코드에서 wxUpdateUIEvent을 사용하는 예를 살펴보고 (단지 grep로 그려야 함) 유용하게 사용할 수 있습니다.

+0

답해 주셔서 감사합니다.하지만 라디오 버튼이있는 예제를 찾을 수 없습니다. 내 코드에는 다른 메뉴 항목이 있습니다. 나는 이미 문서를 읽었고 라디오 버튼에 대해서는 아무것도 읽지 않았다. 그리고 라디오 버튼의 한가지 문제점은 사용자가 UI 버튼 중 하나를 변경하면 UI 업데이트 콜백이 모두 호출된다는 것입니다. – myirci

+0

'wxEVT_UPDATE_UI'를 사용한다면 * 변경 *하지 * 말아야합니다. 라디오 버튼을 사용하든 다른 것을 사용하든 상관 없습니다. 처리기에서'event.Check()'또는'event.Enable()'를 호출하는 것 이외에는 절대로 다른 작업을해서는 안됩니다. –

+0

안녕하세요, 귀하가 제안한대로 처리기를 변경했지만 (이해 한만큼) 작동하지 않습니다. 'void MyFrame :: OnRadioItemUpdate (wxUpdateUIEvent & 이벤트) { std :: cout << "OnRadioItemUpdate"<< std :: endl; switch (event.GetId()) { case wxID_RADIO_ITEM_1 : event.Check (item_controller == 1); 휴식; 케이스 wxID_RADIO_ITEM_2 : event.Check (item_controller == 2); 휴식; 케이스 wxID_RADIO_ITEM_3 : event.Check (item_controller == 3); 휴식; } }' – myirci

관련 문제