DlangUIプロジェクトについてお話ししたいと思います。 彼が誰かに役立つことを願っています。
KDPVでDlangIDEのスクリーンショット-DlangUIで書かれたアプリケーション。
機能:
- クロスプラットフォーム-Windows、Linux、Mac OSXでサポートされています。 他のプラットフォームへの移植の容易さ
- Dで記述-拡張可能
- レイアウトを使用してUI要素を配置する
- 画面解像度に応じたアプリケーションのフォントとアイコンのスケーリング
- Unicodeサポート
- 国際化-UIを複数の言語に翻訳するためのサポート
- OpenGLによるハードウェアアクセラレーション(オプション)
- OpenGLシーンの上にウィジェットを描画する機能(たとえば、ゲームのUI用)
- 小さい実行可能ファイルサイズ
- インターフェイスの外観はテーマを使用して設定されます(2つの標準テーマ-明るい部分と暗い部分)
- 実行可能ファイルへのリソースの埋め込み
- Boost License 1.0の下でライセンスされたオープンソース
さらにいくつかのスクリーンショット
DlangUIデモ-例1
DlangUIデモ-テトリス
なぜ別のGUIライブラリが必要なのですか?
Dには多くのGUIライブラリがあります。 完全なリストはwiki.dlang.orgにあります
バインディングがGTK、Qt、wxWidgets、FLTK、さらにはJavaからD(DWT)へのSWTポート向けである場合でも、多くの依存関係があるため、ウィジェットのセットを拡張して外観を変更することは困難です。
ネイティブ、D、DFL、およびDGUIで記述-Windowsでのみ動作します。
したがって、独自の自転車GUIを記述することは、それほど愚かな仕事ではありません。
Hello、Worldを始めよう
DlangUIでアプリケーションをビルドして実行するには、Dコンパイラー( dmdなど )とDUB(ビルドツールと依存関係マネージャー)が必要です。 まだダウンロードしていない場合は、インストールしてください。
プロジェクトのディレクトリを作成し、DUBのプロジェクトファイルを作成します-dub.json
{ "name": "helloworld", "targetPath": "bin", "targetName": "helloworld", "targetType": "executable", "dependencies": { "dlangui": "~master", } }
また、srcサブディレクトリで、次の内容のsrc / helloworld.dファイルを作成します。
module app; // dlangui import dlangui; // main WinMain mixin APP_ENTRY_POINT; // DlangUI - main extern (C) int UIAppMain(string[] args) { // Window window = Platform.instance.createWindow("DlangUI example - HelloWorld", null); // window.mainWidget = (new Button()).text("Hello, world!"d).margins(Rect(20,20,20,20)); // window.show(); // return Platform.instance.enterMessageLoop(); }
新しいDUBプロジェクトを作成する簡単な方法は、dub initを使用することです
新しいDUBプロジェクトを作成するより便利な方法があります。 コマンドを使用する
DUBは、指定された名前、dub.json、.gitignoreおよびsource / app.dでディレクトリを作成します
dub.jsonの初期コンテンツ:
ここにdlangui依存関係を追加するだけです
app.dをhelloworldに置き換えます
新しいDUBプロジェクトを作成するより便利な方法があります。 コマンドを使用する
dub init helloworld
DUBは、指定された名前、dub.json、.gitignoreおよびsource / app.dでディレクトリを作成します
dub.jsonの初期コンテンツ:
{ "name": "helloworld", "description": "A minimal D application.", "copyright": "Copyright © 2015, username", "authors": ["username"], "dependencies": { } }
ここにdlangui依存関係を追加するだけです
"dependencies": { "dlangui": "~master", }
app.dをhelloworldに置き換えます
これで、アプリケーションを実行できます。 コマンドプロンプトで、dub.jsonを含むプロジェクトディレクトリで次のコマンドを実行します。
dub run
コンパイルに成功すると、アプリケーションはすぐに起動します。 単一ボタンのウィンドウ:
dlangui(ほとんどすべてのexample1ウィジェットとテトリスゲームのデモ)の例も見ることができます。
dub fetch dlangui dub run dlangui:example1 dub run dlangui:tetris
別のアプリケーションはDlangIDEです。
dub fetch dlangide dub run dlangide
ウィジェットとレイアウト
アプリケーションを複雑にしましょう。 いくつかのウィジェットを追加します。
単純なウィジェットを使用します。
- TextWidget-テキスト
- ボタン-テキスト付きボタン
- ImageButton-写真付きのボタン
- ImageTextButton-画像とテキストのあるボタン
- CheckBox-名前からクリア
- RadioButton-名前から削除
- ImageWidget-画像
- EditLine-単一行エディター
- ComboBox-combobox-ドロップダウンリストから項目を選択します
シンプルなテキストボタンを作成する例:
auto btn = new Button("btn1", "Button 1"d);
ここで、「btn1」はウィジェットの識別子で、通常は親ウィジェットで検索したり、共通のイベントハンドラでウィジェットを区別したりするために使用されます。
「ボタン1」d-ボタンのテキスト。 dのサフィックスはutf32-dstringであることに注意してください。 通常、DlangUIウィジェットデザイナーでは、テキスト自体をutf32 dstringなどのテキストとして転送したり、通常の文字列としての文字列リソースの識別子を使用して、インターフェイスを複数の言語に翻訳したりできます。
ウィジェットには、ネストされたウィジェットを含めることができます。
レイアウト-他のウィジェットを整列させるためのコンテナウィジェット。 Android UIで使用されるものと同様:
- VerticalLayout-ネストされたウィジェットを垂直に配置します
- HorizontalLayout-ネストされたウィジェットを垂直に配置します
- TableLayout-テーブルのように、いくつかの列にネストされたウィジェットを配置します
VerticalLayoutを作成し、それにいくつかのボタンを追加します。
auto vlayout = new VerticalLayout(); // vlayout.addChild(new RadioButton("radio1", "Radio Button 1"d)); vlayout.addChild(new RadioButton("radio2", "Radio Button 2"d));
例を修正してください-複雑な構造を持つフォームを作成してください。
module app; // dlangui import dlangui; // main WinMain mixin APP_ENTRY_POINT; // DlangUI - main extern (C) int UIAppMain(string[] args) { // Window window = Platform.instance.createWindow("DlangUI example - HelloWorld", null); // - , auto mainWidget = new VerticalLayout(); mainWidget.addChild(new TextWidget(null, " HorizontalLayout:"d)); // auto hlayout = new HorizontalLayout(); // hlayout.addChild(new Button("btn1", " 1"d)); hlayout.addChild(new Button("btn2", " 2"d)); hlayout.addChild(new Button("btn3", " 3"d)); hlayout.addChild(new CheckBox("btn4", " CheckBox"d)); mainWidget.addChild(hlayout); mainWidget.addChild(new TextWidget(null, " VerticalLayout:"d)); // auto vlayout = new VerticalLayout(); // vlayout.addChild(new RadioButton("radio1", "Radio Button 1"d)); vlayout.addChild(new RadioButton("radio2", "Radio Button 2"d)); vlayout.addChild(new RadioButton("radio3", "Radio Button 3"d)); mainWidget.addChild(vlayout); mainWidget.addChild(new TextWidget(null, " TableLayout - 2 :"d)); // auto tlayout = new TableLayout(); // / tlayout.colCount = 2; tlayout.addChild(new TextWidget(null, " "d)); tlayout.addChild(new EditLine("edit1", "- "d)); tlayout.addChild(new TextWidget(null, "ComboBox"d)); tlayout.addChild((new ComboBox("combo1", [" 1"d, " 2"d, " 3"d])).selectedItemIndex(0)); tlayout.addChild(new TextWidget(null, " RadioButton"d)); // Layout Layout: auto radiogroup = new VerticalLayout(); radiogroup.addChild(new RadioButton("rb1", " 1"d)); radiogroup.addChild(new RadioButton("rb2", " 2"d)); radiogroup.addChild(new RadioButton("rb3", " 3"d)); tlayout.addChild(radiogroup); tlayout.addChild(new TextWidget(null, " ImageTextButton"d)); tlayout.addChild(new ImageTextButton("btn_ok", "dialog-ok-apply", " "d)); mainWidget.addChild(tlayout); // window.mainWidget = mainWidget; // window.show(); // return Platform.instance.enterMessageLoop(); }
取得したものは次のとおりです。
ウィジェットからの信号処理(イベント)
例としてonClick信号を使用した信号処理を検討します
ボタンを押すためのハンドラーを追加します-インターフェースのテーマを切り替えさせます。
この例では、コードをRadioButtonからVerticalLayoutに変更します。
mainWidget.addChild(new TextWidget(null, " :"d)); auto vlayout = new VerticalLayout(); // addChild() , , // . vlayout.addChild(new RadioButton("radio1", ""d)).checked(true).onClickListener = delegate(Widget src) { platform.instance.uiTheme = "theme_default"; return true; }; vlayout.addChild(new RadioButton("radio2", ""d)).onClickListener = delegate(Widget src) { platform.instance.uiTheme = "theme_dark"; return true; }; mainWidget.addChild(vlayout);
起こったことは次のとおりです。
説明:
onClickListener-任意のウィジェットで使用可能なシグナル。以下にその説明を示します。
/// interface - slot for onClick interface OnClickHandler { bool onClick(Widget source); } //..... class Widget { //... Signal!OnClickHandler onClickListener; //... }
ハンドラーは、適切なタイプのデリゲートにすることができます。
イベントハンドラーはさまざまな方法で接続できます。
OnClickハンドラーの例-通常のデリゲート
auto button1 = new Button("btn1", " 1"d); button1.onClickListener = delegate(Widget src) { window.showMessageBox(UIString(" onClick"d), UIString("\ndelegate"d)); return true; };
OnClickの例-クラスメソッド
class MyOnClickHandler1 { bool onButtonClick(Widget src) { src.window.showMessageBox(UIString(" onClick"d), UIString(" MyOnClickHandler1.onClick\n id="d ~ to!dstring(src.id))); return true; } } auto memberFunctionHandler = new MyOnClickHandler1(); auto button2 = new Button("btn2", " 2"d); button2.onClickListener = &memberFunctionHandler.onButtonClick; hlayout.addChild(button2);
OnClickの例-信号を定義するために使用されるインターフェースを定義するクラス
// onClick - , class MyOnClickHandler2 : OnClickHandler { override bool onClick(Widget src) { src.window.showMessageBox(UIString(" onClick"d), UIString(" MyOnClickHandler2.onClick\n id="d ~ to!dstring(src.id))); return true; } } auto interfaceHandler = new MyOnClickHandler2(); auto button4 = new Button("btn4", " 4"d); button2.onClickListener = interfaceHandler; // onClick OnClickHandler
Widgetクラスからの他の有用なシグナル:
- onCheckChangeListener-チェック状態が変更されます(たとえば、CheckBox、RadioButton)
- onFocusChangeListener-このウィジェットのフォーカス状態が変更されました
- onKeyListener-キーボードからのイベントの傍受
- onMouseListener-マウスイベントのインターセプト
一般的に使用されるウィジェットのプロパティ
- マージン-隣接するウィジェットまたはコンテナの境界線からインデントします(ウィジェットの背景はマージンによってインデントされます)
- パディング-ウィジェットの境界から内部要素へのインデント
- backgroundColor-背景色(32ビットuint、0xAARRGGBB)
- backgroundImageId-背景画像-リソースID
- textColor-テキストの色(32ビットuint、0xAARRGGBB)
- fontSize-フォントサイズ
これらおよび他の多くのプロパティは、直接設定するか、スタイルの形式(ファイル-テーマで定義)で設定できます。
styleIdプロパティを使用してスタイルを割り当てることができます。 たとえば、選択したインターフェイステーマのヘッダーのスタイルを変更します。
mainWidget.addChild(new TextWidget(null, " :"d)).styleId("POPUP_MENU");
例:メインウィジェットにパディングを追加し、半透明の黄色の背景にします。
// 10 , 15 mainWidget.margins(Rect(10, 10, 10, 10)).padding(Rect(15, 15, 15, 15)); mainWidget.backgroundColor(0xC0FFFF00); //
TableLayoutには、背景画像「btn_default.png」を割り当てます。 リソースIDは、拡張子なしのファイル名です。 .9.png拡張子はnine-patchを表します。これはAndroidのようにスケーラブルな画像です。
また、パディング-ネストされたウィジェットのインデントも追加します。
tlayout.backgroundImageId("btn_default"); // - btn_default.9.png tlayout.padding(Rect(5, 5, 5, 5)); // - 5
TableLayoutのTextWidgetヘッダーで、フォントサイズと色を変更します。
tlayout.backgroundImageId("btn_default"); // - btn_default.9.png tlayout.padding(Rect(5, 5, 5, 5)); // - 5
起こったことは次のとおりです。
現在のhelloworld.dコード:
module app; // dlangui import dlangui; // main WinMain mixin APP_ENTRY_POINT; // DlangUI - main extern (C) int UIAppMain(string[] args) { // , - 800x600 Window window = Platform.instance.createWindow("DlangUI example - HelloWorld", null, WindowFlag.Resizable, 600, 400); // - , auto mainWidget = new VerticalLayout(); // 10 , 15 mainWidget.margins(Rect(10, 10, 10, 10)).padding(Rect(15, 15, 15, 15)); mainWidget.backgroundColor(0xC0FFFF00); // mainWidget.addChild(new TextWidget(null, " HorizontalLayout:"d)); // auto hlayout = new HorizontalLayout(); // // onClick - auto button1 = new Button("btn1", " 1"d); button1.onClickListener = delegate(Widget src) { window.showMessageBox(UIString(" onClick"d), UIString("\ndelegate"d)); return true; }; hlayout.addChild(button1); // onClick - class MyOnClickHandler1 { bool onButtonClick(Widget src) { src.window.showMessageBox(UIString(" onClick"d), UIString(" MyOnClickHandler1.onClick\n id="d ~ to!dstring(src.id))); return true; } } auto memberFunctionHandler = new MyOnClickHandler1(); auto button2 = new Button("btn2", " 2"d); button2.onClickListener = &memberFunctionHandler.onButtonClick; hlayout.addChild(button2); // hlayout.addChild(new Button("btn3", " 3"d)).onClickListener = &memberFunctionHandler.onButtonClick; // onClick - , class MyOnClickHandler2 : OnClickHandler { override bool onClick(Widget src) { src.window.showMessageBox(UIString(" onClick"d), UIString(" MyOnClickHandler2.onClick\n id="d ~ to!dstring(src.id))); return true; } } auto interfaceHandler = new MyOnClickHandler2(); auto button4 = new Button("btn4", " 4"d); button2.onClickListener = interfaceHandler; // onClick OnClickHandler hlayout.addChild(button4); mainWidget.addChild(hlayout); mainWidget.addChild(new TextWidget(null, " :"d)).styleId("POPUP_MENU"); auto vlayout = new VerticalLayout(); vlayout.addChild(new RadioButton("radio1", ""d)).checked(true).onClickListener = delegate(Widget src) { platform.instance.uiTheme = "theme_default"; return true; }; vlayout.addChild(new RadioButton("radio2", ""d)).onClickListener = delegate(Widget src) { platform.instance.uiTheme = "theme_dark"; return true; }; mainWidget.addChild(vlayout); // , mainWidget.addChild(new TextWidget(null, " TableLayout - 2 :"d)).textColor(0xC00000).fontSize(26).alignment(Align.Right); auto tlayout = new TableLayout(); // / tlayout.backgroundImageId("btn_default"); // - btn_default.9.png tlayout.padding(Rect(5, 5, 5, 5)); // - 5 tlayout.colCount = 2; tlayout.addChild(new TextWidget(null, " "d)); tlayout.addChild(new EditLine("edit1", "- "d)); tlayout.addChild(new TextWidget(null, "ComboBox"d)); tlayout.addChild((new ComboBox("combo1", [" 1"d, " 2"d, " 3"d])).selectedItemIndex(0)); tlayout.addChild(new TextWidget(null, " RadioButton"d)); // Layout Layout: auto radiogroup = new VerticalLayout(); radiogroup.addChild(new RadioButton("rb1", " 1"d)); radiogroup.addChild(new RadioButton("rb2", " 2"d)); radiogroup.addChild(new RadioButton("rb3", " 3"d)); tlayout.addChild(radiogroup); tlayout.addChild(new TextWidget(null, " ImageTextButton"d)); tlayout.addChild(new ImageTextButton("btn_ok", "dialog-ok-apply", " "d)); mainWidget.addChild(tlayout); // window.mainWidget = mainWidget; // window.show(); // return Platform.instance.enterMessageLoop(); }
Ubuntuで実行されている同じプログラム:ウィンドウフレームとフォントのみが異なります。
Windowsのdmd2によってビルドされたhelloworld.exeのサイズ(dub build --build = release)は1.4Mbで、そのうち200Kがリソースを占有します。
libfreetype-6.dll(700K)およびzlib1.dll(84K)が存在する場合-DUBは自動的にbinディレクトリにコピーされます-FreeTypeを使用してフォントをレンダリングします。それ以外の場合-win32 API。
dmd-4Mbを使用してUbuntu x64でビルドされたバイナリファイル。
その他の便利なウィジェット
- EditBox-複数行エディター
- TreeWidget-ツリー
- StringGrid-Excelのようなテーブル
- TabWidget-タブ-ページの選択用
- AppFrame-メニュー、ツールバー、ステータスバーを備えたメインウィンドウウィジェットの基本クラス。このようなアプリケーションを書くのに便利です。
- スクロールバー
- ツールバー
- StatusLine
- ScrollWidget-サイズが利用可能なスペースを超える場合、それに埋め込まれたウィジェットのスクロールを実装します
- DockHost、DockWidget-メインウィンドウウィジェットの端にドックウィジェットがあるアプリケーション用(IDEと同様)
参照資料
継続するには...
次の部分は必要ですか? 他に何を話しますか? コメントを書いてください...