ホーム
C/C++チュートリアル
レイアウト
-
GUI プログラミングにおいて、GUI パーツ(GUI 部品)のレイアウト(layout、配置)は大事な事項です。
-
wxWidgets では GUI パーツ(GUI 部品)のことをウィジェット(widget)と呼びます。
そして、ウィジェットはコンテナー(container)と呼ばれるものに配置します。
-
フレームもコンテナーの一つです。フレームには
一つのウィジェットしか配置できません。そしてそのウィジェットはフレーム一杯に
広がります。
-
複数のウィジェットは配置したり、より柔軟に配置するにはパネル(panel)や
サイザー(sizer)と呼ばれるものを使います。
-
なお、コンテナーもウィジェットの一つです。
フレーム
-
フレーム(Frame)は、ウィンドウのことです。フレームには一つのウィジェットしか配置できません。またフレームに配置されたウィジェットは、フレーム一杯に広がることになります。
frame.cpp3>
#include <wx/wx.h>
class Frame : public wxFrame
{
public:
Frame();
};
class App : public wxApp
{
public:
virtual bool OnInit();
};
Frame::Frame() : wxFrame(NULL, -1, "Frame")
{
wxButton *button = new wxButton(this, -1, "Button");
Center();
}
IMPLEMENT_APP(App)
bool App::OnInit()
{
Frame *frame = new Frame();
frame->Show();
return true;
}
実行結果
コード説明
- wxButton *button = new wxButton(this, -1, "Button");
newキーワードでwxButtonクラスのインスタンスを作り、
そのアドレスを *button ポインターに代入しています。
引数は次のとおりです。
- 第1引数に所属するフレーム(ウィンドウ)を指定します
- 第2引数にウィジェットを区別するための一意の整数を指定します。
-1もしくはwxID_ANYとすると一意の整数が得られます
- 第3引数にボタンに表される文字列を指定します
- Center();
この関数でフレームをディスプレイの中央に表示します。
パネル
-
パネル(panel)というコンテナーを使うと複数のウィジェットを配置することができます。
-
パネルに配置されるウィジェットの位置は、絶対的な位置を指定します。
-
パネルは通常、目に見えませんが、色をつけると見えるようになります。
panel.cpp
#include <wx/wx.h>
class Panel : public wxFrame
{
public:
Panel();
};
class App : public wxApp
{
public:
virtual bool OnInit();
};
Panel::Panel() : wxFrame(NULL, -1, "Panel")
{
wxPanel *panel = new wxPanel(this);
new wxButton(panel, -1, "Button 1", wxPoint(20, 20));
new wxButton(panel, -1, "Button 2", wxPoint(60, 60));
new wxButton(panel, -1, "Button 3", wxPoint(100, 100));
}
IMPLEMENT_APP(App)
bool App::OnInit()
{
Panel *panel = new Panel();
panel->Show();
return true;
}
実行結果
コード説明
- wxPanel *panel = new wxPanel(this);
new wxPanelでパネルを作り、そのアドレスを *panel ポインタに代入しています。
引数にはパネルが配置されるウィンドウを指定します。
ここで this は、フレーム(ウィンドウ)を指し示しています。
- new wxButton(panel, -1, "Button 1", wxPoint(20, 20));
new wxButtonでボタン(wxButton)のインスタンスを作っています。
- 第1引数に配置するコンテナーを指定します
- 第2引数にIDを指定します
- 第3引数にボタンに表示される文字列を指定します
- 第4引数にパネルに配置する位置をwxPoint( )関数で指定します。
- 第1引数は横位置です
- 第2引数は縦位置です
ボックスサイザー
ボックスサイザー(BoxSizer)というコンテナーを使うと、
ウィンドウの大きさに合わせて、
ウィジェットの配置位置を調整する柔軟なレイアウトができるようになります。
boxsizer.cpp
#include <wx/wx.h>
class BoxSizer : public wxFrame
{
public:
BoxSizer();
};
class App : public wxApp
{
public:
virtual bool OnInit();
};
BoxSizer::BoxSizer() : wxFrame(NULL, -1, "BoxSizer")
{
wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
SetSizer(vbox);
wxButton *button = new wxButton(this, -1, "Button");
hbox->Add(button, 0, wxALIGN_CENTER);
vbox->Add(hbox, 1, wxALIGN_CENTER);
}
IMPLEMENT_APP(App)
bool App::OnInit()
{
BoxSizer *boxsizer = new BoxSizer();
boxsizer->Show();
return true;
}
コード説明
- wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL);
ボックスサイザーを作っています。引数に wxHORIZONTAL を指定すると、
横配置のボックスサイザーが作れます。
- wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
引数に wxVERTICAL を指定すると、縦配置のボックスサイザーが作れます。
- SetSizer(vbox);
フレームのサイザーとして 縦配置の vbox を設定しています。
- hbox->Add(button, 0, wxALIGN_CENTER);
ボックスサイザーのAdd( )関数で横配置のボックスにボタンを配置しています。
- 第1引数にボックスに配置するウィジェットを指定します
- 第2引数に横方向に拡大する場合は 1を、拡大しない場合は 0 を指定します。
今回の場合は、どちらでも同じですが、第3引数を指定するために、
第2引数も指定しなければなりません。
- 第3引数に wxALIGN_CENTER を指定すると横方向の中央に表示されます
- vbox->Add(hbox, 1, wxALIGN_CENTER);
vbox->Add( )関数で縦配置のボックスにボタンを配置しています。
- 第1引数にボックスに配置するウィジェットを指定します
- 第2引数に縦方向に拡大する場合は 1を、拡大しない場合は 0 を指定します。
今回の場合は、縦方向に拡大させます
- 第3引数に wxALIGN_CENTER を指定すると縦方向の中央に表示されます
- macOS以外のOSではボタンは縦方向にも拡大しますので、まず横ボックスに配置
して、それから縦ボックスに配置する必要があります。
buttons.cpp
#include <wx/wx.h>
class Buttons : public wxFrame
{
public:
Buttons();
};
class App : public wxApp
{
public:
virtual bool OnInit();
};
Buttons::Buttons() : wxFrame(NULL, -1, "Buttons")
{
wxPanel *panel = new wxPanel(this, -1);
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL);
wxTextCtrl *textctrl = new wxTextCtrl(panel, -1, "", wxPoint(-1, -1), wxSize(-1, -1), wxTE_MULTILINE);
wxButton *ok = new wxButton(panel, -1, "Ok");
wxButton *cancel = new wxButton(panel, -1, "Cancel");
vbox->Add(textctrl, 1, wxEXPAND | wxALL, 5);
hbox->Add(ok);
hbox->Add(cancel, 0, wxLEFT, 5);
vbox->Add(hbox, 0, wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, 5);
panel->SetSizer(vbox);
}
IMPLEMENT_APP(App)
bool App::OnInit()
{
Buttons *buttons = new Buttons();
buttons->Show();
return true;
}
コード説明
- wxPanel *panel = new wxPanel(this, -1);
パネルコンテナーを this(フレーム)に配置します。使う予定がなければ
ID(-1)を省略することもできます。
- wxTextCtrl *textctrl = new wxTextCtrl(panel, -1, "",
wxPoint(-1, -1), wxSize(-1, -1), wxTE_MULTILINE);
ユーザーが文字を入力できるテキストコントロールを作っています。
- 第1引数でパネルに配置することを指定しています
- 第2引数にIDを指定します。次の引数を指定するために省略することはできません
- 第3引数にテキストコントロール内表示される文字列を指定します。
何も表示させたくなければ ""(空文字)を指定します
- 第4引数に配置する位置を指定します。wxPoint(-1, -1)とすると
デフォルトの位置になります
- 第5引数にテキストコントロールの大きさを指定します。wxSize(-1, -1)
とすると、デフォルトの大きさになります。
- 第6引数に wxTE_MULTLINE を指定すると、複数行入力できる
テキストコントロールになります。
第6引数を指定しなかった場合は、1行だけ入力できるテキストコントロールになります
- vbox->Add(textctrl, 1, wxEXPAND | wxALL, 5);
vbox(縦ボックス)にテキストコントロールを配置しています。
縦ボックスに複数のウィジェットを配置する場合は、上から順番に配置されていきます。
- 第1引数に配置するウィジェットを指定します
- 第2引数に1を指定すると縦方向に拡大します。0を指定すると拡大しません
- 第3引数にwxEXPANDを指定すると、そのボックスの方向と違う方向も
拡大します。この場合は横方向にも拡大します
第3引数は | でつなぐことによって複数指定できます。
wxALLはすべての辺という意味になります
- 第4引数に第3引数で指定した辺に作る空白のサイズを指定します
- hbox->Add(ok);
hbox(横ボックス)に OK ボタンを配置しています。
- hbox->Add(cancel, 0, wxLEFT, 5);
hbox(横ボックス)に Cancel ボタンを配置しています。
横ボックスに複数配置する場合は左から配置されていきます。
- 第1引数にボックスに配置するウィジェットを指定します
- 第2引数に横方向に拡大する場合には 1 を、拡大しない場合は 0 を指定します
- 第3引数に辺を指定します。この場合では左辺を指定しています
- 第4引数に第3引数で指定した辺に作る空白のサイズを指定します
- vbox->Add(hbox, 0, wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, 5);
vbox(縦ボックス)にhbox(横ボックス)を配置しています。
テキストコントロールの下に配置されます。
- 第1引数にボックスに配置するウィジェットを指定します。
ボックスもウィジェットです
- 第2引数にボックスと同じ方向に拡大するかどうかを指定します。1 で拡大、0
で拡大しません
- 第3引数は | でつなげて複数の値を指定できます
- wxALIGN_RIGHTで右づめで配置します
- wxRIGHTで右辺を指定しています
- wxBOTTOMで下辺を指定します
- 第4引数には、第3引数で指定した辺に設定する空白のサイズを指定します
- panel->SetSizer(vbox);
パネルにvbox(縦ボックス)を設定しています。
application.cpp
#include <wx/wx.h>
class Application : public wxFrame
{
public:
Application();
};
class App : public wxApp
{
public:
virtual bool OnInit();
};
Application::Application() : wxFrame(NULL, -1, "Application", wxPoint(-1, -1), wxSize(450, 400))
{
wxPanel *panel = new wxPanel(this, -1);
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *hbox1 = new wxBoxSizer(wxHORIZONTAL);
wxStaticText *st1 = new wxStaticText(panel, -1, "StaticText");
hbox1->Add(st1, 0, wxRIGHT, 8);
wxTextCtrl *tc = new wxTextCtrl(panel, -1);
hbox1->Add(tc, 1);
vbox->Add(hbox1, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 10);
vbox->Add(-1, 10);
wxBoxSizer *hbox2 = new wxBoxSizer(wxHORIZONTAL);
wxStaticText *st2 = new wxStaticText(panel, -1, "StaticText");
hbox2->Add(st2, 0);
vbox->Add(hbox2, 0, wxLEFT | wxTOP, 10);
vbox->Add(-1, 10);
wxBoxSizer *hbox3 = new wxBoxSizer(wxHORIZONTAL);
wxTextCtrl *tc2 = new wxTextCtrl(panel, -1, "", wxPoint(-1, -1), wxSize(-1, -1), wxTE_MULTILINE);
hbox3->Add(tc2, 1, wxEXPAND);
vbox->Add(hbox3, 1, wxLEFT | wxRIGHT | wxEXPAND, 10);
vbox->Add(-1, 25);
wxBoxSizer *hbox4 = new wxBoxSizer(wxHORIZONTAL);
wxCheckBox *cb1 = new wxCheckBox(panel, -1, "CheckBox");
hbox4->Add(cb1);
wxCheckBox *cb2 = new wxCheckBox(panel, -1, "CheckBox");
hbox4->Add(cb2, 0, wxLEFT, 10);
wxCheckBox *cb3 = new wxCheckBox(panel, -1, "CheckBox");
hbox4->Add(cb3, 0, wxLEFT, 10);
vbox->Add(hbox4, 0, wxLEFT, 10);
vbox->Add(-1, 25);
wxBoxSizer *hbox5 = new wxBoxSizer(wxHORIZONTAL);
wxButton *btn1 = new wxButton(panel, -1, "Button");
hbox5->Add(btn1, 0);
wxButton *btn2 = new wxButton(panel, -1, "Button");
hbox5->Add(btn2, 0, wxLEFT | wxBOTTOM, 5);
vbox->Add(hbox5, 0, wxALIGN_RIGHT | wxRIGHT, 10);
panel->SetSizer(vbox);
}
IMPLEMENT_APP(App)
bool App::OnInit()
{
Application *application = new Application();
application->Show();
return true;
}
実行結果
コード説明
- Application::Application() : wxFrame(NULL, -1, "Application",
wxPoint(-1, -1), wxSize(450, 400))
クラスのコンストラクは、: コロンに続けてメンバ変数やスーパークラスを
初期化することができます。wxFrame(フレーム、ウィンドウ)には次の引数を渡せます。
- 第1引数に所属するウィンドウを指定します。所属するウィンドウがなければ
NULL を指定します
- 第2引数に ID を指定します。-1 か wxID_ANY を指定すると一意の整数が
取得できます
- 第3引数にウィンドウのタイトルを文字列で指定します
- 第4引数にフレーム(ウィンドウ)の配置位置を指定します。
wxPoint(-1, -1)とすると、デフォルトの位置を指定したことになります
- 第5引数にフレーム(ウィンドウ)の大きさを指定します。
- wxSizeの第1引数に横のサイズ(大きさ)を指定します
- wxSizeの第2引数に縦のサイズ(大きさ)を指定します
- wxStaticText *st1 = new wxStaticText(panel, -1, "StaticText");
wxStaticTextは、ユーザーが編集できない文字列です。
- 第1引数に所属するウィンドウを指定します。パネルもウィンドウ扱いになります
- 第2引数に一意の ID を指定します
- 第3引数に表示する文字列を指定します
- wxTextCtrl *tc = new wxTextCtrl(panel, -1);
テキストコロントロールに wxTE_MULTILNE を指定しなければ、
文字列を一行だけ入力できるテキストコントロールになります。
- vbox->Add(-1, 10);
このコードで、vbox(縦ボックス)に横サイズは未指定で、縦サイズは10ピクセルの
空白を追加できます。
フレックスグリッドサイザー
flexgridsizer.cpp
#include <wx/wx.h>
class FlexGridSizer : public wxFrame
{
public:
FlexGridSizer();
};
class App : public wxApp
{
public:
virtual bool OnInit();
};
FlexGridSizer::FlexGridSizer() : wxFrame(NULL, -1, "FlexGridSizer")
{
wxPanel *panel = new wxPanel(this, -1);
wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL);
wxFlexGridSizer *fgs = new wxFlexGridSizer(3, 2, 9, 25);
wxStaticText *title = new wxStaticText(panel, -1, "Title");
wxStaticText *author = new wxStaticText(panel, -1, "Authjor");
wxStaticText *review = new wxStaticText(panel, -1, "Review");
wxTextCtrl *tc1 = new wxTextCtrl(panel, -1);
wxTextCtrl *tc2 = new wxTextCtrl(panel, -1);
wxTextCtrl *tc3 = new wxTextCtrl(panel, -1, "", wxPoint(-1, -1), wxSize(-1, -1), wxTE_MULTILINE);
fgs->Add(title);
fgs->Add(tc1, 1, wxEXPAND);
fgs->Add(author);
fgs->Add(tc2, 1, wxEXPAND);
fgs->Add(review, 1, wxEXPAND);
fgs->Add(tc3, 1, wxEXPAND);
fgs->AddGrowableCol(1, 1);
fgs->AddGrowableRow(2, 1);
hbox->Add(fgs, 1, wxALL | wxEXPAND, 15);
panel->SetSizer(hbox);
}
IMPLEMENT_APP(App)
bool App::OnInit()
{
FlexGridSizer *fgs = new FlexGridSizer();
fgs->Show();
return true;
}
実行結果
コード説明
- wxFlexGridSizer *fgs = new wxFlexGridSizer(3, 2, 9, 25);
フレックスグリッドサイザーはウィジェットを格子状(表)に配置するコンテナーです。
- 第1引数に表の行数(縦の数)を指定します
- 第2引数に表の列数(横の数)を指定します
- 第3引数にフレックスグリッドサイザーの中に配置されるウィジェット同士の
縦の空白を指定します
- 第4引数にフレックスグリッドサイザーの中に配置されるウィジェット同士の
横の空白を指定します
- fgs->Add(title);
フレックスグリッドサイザーに引数で指定したウィジェットを配置しています。
フレックスグリッドサイザーへの配置は、左上から始まり、次に右横へ、
その行が埋まれば下の行の左に移動します。
- fgs->Add(tc1, 1, wxEXPAND);
第2引数に 1、そして第2引数に wxEXPAND の両方を指定することによって、
後ほど説明する設定次第で、その格子(cell、セル)
のウィジェットは拡大することになります。
- fgs->AddGrowableCol(1, 1);
指定した格子(cell、セル)が横方向に拡大するかどうかを設定します。
- 第1引数に列番号を指定します。列番号は 0 から始まりますので、
1 は2番目の列になります
- 第2引数に 1 を指定すると、その格子(cell、セル)は横方向に拡大します。
0 を指定した場合は拡大しません
- fgs->AddGrowableRow(2, 1);
指定した格子(cell、セル)が縦方向に拡大するかどうかを設定します。
- 第1引数に行番号を指定します。行番号は 0 から始まりますので、
2 は3番目の行になります
- 第2引数に 1 を設定すると、その格子(cell、セル)は縦方向に拡大します。
0 を指定した場合は拡大しません
Posted: Nov. 25, 2019
Update: Dec. 27, 2019