Eto.Formsの安定したGUI操作(GTK対策)
これは、C# Advent Calendar 2017への投稿でもあります。24日が未投稿のままだったのでいただいちゃいました。
Eto.FormsでGUIアプリケーションを書いていると、個人的な範囲だと、Windowsだと問題ないのにLinux(GTK)だと挙動(特に初期設定)がおかしい、という場面に割とあたります。Shown
イベントに書いてもLoadComplete
イベントでもだめ、とか。
なので、力づくな対応策を考えてみました。「フォームが見えたら幅と高さが正の値になる」という前提で、それまでUITimer
で待つというものです。とりあえず手元(Windows, Linux)では正常に動いてます。
(2017-12-30改訂:コードを少し整理しました。挙動はほぼ同様です)
public class MyEtoForm : Form { #region ===== Prepared detection ===== public bool IsPrepared { get { return _isPrepared; } set { if (value == _isPrepared) return; if (value == true) { Prepared?.Invoke(this, EventArgs.Empty); if (showCheckTimer.Started) { showCheckTimer.Stop(); } } _isPrepared = value; } } private bool _isPrepared = false; public event EventHandler<EventArgs> Prepared; UITimer showCheckTimer; int initPreparedCounter = 0; void InitPreparedDetection() { if (showCheckTimer == null) { showCheckTimer = new UITimer { Interval = 0.05 }; showCheckTimer.Elapsed += (s, e) => { CheckPrepared(null,EventArgs.Empty); }; } Shown += CheckPrepared; } void OnShown(object s, EventArgs e) { if (IsDisplayed) { IsPrepared = true; } else { if (showCheckTimer.Started == false) { initPreparedCounter = 0; showCheckTimer.Start(); } } } void CheckPrepared(object s, EventArgs e) { if (IsDisplayed) { if (initPreparedCounter < 1) { initPreparedCounter++; } else { IsPrepared = true; } } } bool IsDisplayed { get { return (Width > 0 && Height > 0); } } #endregion public MyEtoForm() { InitPreparedDetection(); } }
このMyEtoForm
を継承します。
この2つがメンバに加わるので、ご自由にご利用ください。
なお、macOSでの動作は確認していません。申し訳ないです。