替换 wxWidgets 中 wxFrame 的 sizer
Replace sizer of a wxFrame in wxWidgets
我正在编写一个扫雷小游戏来熟悉 wxWidgets(Windows,wxWidgets 3.1.4)。该应用程序可以很好地处理一个游戏,现在我想添加“新游戏”功能。对于布局,我使用 wxGridSizer
.
我的第一个方法是创建一个新的 wxGridSizer
并在其中添加新字段,然后将当前的 sizer 替换为新的。尽管我想出了如何重用旧的 sizer(并且它通常也是一个更好的解决方案),但我还是很好奇如何正确地更换 sizer。
我能够将我的问题简化为:
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
class MyApp : public wxApp {
public:
virtual bool OnInit();
};
class MyFrame : public wxFrame {
public:
MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size);
private:
void OnExit(wxCommandEvent &event);
void OnRefill(wxCommandEvent &event);
wxDECLARE_EVENT_TABLE();
};
enum { ID_Refill = 1 };
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(ID_Refill, MyFrame::OnRefill)
EVT_MENU(wxID_EXIT, MyFrame::OnExit)
wxEND_EVENT_TABLE() wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit() {
MyFrame *frame = new MyFrame("Hello World", wxPoint(50, 50), wxSize(300, 200));
frame->Show(true);
return true;
}
MyFrame::MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size)
: wxFrame(NULL, wxID_ANY, title, pos, size) {
wxMenu *menu = new wxMenu;
menu->Append(ID_Refill, "&Refill...\tCtrl-R", "Creates new layout");
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append(menu, "&Menu");
SetMenuBar(menuBar);
wxGridSizer *sizer = new wxGridSizer(2, 2, 1, 1);
SetSizer(sizer);
for (auto i = 0; i < 4; i++) {
wxButton *button = new wxButton(this, wxID_ANY, std::to_string(i), wxDefaultPosition, wxDefaultSize, 0);
sizer->Add(button, wxALL, 0);
}
}
void MyFrame::OnExit(wxCommandEvent &) {
Close(true);
}
void MyFrame::OnRefill(wxCommandEvent &) {
Freeze();
GetSizer()->Clear(true);
wxGridSizer *sizer = new wxGridSizer(3, 3, 1, 1);
SetSizer(sizer);
for (auto i = 0; i < 9; i++) {
wxButton *button = new wxButton(this, wxID_ANY, std::string("Refilled") + std::to_string(i), wxDefaultPosition,
wxDefaultSize, 0);
sizer->Add(button, wxALL, 0);
}
sizer->Layout();
Thaw();
Refresh();
}
问题是在 OnRefill
功能之后,应用程序只显示第一个按钮 (Refilled0
),而不显示其余按钮。
在OnRefill
之前:
OnRefill
之后:
我的问题是如何正确替换 MyFrame
的 sizer?根据我从示例和文档中了解到的内容,这应该可行,但我想我遗漏了一些东西。
要替换 sizer,您只需对 MyFrame::OnRefill
方法做一点小改动。
不要调用 sizer->Layout();
,只需调用 Layout();
。我不完全确定为什么为 sizer 调用 Layout 不起作用。
完整的方法如下所示:
void MyFrame::OnRefill(wxCommandEvent &) {
Freeze();
GetSizer()->Clear(true);
wxGridSizer *sizer = new wxGridSizer(3, 3, 1, 1);
SetSizer(sizer);
for (auto i = 0; i < 9; i++) {
wxButton *button = new wxButton(this, wxID_ANY, std::string("Refilled") + std::to_string(i), wxDefaultPosition,
wxDefaultSize, 0);
sizer->Add(button, wxALL, 0);
}
Layout();
Thaw();
Refresh();
}
我正在编写一个扫雷小游戏来熟悉 wxWidgets(Windows,wxWidgets 3.1.4)。该应用程序可以很好地处理一个游戏,现在我想添加“新游戏”功能。对于布局,我使用 wxGridSizer
.
我的第一个方法是创建一个新的 wxGridSizer
并在其中添加新字段,然后将当前的 sizer 替换为新的。尽管我想出了如何重用旧的 sizer(并且它通常也是一个更好的解决方案),但我还是很好奇如何正确地更换 sizer。
我能够将我的问题简化为:
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
class MyApp : public wxApp {
public:
virtual bool OnInit();
};
class MyFrame : public wxFrame {
public:
MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size);
private:
void OnExit(wxCommandEvent &event);
void OnRefill(wxCommandEvent &event);
wxDECLARE_EVENT_TABLE();
};
enum { ID_Refill = 1 };
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(ID_Refill, MyFrame::OnRefill)
EVT_MENU(wxID_EXIT, MyFrame::OnExit)
wxEND_EVENT_TABLE() wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit() {
MyFrame *frame = new MyFrame("Hello World", wxPoint(50, 50), wxSize(300, 200));
frame->Show(true);
return true;
}
MyFrame::MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size)
: wxFrame(NULL, wxID_ANY, title, pos, size) {
wxMenu *menu = new wxMenu;
menu->Append(ID_Refill, "&Refill...\tCtrl-R", "Creates new layout");
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append(menu, "&Menu");
SetMenuBar(menuBar);
wxGridSizer *sizer = new wxGridSizer(2, 2, 1, 1);
SetSizer(sizer);
for (auto i = 0; i < 4; i++) {
wxButton *button = new wxButton(this, wxID_ANY, std::to_string(i), wxDefaultPosition, wxDefaultSize, 0);
sizer->Add(button, wxALL, 0);
}
}
void MyFrame::OnExit(wxCommandEvent &) {
Close(true);
}
void MyFrame::OnRefill(wxCommandEvent &) {
Freeze();
GetSizer()->Clear(true);
wxGridSizer *sizer = new wxGridSizer(3, 3, 1, 1);
SetSizer(sizer);
for (auto i = 0; i < 9; i++) {
wxButton *button = new wxButton(this, wxID_ANY, std::string("Refilled") + std::to_string(i), wxDefaultPosition,
wxDefaultSize, 0);
sizer->Add(button, wxALL, 0);
}
sizer->Layout();
Thaw();
Refresh();
}
问题是在 OnRefill
功能之后,应用程序只显示第一个按钮 (Refilled0
),而不显示其余按钮。
在OnRefill
之前:
OnRefill
之后:
我的问题是如何正确替换 MyFrame
的 sizer?根据我从示例和文档中了解到的内容,这应该可行,但我想我遗漏了一些东西。
要替换 sizer,您只需对 MyFrame::OnRefill
方法做一点小改动。
不要调用 sizer->Layout();
,只需调用 Layout();
。我不完全确定为什么为 sizer 调用 Layout 不起作用。
完整的方法如下所示:
void MyFrame::OnRefill(wxCommandEvent &) {
Freeze();
GetSizer()->Clear(true);
wxGridSizer *sizer = new wxGridSizer(3, 3, 1, 1);
SetSizer(sizer);
for (auto i = 0; i < 9; i++) {
wxButton *button = new wxButton(this, wxID_ANY, std::string("Refilled") + std::to_string(i), wxDefaultPosition,
wxDefaultSize, 0);
sizer->Add(button, wxALL, 0);
}
Layout();
Thaw();
Refresh();
}