ホーム < ゲームつくろー! < IKD備忘録

wxWidgets
グリッドウィンドウを触りだけ試してみる

(2010. 5. 4)


 ここまでコントロールを続けてきましたが、いささか飽きが来てしまいました(^-^;。そこで別の物を。今後実用上後必要な物は何かなぁと考えますと、データ(レコード)をどばっと表示するものかなと思いました。リストを並べても可能ですが、それよりは「表」が直接的です。wxWidgetsにはwxGridという表が用意されていますので、今回はこれを使ってみます。



@ wxGridを生成する

 wxGridはコントロールではなくてwxWindowを親に持つウィンドウウィジットです。また、このウィジットを使うにはwxmsw28_adv.lib(デバッグ版はwxmsw28d_adv.lib)をリンクする必要があります。

 wxGridを生成するのは簡単です。フレーム内で以下のようにnewします:

#include "wx/textctrl.h"

TestFrame::TestFrame(const wxString &title, const wxSize &size) :
    wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, size)
{
    // パネル
    wxPanel *panel = new wxPanel(this, wxID_ANY);

// 途中省略

    wxGrid *grid = new wxGrid(panel, -1, wxPoint(0, 0), wxSize(300, 300));
}

 第1引数は親となるウィンドウで上ではパネルを設定しています。これはこれまでのコントロールと同じです。第2引数はウィジットID、これも一緒。残りは位置とウィンドウの幅高で、あ、みんな一緒だ(^-^;。この統一したインターフェイスが秀逸ですねぇ。

 このまま実行してもエラーにはなりませんが、実は正しい表が描画されません。表は行と列の数を指定する必要があります:

grid->CreateGrid(20, 3);

wxGrid::CreateGridメソッドは行数と列数を引数で指定します。これで表が出現します!

お〜Excelライク!これは素晴らしい!!もちろん方向キーでカーソルを動かせますし、行や列の幅をマウスドラッグで変更とかも出来ます。wxGridはウィンドウではありますが生成時に指定した幅高でクリッピングされるので上のようにスクロールバーが出ています。それにしても…たった2行のコードでこれは凄い。

 あとはこの表にデータを追加したり消したりといった操作なんですが、これが色々とあるのは想像に難くありません。上っ面だけ見ていくことにします。



○ 指定の行列に値を入れる

 B4に値を入れる一番簡単な方法はマウスでクリックして手入力ですが、プログラム側から入れたい場合もあります。その時はwxGrid::SetCellValueメソッドを使います:

grid->SetCellValue(3, 1, "Marupeke");

結果はこうなります:

引数は「行番号」、「列番号」の順です。また行列は0基底です。よってB4は(3, 1)となります。お間違え無く〜。



○ リードオンリーにする

 デフォルトで表は読み書きが自由です。でも情報を表示したいだけという場合には上書きされると困ります。セルをリードオンリーにするにはwxGrid::SetReadOnlyメソッドを使います:

// B4をリードオンリーに
grid->SetReadOnly(3, 1, true);

見た目には上の図と同じなのですが、書き込みが出来なくなります。消すこともできません。ただしこれはUI側からの変更をさせないだけで、プログラム側からの変更はリードオンリーにしても普通にできます。



○ セルや文字の色を変更する

 リードオンリーなセルは見た目では区別が尽きません。こういうのは色を変更した方が良いですよね。セルの文字や背景の色を変更するにはwxGrid::SetCellTextColour及びwxGrid::SetCellBackgroundColourを使います:

// B4のテキスト及び背景を変更
grid->SetCellTextColour(3, 1, wxColour(0x404040));
grid->SetCellBackgroundColour(3, 1, wxColour(0xc0a0a0));

これでこうなります:

メソッドの第3引数に色を指定します。注意したいのが、上のように16進数で色指定した場合、色の並びが「GBR」である事です(リトルエンディアンのため)。



○ 列単位でセルの数値入力精度を制限する

 セルの数値のフォーマットを制限することができます。例えば、小数点の精度を指定するにはwxGrid::SetColFormatFloatメソッドを使います:

// A列の浮動小数点精度を制限
grid->SetColFormatFloat(0, 7, 3);

第1引数は列番号、第2引数は表記幅、第3引数は小数点以下の桁数です。なんですが…浮動小数点の整数部を幅以上にしても普通に表記はされます。小数点以下の桁数はうまく整えられます。まぁ、そういう仕様なのかな?

 整数化するにはwxGrid::SetColFormatNumberメソッドを使います:

// C列を整数化
grid->SetColFormatNumber(2);

引数は列番号です。これで整数値に丸められる…はずなのですが、何故だかなりません。まだ実装されていないのかもしれません(^-^;。入力精度はこれからに期待と言った所でしょうか。しばらくは自前で頑張るのが吉かな?



○ ラベルの属性を変更する

 ラベルとは「A」とか左端にある数字の事です。このラベルカラーを変更するにはwxGrid::SetLabelBackgroundColourメソッドを用います。その他ラベル関係の基本的なセッターはこんな感じです:

// ラベル属性を各種変更
grid->SetLabelBackgroundColour(wxColour(0xc0c0c0)); // 背景色変更
grid->SetLabelTextColour(wxColour(0x602030));       // テキスト色変更
grid->SetRowLabelValue(0, "項目");                  // 1行目のラベルを"項目"に
grid->SetColLabelValue(0, "X");                     // 1列目のラベルを"X"に
grid->SetColLabelValue(1, "Y");                     // 2列目のラベルを"Y"に

これを実行するとこういう見た目になります:

これで独自のレコードを表示する時に行列の意味が何か良くわかるようになりますね。



○ ラベルを使わない

 アプリケーションによっては、そもそもラベル自体がいらない場合がります。ラベルを消すというメソッドは無いようなのですが、代わりにラベルの幅や高さを設定するメソッドがあります。これを0にすれば行列のラベルを消せます:

grid->SetColLabelSize(0);  // 列ラベル幅を0に
grid->SetRowLabelSize(0);  // 行ラベル幅を0に

これで入力表のみになります:

あ、上の図は表の基点を(30,30)に変更しています。確かにラベルは無いですよね。



○ 行列の数を変更する

 wxGrid::CreateGridメソッドは初期グリッド数を決めますが、一度決めた後にその数を変更する事はしょっちゅうあります。例えば外部ファイルから情報を取得した時などです。行列の数を変更するにはwxGrid::AppendRowsとAppendColsメソッドを用います。これらのメソッドは現在の行の最下部及び列の右端に追加します。一方、ある行や列の間に挿入したい場合ももちろんあります。その時にはInsertRowsとInsertColsメソッドを用います。

 追加があればもちろん削除も必要で、これにはDeleteRowsとDeleteColsメソッドを用います。実装例は次の通りです:

// 行列を追加、挿入、削除
grid->AppendCols(1);      // 右端に1列追加
grid->AppendRows(10);     // 下端に10行追加
grid->InsertCols(1, 1);   // 1-2列目の間に1列挿入
grid->InsertRows(2, 5);   // 2-3行目の間に5行追加
grid->DeleteCols(4, 1);   // 5列目から1列削除
grid->DeleteRows(20, 20); // 21行目から20行削除

追加した場合、ラベルはその追加行及び列のデフォルト番号になり、他の行列のデフォルトラベルは変更されます。ラベルを変更している行列はもちろんそのままです。削除については該当しない部分まで指定しても大丈夫のようです。


 まぁこの位で十分かなと思います。他にも行や列の幅を決めるメソッドなど色々ありますが、詳しくはマニュアルを御覧下さい。

 さて、これである程度の事はできそうです。この備忘録を書き出したのは、実はwxWidgetsとDirectXを一緒に使いたいという目論見があるからなんです。次からはその辺りを調べていこうと思います。