記事「MQL5のインタラクティブGUIで取引チャートを改善する(第3回):シンプルで移動可能な取引GUI」についてのディスカッション - ページ 2

 
Maxim Kuznetsov #:

UIをどう実装すれば耐え難い苦痛を伴わないか」という、美しい矢印のついた手の込んだメソッドの闇がある:-)MVCとか。そこで、フロントエンド(win,gtk,qt,web)は、ちょっとした手の動きで変更できることがある。

どれもMQLには実装されていない。すべてが釘付けで、TurboVisionよりもひどい - Adamからのクラスがあるとはいえ、モデルを持っている

個人が何年も(!!)「簡単でシンプル」とか「シンプルなインターフェース」とか書いているが、この記事とまったく同じである。何も簡単にしないコードの数々。唯一の効果は、作者のアカウントにボーナスが入ることだ。

ああ、MVCと 聞いただけで ぞっとする

私が妻のサイト、OcStoreエンジンのオンラインショップを作ったときからずっとそうだった。

MVCの仕組みをある程度理解した頃には、私は半分白髪になっていた。)


この連載は初心者を対象にしている。

記事は明瞭かつ明快に書かれており、明瞭に書くことはそれほど簡単なことではない。

著者は、この課題に完璧に対処している。

 
Aleksandr Slavskii #:

痛い、 MVCと 聞いただけで ゾッとする

妻のウェブサイトをOcStoreエンジンで作って以来だ。

仕組みを理解するようになった頃には、半分白髪になっていた))))


この連載は初心者を対象にしている。

記事はわかりやすく書かれているし、わかりやすく書くのはそう簡単なことではない。

著者は、この課題に完璧に対処している。

クソみたいなボタンの幅と高さ、相対座標と絶対座標を数えるのが鬱陶しかった思い出がある :-)

2024 - それでも、ライブラリーのユーザーはピクセルを数えなければならない。

与えられたダイアログは、ボリューム入力フィールドと2つの売買ボタンの形をしている。

上記のダイアログは、ボリュームの許容範囲と取引可能性に関する問題をどのように解決するのでしょうか。
。 解決策のヒントは?

EA内部で、特定のGUIのすべてのオプションを手動で管理します。ターミナル関数を直接使うより全然いい。

ObjectSetXXX(chart,objName,propertyName,propertyValue)とobj.SetInteger(value)の違いはdefineでカバーされており、OOPは必要ありません。

---

この記事についてではなく、一般的な "ライター "についてです。以下を読んだ方がいい。

 
Maxim Kuznetsov # :

ボタンの幅と高さ、相対座標と絶対座標を計算した記憶があるんだけど、それが憂鬱なんだ :-)

2024 - それでも、ライブラリのユーザーはピクセルを数えなければならない。

与えられたダイアログの形式:ボリューム入力フィールドと2つの売買ボタン

上記のダイアログは、ボリュームの許容性と取引の可能性に関する問題をどのように解決するのですか?はい、ロットは最小値より少なくすることはできず、段階的に増加し、最大値より多くすることはできません。売買は常に可能というわけではありません。解決のヒントはありますか?ありません。

どうやって?アドバイザーの中で、特定のGUIのすべてのオプションを手動でコントロールする。ターミナル機能を直接使うより全然いい。

ObjectSetXXX(chart,objName,propertyName,propertyValue)とobj.SetInteger(value)の違い - 違いは定義でカバーされている。

---

これはもはや記事の観点ではなく、一般的に「ライター」についてです。彼らが読むなら

ただ一つ指摘しておきたいのは、この連載はこの売買GUIのために書かれたものではなく、むしろあらゆるGUIのために書かれたものであり、この売買GUIは単純な例として機能している。

このシリーズにこのような考えを与えていただきありがとうございます。

よろしくお願いします。

 
Maxim Kuznetsov #:

クソみたいなボタンの幅と高さ、相対座標と絶対座標を数えた記憶があるので、意気消沈してしまう :-)

2024 - それでもライブラリのユーザーはピクセルを数えなければならない

与えられたダイアログの形式:ボリューム入力フィールドと2つの売買ボタン

上記のダイアログは、ボリュームの許容範囲と取引可能性の問題をどのように解決するのでしょうか?
解決策のヒントはありますか? いいえ。

EA内部で、特定のGUIのすべてのオプションを手動で管理します。ターミナル関数を直接使用するのと変わらない。

ObjectSetXXX(chart,objName,propertyName,propertyValue)とobj.SetInteger(value)の違い - 違いはdefineでカバーされており、ここではOOPは必要ありません。

---

この記事についてではなく、一般的な "ライター "についてです。以下を読んだ方がいい。

まだ3コマ目だから、最初の2コマは思い出したくない。

もしコーダーがそれを見たら、私は恥をかくだろう。次回はそんなにいじらなくてもいいように、今やっておきたい。

さて、プラグイン・ファイルには、パネルのすべての要素をドラッグするコードと、たくさんのgetを含むクラスだけが残っている。

class CreateObject
  {
private:
   string            _name; // 矩形ラベルの名前
   int               previousMouseState, mlbDownX, mlbDownY, mlbDownXDistance, mlbDownYDistance; // マウスの状態追跡変数
   bool              movingState; // オブジェクトが動いているかどうかの状態
   string            addedNames[]; // 追加された名前の配列
   long              addedXDisDiffrence[], addedYDisDiffrence[]; // 追加された距離の差を格納する配列
   void              Destroy() {for(int i = 0; i < (int)addedNames.Size(); i++)ObjectDelete(0, addedNames[i]); ObjectDelete(0, _name);} // 矩形ラベルの破棄メソッド
public:
                     CreateObject(void); // コンストラクタ
                    ~CreateObject(void); // デストラクタ
   void              SetName(string name) {_name = name;}
   string            GetText(string name) {return ObjectGetString(0, name, OBJPROP_TEXT);} // テキストの内容を取得するメソッド
   long              GetType(string name) {return ObjectGetInteger(0, name, OBJPROP_TYPE);}
   double            GetPrice(string name) {return ObjectGetDouble(0, name, OBJPROP_PRICE);}
   void              OnEvent(int id, long lparam, double dparam, string sparam); // イベント・ハンドラ・メソッド
   void              Add(string name); // オブジェクトに名前を追加するメソッド
  };
//+------------------------------------------------------------------+
CreateObject::CreateObject(void) {}
//+------------------------------------------------------------------+
CreateObject::~CreateObject(void) {Destroy();}
//+------------------------------------------------------------------+
//| マウスの動きに対するイベント処理
//+------------------------------------------------------------------+
void CreateObject::OnEvent(int id, long lparam, double dparam, string sparam)
  {
// 矩形ラベルをドラッグするためのマウス移動イベントを処理する。
   if(id == CHARTEVENT_MOUSE_MOVE && lparam > 20 && dparam > 20 &&
      lparam < ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) - 20 && dparam < ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS) - 20)
     {
      int X = (int)lparam;
      int Y = (int)dparam;
      int MouseState = (int)sparam;

      string name = _name;
      int XDistance = (int)ObjectGetInteger(0, name, OBJPROP_XDISTANCE);
      int YDistance = (int)ObjectGetInteger(0, name, OBJPROP_YDISTANCE);
      int XSize = (int)ObjectGetInteger(0, name, OBJPROP_XSIZE);
      int YSize = (int)ObjectGetInteger(0, name, OBJPROP_YSIZE);

      if(previousMouseState == 0 && MouseState == 1)
        {
         mlbDownX = X;
         mlbDownY = Y;
         mlbDownXDistance = XDistance;
         mlbDownYDistance = YDistance;

         if(X >= XDistance && X <= XDistance + XSize && Y >= YDistance && Y <= YDistance + YSize)
           {
            movingState = true;
           }
        }

      if(movingState)
        {
         ChartSetInteger(0, CHART_MOUSE_SCROLL, false);
         ObjectSetInteger(0, name, OBJPROP_XDISTANCE, mlbDownXDistance + X - mlbDownX);
         ObjectSetInteger(0, name, OBJPROP_YDISTANCE, mlbDownYDistance + Y - mlbDownY);
         for(int i = 0; i < ArraySize(addedNames); i++)
           {
            ObjectSetInteger(0, addedNames[i], OBJPROP_XDISTANCE, mlbDownXDistance + X - mlbDownX - addedXDisDiffrence[i]);
            ObjectSetInteger(0, addedNames[i], OBJPROP_YDISTANCE, mlbDownYDistance + Y - mlbDownY - addedYDisDiffrence[i]);
           }
         ChartRedraw(0);
        }

      if(MouseState == 0)
        {
         movingState = false;
         ChartSetInteger(0, CHART_MOUSE_SCROLL, true);
        }

      previousMouseState = MouseState;
     }
  }
//+------------------------------------------------------------------+
//| 矩形ラベルに名前を付けてオブジェクトを追加するメソッド。
//+------------------------------------------------------------------+
void CreateObject::Add(string name)
  {
// 矩形ラベルとトラック距離に名前を付けて新しいオブジェクトを追加する。
   ArrayResize(addedNames, ArraySize(addedNames) + 1);
   ArrayResize(addedXDisDiffrence, ArraySize(addedXDisDiffrence) + 1);
   ArrayResize(addedYDisDiffrence, ArraySize(addedYDisDiffrence) + 1);

   addedNames[ArraySize(addedNames) - 1] = name;
   addedXDisDiffrence[ArraySize(addedXDisDiffrence) - 1] = ObjectGetInteger(0, _name, OBJPROP_XDISTANCE) - ObjectGetInteger(0, name, OBJPROP_XDISTANCE);
   addedYDisDiffrence[ArraySize(addedYDisDiffrence) - 1] = ObjectGetInteger(0, _name, OBJPROP_YDISTANCE) - ObjectGetInteger(0, name, OBJPROP_YDISTANCE);
  }
//+------------------------------------------------------------------+

そしてその下には、ヘルプからコピーしたオブジェクトを描画するための関数があるだけだ。

その結果、Expert Advisorのコードは長くなり、今では幅が広くなった。

全ポジションの計算、価格の正規化、ポジションのクローズなど、よく使う取引機能をまとめたプラグイン・ファイルもある。

しかし、まだ少し面倒で、普遍的ではありません。

次のパネルでは、各フィールドを計算し、これらのフィールド(ボタン/入力フィールド)の処理を書かなければならない。

そして、それをもっと普遍的に行うスキームが思いつきません。

コード設計のヒントをいただけないでしょうか?

 
Aleksandr Slavskii #:

でも、まだちょっと面倒だし、汎用性もない。

次のパネルでは、各フィールドを計算し、そのフィールド(ボタン/入力フィールド)の処理を書くことになる。

それに、もっと汎用的にする方法は思いつかない。

コード設計のヒントをいただけないでしょうか?

最も実用的で普遍的な方法は、レイアウトコードをまったく気にせずに、フォームを視覚的にデザインすることです。可能な解決策の1つが記事に ありました。

Язык MQL как средство разметки графического интерфейса MQL-программ (Часть 3). Дизайнер форм
Язык MQL как средство разметки графического интерфейса MQL-программ (Часть 3). Дизайнер форм
  • www.mql5.com
В этой статье мы завершаем описание концепции построения оконного интерфейса MQL-программ с помощью конструкций языка MQL. Специальный графический редактор позволит интерактивно настраивать раскладку, состоящую из основных классов элементов GUI, и затем экспортировать её в MQL-описание для использования в вашем MQL-проекте. Представлено внутреннее устройство редактора и руководство пользователя. Исходные коды прилагаются.
 
Stanislav Korotky #:

最も実用的で普遍的な選択肢は、レイアウトコードをまったく気にすることなく、視覚的にフォームをデザイン することです。可能な解決策の1つが記事に ありました。

思い出しました :-)

市場向けではなく、多かれ少なかれ複雑で美しいフォームが必要で、DLLを書くのが面倒な人のために、GtkServerhttps://sourceforge.net/projects/gtk-server/ と Glade フォームデザイナがあります。

方法: GtkServerはtcpリスナーとして起動し、SocketOpen/SocketSendを使用してアドバイザーが "load form "というテキストを送信し(またはgtkウィジェットのステップフォームでそれ自身)、その結果を読み取ります。

GTK-server
  • 2018.11.27
  • sourceforge.net
From AI to Wasm, eBPF, and environmental sustainability, KubeCon + CloudNative Con Europe is the place to experience everything cloud native has to offer and also take a deep dive into new and promising...
 
Stanislav Korotky #:

最も実用的で普遍的な選択肢は、レイアウトコードをまったく気にすることなく、視覚的にフォームをデザインすることです。可能な解決策の1つが記事に ありました。

スタニスラフ、初心者向けの記事の下に上級者向けの記事へのリンクがありますね :)

私のプログラミングのレベルは、そこに書かれていることを理解するのに必要なレベルよりもずっと低いので、私はそれを読みました。

理解できないことはできるだけ使わないようにしている。最近のある状況は、このことをさらに強く私に根付かせた。

おそらく「エラー、バグ、質問」というトピックを読んでいるのだろう。そこで私は、閉じた位置からの矢印を連動グラフ上に表示し、その間に出入り口-線を表示するという仕事をした。

自分で書くのではなく、サイバーの既成コードを使うことにしました。その結果、半日を無駄にした。サイバーは最終的にコードを修正してくれたが、私は時間を失った。

そして、もし私があなたの記事からコードを引用し、何かを微調整する必要があったとしても、まあ、あなたは理解しているはずだ。

私には、あなたが記事を書くときに設定したよりも簡単な仕事がある。子供がレゴで家を建てるように、出来合いのコードから次のパネルを作れるようにするだけだ。

この目的のためにOOPはまったく必要ないと私は思う。私はそれを知らないので、好きではない。

MVCの原則は、私が正しく理解していれば、私の目的にはかなり適している))))))

一般的に、私はすでにそれがどのようにあるべきかのイメージを持っています。


ところで、プログラムから継承クラスの関数にアクセスしたときに、基底クラスの関数が表示されないようにする方法を教えてもらえませんか?可能ならね。

 
Maxim Kuznetsov #:

を思い浮かべた。)

市場向けではなく、多かれ少なかれ複雑だが美しいものが欲しい、そしてDLLを書くのは面倒だという人のために、GtkServerhttps://sourceforge.net/projects/gtk-server/ と Glade form designer があります。

方法: GtkServerはtcpリスナーとして起動し、SocketOpen/SocketSendを使用してアドバイザーが "load form "というテキストを送信し(またはgtkウィジェットのステップフォームでそれ自身)、その結果を読み取ります。

あなたも)

tcpリスナー、 SocketOpen/SocketSendといった 言葉は冒涜的 で、 ググらないと意味すらわからない。

皆さん、良心を持ってください、あなたの専門用語で人々を怖がらせるのはやめてください))))

 
Aleksandr Slavskii #:

スタニスラフ、ヨーヨーヨーヨー、初心者向けの記事の下に上級者向けの記事へのリンクがあるよ。)

僕のプログラミングのレベルは、そこに書かれていることを理解するのに必要なレベルよりもずっと低いから。

理解できないことはできるだけ使わないようにしている。最近のある状況は、このことをさらに強く私に根付かせている。

残念ながら、ソフトウェアの状況は、すべてを自分で理解することは不可能なのだ。この論理に従えば、オペレーティング・システムはカスタマイズされるべきなのだ(一部のLinux擁護者はそうしている)。

だからこそ、現代のアプローチは、(多かれ少なかれ必要なことをする)既製のレンガを手に入れ、(実装に深入りすることなく)ドッキングさせることなのだ。

私は、どうすればもっと普遍的なことができるかという質問に答えただけだ。私の記事が複雑であることに異論はないだろうが、要は、コントローラやウィンドウのドラッグ、リサイズなどを得るために囲いを差し込むだけで、プログラミングなしで必要なGUIをテンプレートとして記述できるということだ。

 
素晴らしい、とても良い。私はコーディングできないものをいじることができるが、私が扱えない機能がいくつかある。入力ボックスに+-記号を追加してください。ありがとうございます!