この章では、アプリケーションのメニュー、ステータスバー、ツールバーを説明します。
#include <wx/wx.h>
#include <wx/menu.h>
class Menu : public wxFrame
{
public:
Menu();
void OnQuit(wxCommandEvent &event);
wxMenuBar *menubar;
wxMenu *file;
};
class App : public wxApp
{
public:
virtual bool OnInit();
};
Menu::Menu() : wxFrame(NULL, -1, "Menu")
{
menubar = new wxMenuBar;
file = new wxMenu;
menubar->Append(file, "File");
file->Append(wxID_EXIT, "Quit");
SetMenuBar(menubar);
Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(Menu::OnQuit));
}
void Menu::OnQuit(wxCommandEvent &event)
{
Close(true);
}
IMPLEMENT_APP(App)
bool App::OnInit()
{
Menu *menu = new Menu();
menu->Show();
return true;
}
#include <wx/wx.h>
#include <wx/menu.h>
class SubMenu : public wxFrame
{
public:
SubMenu();
void OnQuit(wxCommandEvent & event);
wxMenuBar *menubar;
wxMenu *file;
wxMenu *imp;
wxMenuItem *quit;
};
class App : public wxApp
{
public:
virtual bool OnInit();
};
SubMenu::SubMenu() : wxFrame(NULL, -1, "SubMenu")
{
menubar = new wxMenuBar;
file = new wxMenu;
file->Append(wxID_NEW, wxT("新規"));
file->Append(wxID_OPEN, wxT("開く"));
file->Append(wxID_SAVE, wxT("保存"));
file->AppendSeparator();
imp = new wxMenu;
imp->Append(-1, wxT("ブックマークをインポート"));
imp->Append(-1, wxT("メールをインポート"));
file->AppendSubMenu(imp, wxT("インポート"));
quit = new wxMenuItem(file, wxID_EXIT, wxT("終了\tCtrl+Q"));
file->Append(quit);
menubar->Append(file, wxT("ファイル"));
SetMenuBar(menubar);
Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(SubMenu::OnQuit));
}
void SubMenu::OnQuit(wxCommandEvent & event)
{
Close(true);
}
IMPLEMENT_APP(App)
bool App::OnInit()
{
SubMenu *submenu = new SubMenu();
submenu->Show();
return true;
}
#include <wx/wx.h>
#include <wx/menu.h>
class PredefinedMenu : public wxFrame
{
public:
PredefinedMenu();
wxMenuBar *menubar;
wxMenu *filemenu;
wxMenu *editmenu;
wxMenu *helpmenu;
};
class App : public wxApp
{
public:
virtual bool OnInit();
};
PredefinedMenu::PredefinedMenu() : wxFrame(NULL, -1, "PredefinedMenu")
{
menubar = new wxMenuBar();
filemenu = new wxMenu();
editmenu = new wxMenu();
helpmenu = new wxMenu();
filemenu->Append(wxID_ABOUT);
filemenu->AppendSeparator();
filemenu->Append(wxID_NEW);
filemenu->Append(wxID_OPEN);
filemenu->Append(wxID_SAVE);
filemenu->AppendSeparator();
filemenu->Append(wxID_SAVEAS);
filemenu->Append(wxID_CLOSE);
filemenu->AppendSeparator();
filemenu->Append(wxID_EXIT);
editmenu->Append(wxID_UNDO);
editmenu->Append(wxID_REDO);
editmenu->AppendSeparator();
editmenu->Append(wxID_COPY);
editmenu->Append(wxID_CUT);
editmenu->Append(wxID_PASTE);
editmenu->Append(wxID_DELETE);
helpmenu->Append(wxID_HELP);
menubar->Append(filemenu, "File");
menubar->Append(editmenu, "Edit");
menubar->Append(helpmenu, "Help");
SetMenuBar(menubar);
}
IMPLEMENT_APP(App)
bool App::OnInit()
{
PredefinedMenu *predefinedmenu = new PredefinedMenu();
predefinedmenu->Show();
return true;
}
#include <wx/wx.h>
#include <wx/menu.h>
class CheckMenu : public wxFrame
{
public:
CheckMenu();
void OnCheck(wxCommandEvent & event);
wxMenuBar *menubar;
wxMenu *filemenu;
wxBoxSizer *hbox;
wxBoxSizer *vbox;
wxStaticText *statictext;
};
class App : public wxApp
{
public:
virtual bool OnInit();
};
CheckMenu::CheckMenu() : wxFrame(NULL, -1, "CheckMenu")
{
menubar = new wxMenuBar();
filemenu = new wxMenu();
filemenu->AppendCheckItem(1001, wxT("チェックメニュー"));
statictext = new wxStaticText(this, -1, wxT("未選択"));
hbox = new wxBoxSizer(wxHORIZONTAL);
hbox->Add(statictext, 1, wxALIGN_CENTER);
vbox = new wxBoxSizer(wxVERTICAL);
vbox->Add(hbox, 1, wxLEFT, 10);
menubar->Append(filemenu, "File");
SetMenuBar(menubar);
SetSizer(vbox);
Bind(wxEVT_COMMAND_MENU_SELECTED, &CheckMenu::OnCheck, this, 1001);
//Connect(1001, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CheckMenu::OnCheck));
}
void CheckMenu::OnCheck(wxCommandEvent & event)
{
if (menubar->IsChecked(1001)) {
statictext->SetLabel(wxT("チェックされました"));
} else {
statictext->SetLabel(wxT("未選択"));
}
}
IMPLEMENT_APP(App)
bool App::OnInit()
{
CheckMenu *checkmenu = new CheckMenu();
checkmenu->Show();
return true;
}
今回は、イベントとイベントハンドラー(そのイベントを処理する関数)を結びつけるために、Connect( ) 関数の代わりに Bind( ) 関数を使ってみました。Bindのほうが、Connectよりも新しい手法です。
#include <wx/wx.h>
class Context : public wxFrame
{
public:
Context();
void OnRightDown(wxCommandEvent & event);
void OnMinimize(wxCommandEvent & event);
void OnQuit(wxCommandEvent & event);
wxMenu * menu;
};
class App : public wxApp
{
public:
virtual bool OnInit();
};
Context::Context() : wxFrame(NULL, 101, "Context")
{
menu = new wxMenu();
menu->Append(1001, "Minimize");
menu->Append(wxID_EXIT);
Connect(101, wxEVT_RIGHT_DOWN, wxCommandEventHandler(Context::OnRightDown));
Bind(wxEVT_MENU, &Context::OnMinimize, this, 1001);
Bind(wxEVT_MENU, &Context::OnQuit, this, wxID_EXIT);
}
void Context::OnRightDown(wxCommandEvent & event)
{
PopupMenu(menu);
}
void Context::OnMinimize(wxCommandEvent & event)
{
Iconize();
}
void Context::OnQuit(wxCommandEvent & event)
{
Close();
}
IMPLEMENT_APP(App)
bool App::OnInit()
{
Context *context = new Context();
context->Show();
return true;
}
右クリックした場合の Bind の方法が分からず、このイベントだけ Connect を使っています。
#include <wx/wx.h>
#include <wx/menu.h>
class StatusBar : public wxFrame
{
public:
StatusBar();
void ShowStatusBar(wxCommandEvent & event);
void ShowWxWidgets(wxCommandEvent & event);
wxMenuBar *menubar;
wxMenu *view;
};
class App : public wxApp
{
public:
virtual bool OnInit();
};
StatusBar::StatusBar() : wxFrame(NULL, -1, "StatusBar")
{
menubar = new wxMenuBar;
view = new wxMenu;
view->AppendCheckItem(1001, "Show StatusBar");
view->AppendCheckItem(1002, "Show wxWidgets");
view->Check(1001, true);
menubar->Append(view, "View");
SetMenuBar(menubar);
CreateStatusBar();
Bind(wxEVT_COMMAND_MENU_SELECTED, &StatusBar::ShowStatusBar, this, 1001);
Bind(wxEVT_COMMAND_MENU_SELECTED, &StatusBar::ShowWxWidgets, this, 1002);
}
void StatusBar::ShowStatusBar(wxCommandEvent & event)
{
if (menubar->IsChecked(1001)) {
GetStatusBar()->Show();
} else {
GetStatusBar()->Hide();
}
}
void StatusBar::ShowWxWidgets(wxCommandEvent & event)
{
if (menubar->IsChecked(1002)) {
SetStatusText("wxWidgets");
} else {
SetStatusText("");
}
}
IMPLEMENT_APP(App)
bool App::OnInit()
{
StatusBar *statusbar = new StatusBar();
statusbar->Show();
return true;
}
次の toolbar.cpp で使われている std::to_string()
という関数は、g++ のバージョン 7 以上が必要です。Mint 18 と Ubuntu 16.04 のデフォルトの g++ は、バージョン 4 か 5 です。ターミナルで次のコマンドを実行して バージョン 9 をインストールしてください。この作業は、Mint 18 と Ubuntu 16.04 以外では必要ありません。
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt update
sudo apt install -y g++-9
コンパイルする時は次のようにします。
g++-9 toolbar.cpp `wx-config --cppflags --libs` -o ToolBar
デフォルトの g++ を使う場合は、今までとおりに次のようにします。
g++ ~~~~.cpp `wx-config -cppflags --libs` -o ~~~~
#include <wx/wx.h>
#include <wx/artprov.h>
class ToolBar : public wxFrame
{
public:
ToolBar();
wxStaticText *text;
wxToolBar *toolbar;
void OnUndo(wxCommandEvent & event);
void OnRedo(wxCommandEvent & event);
void OnQuit(wxCommandEvent & event);
};
class App : public wxApp
{
public:
virtual bool OnInit();
};
ToolBar::ToolBar() : wxFrame(NULL, -1, "ToolBar")
{
wxImage::AddHandler(new wxPNGHandler);
wxBitmap undo = wxArtProvider::GetBitmap(wxART_UNDO);
wxBitmap redo = wxArtProvider::GetBitmap(wxART_REDO);
wxBitmap exit = wxArtProvider::GetBitmap(wxART_QUIT);
toolbar = CreateToolBar();
toolbar->AddTool(wxID_UNDO, "Undo", undo);
toolbar->AddTool(wxID_REDO, "Redo", redo);
toolbar->AddSeparator();
toolbar->AddTool(wxID_EXIT, "Quit", exit);
toolbar->Realize();
toolbar->EnableTool(wxID_REDO, false);
text = new wxStaticText(this,101, "5");
wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
hbox->Add(text, 1, wxALIGN_CENTER);
vbox->Add(hbox, 1, wxALIGN_CENTER);
SetSizer(vbox);
Bind(wxEVT_COMMAND_TOOL_CLICKED, &ToolBar::OnUndo, this, wxID_UNDO);
Bind(wxEVT_COMMAND_TOOL_CLICKED, &ToolBar::OnRedo, this, wxID_REDO);
Bind(wxEVT_COMMAND_TOOL_CLICKED, &ToolBar::OnQuit, this, wxID_EXIT);
}
void ToolBar::OnUndo(wxCommandEvent & event)
{
int num = atoi(text->GetLabel());
num--;
switch (num)
{
case 0:
toolbar->EnableTool(wxID_UNDO, false);
break;
case 4:
toolbar->EnableTool(wxID_REDO, true);
break;
}
text->SetLabel(std::to_string(num));
}
void ToolBar::OnRedo(wxCommandEvent & event)
{
int num = atoi(text->GetLabel());
num++;
switch (num)
{
case 1:
toolbar->EnableTool(wxID_UNDO, true);
break;
case 5:
toolbar->EnableTool(wxID_REDO, false);
break;
}
text->SetLabel(std::to_string(num));
}
void ToolBar::OnQuit(wxCommandEvent & event)
{
Close();
}
IMPLEMENT_APP(App)
bool App::OnInit()
{
ToolBar *toolbar = new ToolBar();
toolbar->Show();
return true;
}
今回は、wxArtProvider で提供されているビットマップイメージを使っています。