Windows,Linux,OSXに対応しており、D言語ネイティブ。そんな便利そうなGUIライブラリの入門記事です。
公式のGetting Startedと内容はほぼ同じですが...
#どんなものが作れるか
こんなものが割と簡単に作れます。
この記事ではこれを何も見ずに作れるように記事を書いていきます
#DUBでプロジェクトを作る
今回はDlangManという名前でプロジェクトを作ります。
dub init DlangMan
として、dub.sdlを
name "dlangman"
description "A minimal D application."
copyright "Copyright © 2015, namachan"
authors "namachan"
dependency "dlangui" version="~master"
としてもいいですが、
dub init DlangMan dlangui
とすると自動的にDlangUIの最新版が使えるので楽です。
#動かしてみる
では次に、プロジェクトのディレクトリの中のsourceディレクトリにあるapp.dを次のように書き換えてください
import dlangui;
mixin APP_ENTRY_POINT;
extern(C) int UIAppMain(string[] args)
{
Platform.instance.uiLanguage="en";
Platform.instance.uiTheme="theme_default";
auto window = Platform.instance.createWindow("DlangMan",null);
auto button = new Button;
button.text = "DlangMan";
window.mainWidget = button;
window.show;
return Platform.instance.enterMessageLoop();
}
これを実行すると
このような画面が表示されます。
Platform.instance.uiLanguageは言語の設定をする関数です。一見変数に直接代入しているように見えますが、実際は@property
を付けてあたかも変数のように扱えるようにした関数です。
使用できる言語は、英語、フランス語、ロシア語を指定でき、それぞれen,fr,ruと表記します。
Platform.instance.uiThemeはUIのテーマを指定でき、theme_darkとtheme_defaultがもともとあります。また、Android APIのテーマと同じ形式で記述されたテーマファイルを使うことでテーマをカスタマイズすることが可能です。
Platform.instance.createWindow
の第一引数にはウィンドウのタイトルバーの文字列、第二引数には親ウィンドウを渡します。今回は親ウィンドウが無いのでnullを渡します。
第三引数にはWindowFlagで定義されているフラグを渡すことでフルスクリーン、モーダルウィンドウ、大きさ変更可能なウィンドウに出来ます。それぞれ、WindowFlag.Fullscreen
,WindowFlag.Modal
,WindowFlag.Resizable
です。
今回はwindow.mainWidget
に直接Buttonをセットしていますが、実際にはLayoutにウィジェットやLayoutを追加していき、それをセットすることが多いと思います。
Platform.instance.enterMessageLoop();
でメッセージループに入り、ボタンなどが使用できるようになります。
#Buttonを使ってみる
まずは押すと標準出力にpush
と出力するボタンを作ってみましょう。最初のプログラムに少し付け加えるだけです。
ボタンは、
auto button = new Button
button.text = "push!";
これで、ボタンをヒープに生成して表示する文字をセットします。
引数を取るコンストラクタもあるのですが、まだよく分かりません...。
button.addOnClickListener(delegate(Widget src)
{
"pushed".writeln;
});
でクリックされた際に呼び出されるデリゲートをセットします。
そしてこのbutton
をwindow
のmainWidget
に設定すればボタンを押すと標準出力にpushedと表示されるはずです。
import dlangui;
import std.stdio;
mixin APP_ENTRY_POINT;
extern(C) int UIAppMain(string[] args)
{
Platform.instance.uiLanguage = "en";
Platform.instance.uiTheme = "theme_default";
auto window = Platform.instance.createWindow("push",null);
auto button = new Button;
button.text = "push!";
button.addOnClickListener(delegate(Widget src)
{
"pushed".writeln;
return true;
});
window.mainWidget = button;
window.show;
return Platform.instance.enterMessageLoop();
}
#画像の読み込みと描画
画像の読み込みは簡単です。
dlangui.graphics.image.loadImage
を使うことで、画像をDrawBuf
として読み込めます。DrawBufはJavaで言うBuffredImageみたいなもので、DrawBufに線やフォントやDrawBufを描画したり出来ます。
では早速
import std.stdio;
import dlangui;
mixin APP_ENTRY_POINT;
extern(C) int UIAppMain(string[] args)
{
Platform.instance.uiLanguage = "en";
Platform.instance.uiTheme = "theme_default";
auto window = Platform.instance.createWindow("dman",null);
auto dman = new Dman;
window.mainWidget = dman;
window.show;
return Platform.instance.enterMessageLoop();
}
class Dman : Widget
{
private:
DrawBuf image;
public:
this()
{
image = loadImage("dman.png");
}
override void onDraw(DrawBuf buf)
{
buf.drawImage(0,0,image);
}
}
ここでは、Button
やLayout
などのスーパークラスであるWidget
を継承し、そのonDraw
関数をオーバーライドして描画します。このonDraw関数は、画面の再描画時に呼び出される関数で、渡されるDrawBuf
に描画することでWidget
の見た目が変化します。
再描画を要求する関数はinvalidate()
です。
#フォントの変更
僕の環境では日本語を描画すると豆腐になってしまうのでフォントの変更は必須です。
import std.stdio;
import dlangui;
mixin APP_ENTRY_POINT;
extern(C) int UIAppMain(string[] args)
{
Platform.instance.uiLanguage = "en";
Platform.instance.uiTheme = "theme_default";
auto window = Platform.instance.createWindow("dman",null);
auto button = new JaButton;
window.mainWidget = button;
button.text = "D言語くん可愛い";
window.show;
return Platform.instance.enterMessageLoop();
}
class JaButton : Button
{
private:
FontRef jaFont;
public:
this()
{
jaFont = FontManager.instance.getFont(20,FontWeight.Normal,false,FontFamily.MonoSpace,"JKゴシックM");
}
override FontRef font() @property const
{
return cast(FontRef)jaFont;
}
}
フォント名のところは自分の環境にある日本語フォントに読み替えてください。
ここでは、Button
で日本語を表示できるようにしました。
Button
は@property
の付いたfont
という関数を使ってフォントを取得しています。そのため、このfont
関数をオーバーライドすることで比較的簡単に表示されるフォントを変更することが出来ます。
フォントには、通常のFont
と、FreeTypeを利用したFreeTypeFont
があり、それぞれFontManager
とFreeTypeFontManager
で読み込みます。
DrawBufに文字列を描画する関数は、DrawBuf
にではなく、Font
に用意されてあるので注意してください。
#Layoutについて
僕自身、まだ全然わからないのですが、これが使えないとGUI組めないので解説します。
デフォルトで用意されているLayoutは主に5つあり、
- VerticalLayout
- HorizontalLayout
- TableLayout
- LinerLayout
- FrameLayout
です。
Widget
やLayout
を追加するにはaddChild()
関数を利用します。
###VerticalLayout
名前の通り垂直に並べます
###HorizontalLayout
同じく平行に並べます
###FrameLayout
こうなってしまいます。
これはButtonの大きさとかマージンとか考えずに上に重ねてしまうからです。
###TableLayout
Excelみたいに並べるやつです
また、これらのレイアウト以外にも自作のレイアウトを使うことも出来ます。
###DMLの利用
DML(DlangUI Markup Language)という言語を使ってレイアウトを作ることが出来ます。
import std.stdio;
import dlangui;
mixin APP_ENTRY_POINT;
extern(C) int UIAppMain(string[] args)
{
Platform.instance.uiLanguage = "en";
Platform.instance.uiTheme = "theme_default";
auto window = Platform.instance.createWindow("dman",null);
auto layout = parseML(q{
TableLayout {
colCount: 2
margins: 30;padding: 20
Button {text: "button1"}
Button {text:"button2"}
Button {text:"button3"}
HorizontalLayout {
Button {text:"button4"}
Button {text:"button5"}
}
}
});
window.mainWidget = layout;
window.show;
return Platform.instance.enterMessageLoop();
}
DMLを中括弧を宣言の次の行に書くFreeBSDスタイルで書くとエラーが出ます(経験済み)
#終わりに
大変遅れてしまいました...
当初はD言語くんAdventCalenderのプログラムに関してなにか書こうと思っていたのですが、書くことが無さ過ぎてDlangUIの入門記事に変更しました。