文章 "利用 MQL5 的交互式 GUI 改进您的交易图表(第 III 部分):简易可移动交易 GUI" - 页 2

 
Maxim Kuznetsov #:

如何实现用户界面,使其不会令人痛苦不堪":-)MVC 和类似方法。因此,前端(win,gtk,qt,web)有时只需动动手就能改变。

在 MQL 中,这些功能都没有实现。一切都被钉死了,比 TurboVision 还糟糕--尽管它有来自 Adam 的类,但它有模型

个人多年来一直在写 "简单易行 "和 "界面简洁",但这与本文中的 内容如出一辙。大量的代码并没有让任何事情变得更简单。唯一的效果就是给作者的账户带来奖金。

哦,只要一提到MVC, 就心惊肉跳

从我为我妻子创建一个基于 OcStore 引擎的在线商店网站开始,它就一直存在。

当我至少对它的工作原理有了一些了解时,我已经是半个灰))))。


让我们不要严格地评判,这一系列文章是针对初学者的。

文章写得清晰明了,而要写出清晰明了的文章并非易事。

作者完美地完成了这项任务。

 
Aleksandr Slavskii #:

哎哟,一提到MVC 觉得恶心

自从我用 OcStore 引擎为我妻子制作网站以来,它就一直存在。

当我了解到它的工作原理时,我已经灰心丧气了一半))))。


我们不要妄下结论,这一系列文章都是针对初学者的。

文章写得清楚易懂,而写清楚并不是一件容易的事。

作者完美地完成了这项任务。

在我的记忆中,计算一个破按钮的宽度/高度、相对坐标和绝对坐标的过程令人沮丧:-)

2024 - 但库用户仍然需要计算像素。

请看下面的对话,其形式是一个音量输入框和两个买入/卖出按钮。

是的,手数不能小于最小值,不能逐级递增,也不能超过最大值。买入/卖出并不总是可能的。
有解决方案的提示吗?没有。

在 EA 内部手动管理特定图形用户界面的所有选项。这并不比直接使用终端函数好。

ObjectSetXXX(chart,objName,propertyName,propertyValue)和 obj.SetInteger(value) 之间的区别由定义覆盖,这里不需要 OOP。

---

这与文章无关,而是与一般的 "作者 "有关。您最好阅读

 
Maxim Kuznetsov # :

在我的记忆中,计算按钮的宽度/高度以及相对坐标和绝对坐标的过程令人沮丧:-)

2024 - 但图书馆用户仍然必须计算像素数

给定对话框的形式:音量输入框和两个买入/卖出按钮

上述对话如何解决交易量和交易可能性的问题?是的,手数不能小于最小值,它们是逐级递增的,不能超过最大值。买入/卖出并不总是可能的。有任何解决方案的提示吗?没有

如何解决?内,手动控制特定图形用户界面的所有选项。这并不比直接使用终端功能更好。

ObjectSetXXX(chart,objName,propertyName,propertyValue)和 obj.SetInteger(value) 之间的区别 - 定义已经涵盖,这里不需要 OOP。

---

这不再是文章的问题,而是 "作者 "的问题。如果他们阅读

有一点,我想指出的是,这个系列不是为这个买卖图形用户界面而写的,而是为任何图形用户界面而写的,这个买卖图形用户界面只是一个简单的例子。

感谢您对本系列的思考,希望您能提出建议。

谢谢

 
Maxim Kuznetsov #:

在我的记忆中,我曾计算过一个破按钮的宽度/高度、相对坐标和绝对坐标,这让我感到绝望:-)

2024 - 但图书馆用户仍然需要计算像素数

给定对话框的形式:音量输入框和两个买入/卖出按钮

是的,手数不能小于最小值,不能逐级递增,也不能超过最大值。买入/卖出并不总是可能的。
有解决方案的提示吗?没有。

在 EA 内部手动管理特定图形用户界面的所有选项。这并不比直接使用终端函数好。

ObjectSetXXX(chart,objName,propertyName,propertyValue)和 obj.SetInteger(value) 之间的区别由定义覆盖,这里不需要 OOP。

---

这与文章无关,而是与一般的 "作者 "有关。您最好阅读

天哪,这才是我的第三个面板,我可不想记住前两个,如果有编码员看到,我会感到羞愧的。

我想现在就做,这样下次就不用这么麻烦了。

现在,插件文件中只剩下一个包含拖动面板所有元素代码的类和一堆获取代码。

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);
  }
//+------------------------------------------------------------------+

在下面,我只留下了从帮助文件中复制的绘制对象的函数,把所有东西都集中在一起似乎很方便。

因此,"智能交易系统 "中的代码原来很长,现在变宽了。

另一个插件文件包含常用的交易功能,如计算所有头寸、价格正常化、平仓等。

但还是有点繁琐,不通用。

在下一个面板中,我们必须计算每个字段,并为这些字段(按钮/输入字段)编写处理程序。

我想不出一个更通用的方案。

您能给我一些设计代码的好建议吗?

 
Aleksandr Slavskii #:

但它仍然有点繁琐,而且用途不广。

在下一个面板中,我们将计算每个字段,并为这些字段(按钮/输入字段)编写处理程序。

我想不出有什么办法能让它更通用。

您能就如何设计代码给我一些好的提示吗?

最实用、最通用的变体是直观地设计表单,而完全不用关心布局代码--这就是类应该做的事情。文章 中提到了一种可能的解决方案。

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

最实用、最普遍的选择是直观地设计表单,而完全不用担心布局代码,这正是类应该做的。文章 中提出了一种可能的解决方案。

我想起来了 :-)

对于那些不面向市场、想要或多或少复杂但漂亮的表单,又懒得写 DLL 的人,有 GtkServerhttps://sourceforge.net/projects/gtk-server/ 和 Glade 表单设计器。

方法:GtkServer 作为 tcp 监听器启动,顾问使用 SocketOpen/SocketSend 发送文本 "加载表单"(或通过步骤表单 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 #:

最实用、最普遍的选择是直观地设计表单,而完全不用担心布局代码,这正是类应该做的。文章 中提出了一种可能的解决方案。

斯坦尼斯拉夫,在针对初学者的文章下,你提供了针对高级用户的文章链接:)

我读了,不是读了,只是读了,因为我的编程水平远低于理解文章内容的需要。

我尽量少用我不懂的东西。最近的一个情况让我更加坚信这一点。

您可能正在阅读 "错误、bug、问题 "主题,因此我有一项任务,要在renko-graph上显示从封闭位置出发的箭头,以及它们之间的出入口--一条线。

我决定不自己写,而是从 Saiber 拿现成的代码,结果浪费了半天时间。最后,Saiber 更正了它的代码,但我损失了时间。

如果我想从你的文章中获取代码,并需要对某些地方进行调整,那么,你明白,这样做不会有什么好结果。

我的任务比你写文章时给自己设定的简单。我只需要用现成的代码块搭建下一个面板,就像孩子们用乐高积木搭建房子一样。

在我看来,我根本不需要 OOP 来达到这个目的。我不了解它,所以我不喜欢它。

如果我理解正确的话,MVC 原理非常适合我的目的)))))。

总的来说,我已经想到了应该怎么做。


顺便问一下,你能告诉我如何让我在程序中访问继承类的函数时,看不到基类的函数吗?如果可以的话。

 
Maxim Kuznetsov #:

我想到了)

对于那些不面向市场、想要或多或少复杂但漂亮、又懒得写 DLL 的人,有 GtkServerhttps://sourceforge.net/projects/gtk-server/ 和 Glade 表单设计器。

方法:GtkServer 作为一个 tcp 监听器启动,顾问使用 SocketOpen/SocketSend 发送文本 "加载表单"(或通过步骤表单 gtk 部件本身),并读取结果....。

你也是:)

tcp 监听器、 SocketOpen/SocketSend 等词视为亵渎,甚至不通过谷歌就不知道它们的含义,而你却建议我使用它们。

先生们,有点良知吧,别再用你们的术语吓唬人了)))))。

 
Aleksandr Slavskii #:

斯坦尼斯拉夫,好吧,溜溜球,在初学者文章下,你扔了一个链接到高级文章:)

我已经读过了,不是读过,只是读过,因为我的编程水平远低于我理解文章内容所需的水平。

我尽量少用我不懂的东西。最近的一个情况让我更加坚信这一点。

不幸的是,软件的情况就是这样,不可能自己了解所有的东西。根据这种逻辑,操作系统应该是定制的(一些 Linux 的辩护者就是这么做的)。

这就是为什么现代的做法是采用现成的砖块(它们或多或少能满足你的需求),然后将它们对接起来(而不去深入实施)。

我只是回答了如何做得更普遍的问题。我的文章很复杂,你无法反驳,但重点是,你可以将必要的图形用户界面描述为模板,无需编程,只需插入外壳即可获得控制器、窗口拖动、大小调整等功能。

 
很优秀,非常好,我不会代码的都能修修改改用,但有些功能不会处理,方便帮我修改下吗?加个输入框带+-号的。谢谢!