I am using WxWidgets 3.2 for my C++ Windows application. In my application I need to change the interface for the user when he clicks the buttons.
To change the interface, I use this idea: I show the desired panel using the Show() function and hide the rest of the panels using the Hide() function. Of course, I create the necessary panels in advance.
For example, here is the code for the main window of my application:
MainFrame.h
class MainFrame : public wxFrame {
public:
MainFrame(const wxString& title);
~MainFrame();
private:
LoginPanel * loginPanel; // panel pointer
TablePanel * tablePanel; // panel pointer
public:
void ShowLoginPanel(); // function that displays the loginPanel
void ShowTablePanel(); // function that displays the tablePanel
void OnLoginEntered(wxCommandEvent& event); // to check the login
};
class implementation
MainFrame.cpp
MainFrameFrame::MainFrameFrame(const wxString& title)
: wxFrame(nullptr, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE & ~wxRESIZE_BORDER) {
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
loginPanel = new LoginPanel(this, wxID_ANY);
tablePanel = new TablePanel(this, wxID_ANY);
mainSizer->Add(loginPanel, 1, wxEXPAND);
mainSizer->Add(tablePanel, 1, wxEXPAND);
SetSizer(mainSizer);
ShowLoginPanel();
}
void MainFrame::OnLoginEntered(wxCommandEvent& event) {
auto login = event.GetString();
if (login == CORRECT)
ShowTablePanel();
}
void MainFrame::ShowTablePanel() {
if (loginPanel != nullptr)
loginPanel->Hide();
if (tablePanel != nullptr) {
tablePanel->Show();
}
}
void MainFrame::ShowLoginPanel() {
if (tablePanel != nullptr) {
tablePanel->Hide();
}
if (loginPanel != nullptr)
loginPanel->Show();
}
In this code, if the user entered the correct login, then I show the tablePanel and hide the loginPanel.
Here is the LoginPanel class code :
LoginPanel.h
class LoginPanel : public wxPanel {
public:
LoginPanel(wxWindow* parent, wxWindowID id = wxID_ANY);
private:
wxTextCtrl* usernameInput;
};
LoginPanel.cpp
LoginPanel::LoginPanel(wxWindow* parent, wxWindowID id)
: wxPanel(parent, id) {
wxButton* connectButton = new wxButton(loginTab, wxID_ANY, "Connect");
connectButton->Bind(wxEVT_BUTTON, &LoginPanel::OnConnectButton, this);
}
Here is the TablePanel class code :
TablePanel.h
class TablePanel : public wxPanel {
public:
TablePanel(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL, const wxString& name = wxPanelNameStr);
private:
wxButton* backButton;
wxGridSizer* tableGrid;
wxPanel* CreateTableItemPanel(int tableNumber);
};
TablePanel.cpp
TablePanel::TablePanel(wxWindow* parent, wxWindowID id, const wxPoint& pos,
const wxSize& size, long style, const wxString& name)
: wxPanel(parent, id, pos, size, style, name)
{
// Creating a back button
backButton = new wxButton(this, wxID_ANY, "Back");
// Create a grid of gaming tables
tableGrid = new wxGridSizer(5, 4, 5, 5);
// Adding multiple grid elements
for (int i = 1; i <= 20; ++i) {
wxPanel* tableItemPanel = CreateTableItemPanel(i);
tableGrid->Add(tableItemPanel, 0, wxEXPAND | wxALL, 5);
}
// Placing elements on the gaming table selection panel
wxBoxSizer* tableSelectSizer = new wxBoxSizer(wxVERTICAL);
tableSelectSizer->Add(backButton, 0, wxALIGN_LEFT | wxALL, 5);
tableSelectSizer->Add(tableGrid, 1, wxEXPAND | wxALL, 5);
this->SetSizer(tableSelectSizer);
}
wxPanel* TableSelectPanel::CreateTableItemPanel(int tableNumber){
wxPanel* itemPanel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SIMPLE);
wxBoxSizer* itemSizer = new wxBoxSizer(wxVERTICAL);
// Create an image and add it to the grid
wxBitmap bitmap; // Replace with real image
wxStaticBitmap* bmpCtrl = new wxStaticBitmap(itemPanel, wxID_ANY, bitmap);
itemSizer->Add(bmpCtrl, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5);
// Creating text with information about the table
wxString tableInfo = wxString::Format("Стол %d", tableNumber);
wxStaticText* infoText = new wxStaticText(itemPanel, wxID_ANY, tableInfo);
itemSizer->Add(infoText, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5);
// Create a "Play" button and add it to the grid
wxButton* playButton = new wxButton(itemPanel, wxID_ANY, "Play");
itemSizer->Add(playButton, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5);
itemPanel->SetSizer(itemSizer);
return itemPanel;
}
The problem is that when changing panels, all elements in the displayed panel are shifted to the upper left corner.
If you stretch the panel to full screen, then all the elements are displayed correctly again. Why do items in the rendered panel display incorrectly when changing panels? And how can I fix it?
You can, of course, implement this yourself, but what you describe seems an awful lot like wxSimplebook, so perhaps you could just use this class instead?