Tab-Focus problem

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
Neal_Miskin
In need of some credit
In need of some credit
Posts: 9
Joined: Sat Jan 12, 2019 10:00 pm

Tab-Focus problem

Post by Neal_Miskin »

I'm having an interesting issue where I can't seem to get radio buttons to take focus from the TAB key. In fact, I couldn't get anything to respond to the TAB key until I manually added the event handler.

I'm working on a basic calculator (because n00b) and it works pretty well. I've gotten it to tab between the two main text controls, but it doesn't seem to work with the radio buttons. As far as I can deduce, TextCtrl2->HasFocus() returns true (if I put a wxMessageBox there it shows up at runtime) but AddButton->HasFocus() never returns true.

Are RadfioButtons different? Am I evaluating the wrong condition here?

Here's the relevant code:

Code: Select all

void wxtestFrame::OnNavigationKey(wxNavigationKeyEvent& event){

    wxCommandEvent ev;
    if(TextCtrl1->HasFocus()){
            TextCtrl2->SetFocus();
        }else if(TextCtrl2->HasFocus()){
            //wxMessageBox("TextCtrl2 had focus");
            AddButton->SetFocus();
            AddButton->SetValue(true);
            wxtestFrame::OnAddButtonSelect(ev);
        }else if(AddButton->HasFocus()){
            wxMessageBox("Add Button sent this"); /* This message box never shows up, I must be evaluating the wrong condition. */
            SubButton->SetFocus();
            SubButton->SetValue(true);
            wxtestFrame::OnSubButtonSelect(ev);
        }else if(SubButton->HasFocus()){
            MultButton->SetFocus();
            MultButton->SetValue(true);
            wxtestFrame::OnMultButtonSelect(ev);
        }else if(MultButton->HasFocus()){
            DivideButton->SetFocus();
            DivideButton->SetValue(true);
            wxtestFrame::OnDivideButtonSelect(ev);
        }else if(Button1->HasFocus()){
            ClearBtn->SetFocus();
            wxMessageBox("Calc>Clear");
        }else if(ClearBtn->HasFocus()){
            TextCtrl1->SetFocus();
            wxMessageBox("Clear>Text1");
        }
}
P.S. I've tried it with the Tab_Traversal style on and off for each element and it doesn't seem to make a difference.

Thanks.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: Tab-Focus problem

Post by PB »

I would add a wxPanel as the only child of the wxFrame and created all the controls as children of that panel. wxPanel has a built-in support for tab navigation (and has the proper color for such a window).
Neal_Miskin
In need of some credit
In need of some credit
Posts: 9
Joined: Sat Jan 12, 2019 10:00 pm

Re: Tab-Focus problem

Post by Neal_Miskin »

So I tried creating a new panel.

I think I made the controls children of it, by changing "this" to "Panel2"

Code: Select all

    SubButton = new wxRadioButton(Panel2, ID_RADIOBUTTON2, _("Subtract"), wxPoint(16,120), wxDefaultSize, wxTAB_TRAVERSAL, wxDefaultValidator, _T("ID_RADIOBUTTON2"));
rather than

Code: Select all

SubButton = new wxRadioButton(this, ID_RADIOBUTTON2, _("Subtract"), wxPoint(16,120), wxDefaultSize, wxTAB_TRAVERSAL, wxDefaultValidator, _T("ID_RADIOBUTTON2"));
But it still doesn't seem to tab to the radio buttons, although it seems to now let me click on the background to have NO controls selected, which I guess is cool.

Previously it seemed to tab from TextCtrl2 to the AddButton and then immediately switch back to the 2nd TextCtrl, instead of any of the other radio buttons. Now , with the panel when I tab from TextCtrl2, it apparently goes to my 3rd TextCtrl, for which Tab_Traversal is off, and none of my code specifies that it should ever receive focus.

Also, the code seems to snap back to "this" instead of "Panel2" any time I touch anything with WXSmith, automated code just replaces itself I guess?
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: Tab-Focus problem

Post by PB »

Please post the whole code where you create the controls. Tabbing should work out of the box, unless one did something wrong, like using a wrong parent or flags for the radio button.

I tested the code below with this layout, did not notice any issues (wxWidgets 3.1.2, Windows 10)
rb.png
rb.png (8.73 KiB) Viewed 639 times

Code: Select all

#include <wx/wx.h>

class MyFrame : public wxFrame
{
public:
    MyFrame() : wxFrame(NULL, wxID_ANY, "Test", wxDefaultPosition, wxSize(800, 400))
    {               
        wxBoxSizer* mainPanelSizer = new wxBoxSizer(wxVERTICAL);
        wxPanel* mainPanel = new wxPanel(this);               
        
        mainPanelSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY), wxSizerFlags().Expand().Border());

        // a group of radio buttons, usually it is better to use a wxRadioBox instead
        wxBoxSizer* radioGroupSizer = new wxBoxSizer(wxHORIZONTAL);
        
        radioGroupSizer->Add(new wxRadioButton(mainPanel, wxID_ANY, "Radio Button 1.1", wxDefaultPosition, wxDefaultSize, wxRB_GROUP));        
        radioGroupSizer->Add(new wxRadioButton(mainPanel, wxID_ANY, "Radio Button 1.2"));        
        radioGroupSizer->Add(new wxRadioButton(mainPanel, wxID_ANY, "Radio Button 1.3"));
        mainPanelSizer->Add(radioGroupSizer, wxSizerFlags().Expand().Border());

        mainPanelSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY), wxSizerFlags().Expand().Border());

        // another group of radio buttons
        wxBoxSizer* radioGroupSizer2 = new wxBoxSizer(wxHORIZONTAL);
        
        radioGroupSizer2->Add(new wxRadioButton(mainPanel, wxID_ANY, "Radio Button 2.1", wxDefaultPosition, wxDefaultSize, wxRB_GROUP));        
        radioGroupSizer2->Add(new wxRadioButton(mainPanel, wxID_ANY, "Radio Button 2.2"));        
        radioGroupSizer2->Add(new wxRadioButton(mainPanel, wxID_ANY, "Radio Button 2.3"));
        mainPanelSizer->Add(radioGroupSizer2, wxSizerFlags().Expand().Border());

        mainPanelSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY), wxSizerFlags().Expand().Border());

        wxBoxSizer* radioAndTextSizer = new wxBoxSizer(wxHORIZONTAL);

        // a single radio button next to a text control
        radioAndTextSizer->Add(new wxRadioButton(mainPanel, wxID_ANY, "Radio Button Single", wxDefaultPosition, wxDefaultSize, wxRB_SINGLE),
            wxSizerFlags().Expand().Border());
        radioAndTextSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY), wxSizerFlags().Expand().Proportion(1).Border());

        mainPanelSizer->Add(radioAndTextSizer, wxSizerFlags().Expand().Border());

        mainPanelSizer->Add(new wxTextCtrl(mainPanel, wxID_ANY), wxSizerFlags().Expand().Border());
        
        mainPanel->SetSizer(mainPanelSizer);
    }	
};

class MyApp : public wxApp
{
public:	
    bool OnInit()
    {
        (new MyFrame)->Show();
        return true;
    }
}; wxIMPLEMENT_APP(MyApp);
As for wxSmith messing the code, I have never used it but it should take the parent from the control hierarchy you create when laying out the controls...
Post Reply