読者です 読者をやめる 読者になる 読者になる

Eto.Formsでボタンと1行テキストボックス

テンプレートのHello Worldはラベルを使っていたので、今度は他の基本のコントロールとしてボタンと1行テキストを使ってみます。

前回と同様、Eto Applicationプロジェクトを作成しますが、今回は、MainForm.csを大幅に書き換えてみます。

using System;
using Eto.Forms;
using Eto.Drawing;

namespace EtoSample1
{
    public class MainForm : Form
    {
        TextBox sampleText = new TextBox
        {
            Text = "Not Clicked",
            ReadOnly = true,
            TextColor = Color.FromArgb(0xFF, 0xFF, 0xFF),
            BackgroundColor = Color.FromArgb(0, 0x80, 0x20),
        };
        Button sampleButton;
        int number = 0;

        public MainForm()
        {
            Title = "Sample-1";

            sampleButton = new Button
            {
                Text = "Count",
                TextColor = Color.FromArgb(0, 0, 0),
                BackgroundColor = Color.FromArgb(0xD0, 0xF0, 0xFF),
            };
            sampleButton.Click += (s, e) =>
            {
                number++;
                sampleText.Text = string.Format("{0} clicked", number);
            };

            Content = new StackLayout
            {
                Padding = 10,
                Items =
                {
                    sampleText,
                    sampleButton,
                }
            };

            var quitCommand = new Command {
                MenuText = "Quit",
                Shortcut = Application.Instance.CommonModifier | Keys.Q
            };
            quitCommand.Executed += (sender, e) => Application.Instance.Quit();

            Menu = new MenuBar
            {
                QuitItem = quitCommand,
            };
        }
    }
}

主な変更点は、次のようにまとめられます。

  • コントロールなどを、フィールドとして定義(TextBox, Button, int)
  • コンストラクタで一部フィールドを定義し、イベント処理も設定
  • メニュー関連は大半を削除(※単にコードを短くするためです)

何をしているかは、ソースを見ればだいたい分かると思います。 ボタンをクリックすると、テキストの文字列が(クリック数を表示するように)変わるという素敵なアプリケーションです。

f:id:mokake:20161226124822p:plain

Formクラス

今回は、ClientSizeプロパティの設定がありません。

Eto.Formsのコンテナは通常、サイズ指定がない場合は、内容に基づく最小サイズを自動設定します。 なので、今回のウインドウは小さいんです。

TextBox

TextBoxは、1行テキストです。 複数行入れたい場合は、TextAreaを使います。

定義時に、プロパティは初期設定が可能なので、ここでスタイルや初期文字列を一気に設定しています。 ちなみにColorクラスはEto.Drawing名前空間にありますが、色名定数フィールドはありません。 これとは別に、一般的なコントロールなどの色としてSystemColorクラスもあります(ただしプラットフォームによっては特に意味がない項目もありますが)。

ReadOnlyプロパティは、その名の通り書き換え可否を設定できます。 なお、今回のようにtrueにすると、書き換えできないだけでなく、カーソル(キャレット)も出ません。 マウスでなら部分文字列の選択(やコピー)もできるのですが、カーソルが出ないのでキーで選択できないのは残念。

Button

ボタンです。 今回は、コンストラクタで生成してみました。 イベント設定はフィールド定義内部では不可能なので、sampleButtonの設定を集約してみた次第です。 実際には、スタイルと動作は分割して、スタイルだけを集約した方が妥当かなと思いますが。

イベント設定は、ラムダ式で行っています。 ラムダだと、イベント引数の型を書かないでいいのは楽ですね。 複数の箇所から同じ処理を呼ぶのには使えませんが。

StackLayout

Formクラスの内容は、Contentプロパティですが、ここには1個しか設定できません。 普通は、Contentは何らかのコンテナを設定し、その中に個別のコントロール(やコンテナ)を入れます。

C#インスタンス初期化書式の恩恵で、コードでのGUI生成でもそこそこの可読性はあるように個人的には思います。

StackLayoutはEto.Formsとしては比較的新しいコンテナで、他のGUIライブラリにもある「縦または横に内容を配置していくだけ」のものです。 StackLayoutを2段階の入れ子にすれば、「ヘッダ、中央、フッタ(またはステータスバー)」といった構成も作れます。

ただし、StackLayoutは現状、中身の動的な変更には(GTK#で)弱い印象です。 そういったことが必要なら、TableLayoutやDynamicLayoutを使うのがおすすめです。