Обсуждение статьи "Сделайте торговые графики лучше с интерактивным графическим интерфейсом на основе MQL5 (Часть III): Простой перемещаемый торговый интерфейс" - страница 2

 
Maxim Kuznetsov #:

есть тьма проработанных методик с красивыми стрелочками "как реализовать UI чтобы не было мучительно больно" :-) MVC и подобные. Так там фронт (win,gtk,qt,web) подчас можно менять лёгким движением руки. 

ни одно не было реализовано в MQL. Тут всё прибивается наглухо гвоздями, хуже TurboVision - там хоть так-же классы от адама, но там есть модели  

отдельные лица годами(!!) пишут про "легко и просто" и "простой интерфейс", но ровно то-же самое что в этой статье. Масса кода не облегчающего ничего. Единственный эффект - бонус на счёт автора.

Ой, у меня одно только упоминание об  MVC вызывает ужас.

Это осталось с тех пор как я, жене сайт, интернет магазина делал на движке OcStore.

К тому времени как пришло хоть какое то понимание как это работает, я был наполовину седой)))


Давайте не будем судить строго, эта серия статей ориентирована на начинающих.

Статьи написаны понятно и доходчиво, а написать понятно это не такая уж простая задача.

Автор, справляется с этой задачей на отлично.

 
Aleksandr Slavskii #:

Ой, у меня одно только упоминание об  MVC вызывает ужас.

Это осталось с тех пор как я, жене сайт, интернет магазина делал на движке OcStore.

К тому времени как пришло хоть какое то понимание как это работает, я был наполовину седой)))


Давайте не будем судить строго, эта серия статей ориентирована на начинающих.

Статьи написаны понятно и доходчиво, а написать понятно это не такая уж простая задача.

Автор, справляется с этой задачей на отлично.

у меня вот воспоминание о том чтобы считать ширину/высоту и относительные и абс.координаты всратой кнопки повергают в уныние :-)

2024 год - но пр прежнему, пользователь библиотеки должен считать пиксели 

приведёный диалог, в виде : поле ввода объёмов и две кнополки buy/sell

как приведённый диалог решает проблемы с допустимостью объёмов и возможностью торговли ? да, лоты не могут быть менее минимума, инкременируются по шагам и не более максимума. Buy/Sell не всегда возможны.
Хоть намётки на решения есть ? нету

КАК ? в рукопашку-же...внутри советника вручную рулить всеми опциями конкретного GUI. Ничуть не лучше использольвания напрямую функций терминала.

между ObjectSetXXX(chart,objName,propertyName,propertyValue) и obj.SetInteger(value) - разница покрывается дефайнами, тут не нужно никакое ООП

---

это уже не в плане статьи, это вообще про "писателей". Лучше-бы читали

 
Maxim Kuznetsov # :

I have a memory of calculating the width/height and the relative and absolute coordinates of a button, which is depressing :-)

2024 - but still, the library user must count pixels 

the given dialogue, in the form: volume input field and two buy/sell buttons

How does the above dialogue solve problems with the admissibility of volumes and the possibility of trading? Yes, lots cannot be less than the minimum, they are incremented in steps and no more than the maximum. Buy/Sell is not always possible. Are there any hints of solutions? There is not

HOW? in hand-to-hand combat... inside the advisor, manually control all the options of a specific GUI. It's no better than using the terminal functions directly.

between ObjectSetXXX(chart,objName,propertyName,propertyValue) and obj.SetInteger(value) - the difference is covered by definitions, no OOP is needed here

---

This is no longer in terms of the article, it's generally about “writers”. It would be better if they read

Just one thing, I would like to point out is, this series was not written for this Buy/Sell GUI rather it was written for any GUI and this Buy/Sell GUI acts as an simple example.

Thanks for giving the series such thoughts, would appreciate suggestions.

Regards

 
Maxim Kuznetsov #:

у меня вот воспоминание о том чтобы считать ширину/высоту и относительные и абс.координаты всратой кнопки повергают в уныние :-)

2024 год - но пр прежнему, пользователь библиотеки должен считать пиксели 

приведёный диалог, в виде : поле ввода объёмов и две кнополки buy/sell

как приведённый диалог решает проблемы с допустимостью объёмов и возможностью торговли ? да, лоты не могут быть менее минимума, инкременируются по шагам и не более максимума. Buy/Sell не всегда возможны.
Хоть намётки на решения есть ? нету

КАК ? в рукопашку-же...внутри советника вручную рулить всеми опциями конкретного GUI. Ничуть не лучше использольвания напрямую функций терминала.

между ObjectSetXXX(chart,objName,propertyName,propertyValue) и obj.SetInteger(value) - разница покрывается дефайнами, тут не нужно никакое ООП

---

это уже не в плане статьи, это вообще про "писателей". Лучше-бы читали

Блин, у меня это всего третья панелька, первые две вспоминать не охота, если их увидит какой нибудь кодер, мне будет стыдно.

Хотелось бы сделать сейчас так, чтоб в следующий раз не пришлось столько с ней возится.

Сейчас в подключаемом файле оставил только класс с кодом для перетаскивания всех элементов панели и кучка гетов.

class CreateObject
  {
private:
   string            _name; // Name of the rectangle label
   int               previousMouseState, mlbDownX, mlbDownY, mlbDownXDistance, mlbDownYDistance; // Mouse state tracking variables
   bool              movingState; // State for whether the object is moving
   string            addedNames[]; // Array of added names
   long              addedXDisDiffrence[], addedYDisDiffrence[]; // Arrays to store added distance differences
   void              Destroy() {for(int i = 0; i < (int)addedNames.Size(); i++)ObjectDelete(0, addedNames[i]); ObjectDelete(0, _name);} // Destroy method for rectangle label
public:
                     CreateObject(void); // Constructor
                    ~CreateObject(void); // Destructor
   void              SetName(string name) {_name = name;}
   string            GetText(string name) {return ObjectGetString(0, name, OBJPROP_TEXT);} // Method to retrieve the text content
   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); // Event handler method
   void              Add(string name); // Method to add a name to the object
  };
//+------------------------------------------------------------------+
CreateObject::CreateObject(void) {}
//+------------------------------------------------------------------+
CreateObject::~CreateObject(void) {Destroy();}
//+------------------------------------------------------------------+
//| Event handling for mouse movements                               |
//+------------------------------------------------------------------+
void CreateObject::OnEvent(int id, long lparam, double dparam, string sparam)
  {
// Handle mouse movement events for dragging the rectangle label
   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;
     }
  }
//+------------------------------------------------------------------+
//| Method to add an object by name to the rectangle label           |
//+------------------------------------------------------------------+
void CreateObject::Add(string name)
  {
// Add a new object by name to the rectangle label and track distances
   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 при этом писать лень, существует GtkServer https://sourceforge.net/projects/gtk-server/ и к нему дизайнер форм Glade

методика: GtkServer запускается как tcp listener, советник используя 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 #:

Наиболее практичный и универсальный вариант - дизайнить формы визуально, не заботясь о коде раскладки вообще - этим как раз должны заниматься классы. Одно из возможных решений было в статье.

Станислав, ну ё-ма-ё, под статьёй для начинающих скидываете ссылку на статью для продвинутых  :)

Почитал, не прочитал, а всего лишь почитал, так как мой уровень в программировании намного ниже, чем нужен для понимания того, что там написано.

Пользоваться тем, чего не понимаю, стараюсь как можно меньше. Недавняя ситуация ещё сильнее укоренила меня в этом.

Вы ведь наверняка читаете тему «Ошибки, баги, вопросы», так вот, у меня была задача вывести стрелочки от закрытых позиций на ренко-график, вход-выход между ними — линия.

Решил сам не писать, а взять готовое от Сайбера, как итог — полдня потерянного времени. Сайбер свой код в итоге поправил, но время-то я потерял.

А если бы я захотел взять код из вашей статьи и мне понадобилось бы что-то подправить, ну, в общем, вы понимаете, ничего хорошего из этого не вышло.

У меня задача попроще, чем поставили себе вы при написании статьи. Мне просто нужно сделать так, чтоб следующую панельку я мог собирать из кусков готового кода, как дети из лего строят домики.

ООП для этого, на мой взгляд, вообще ни к чему. Я его не знаю, поэтому не люблю.

Принцип MVC для моих целей вполне подходит, если я его правильно понял)))

В общем-то картинка, как это должно быть, у меня уже сложилась.


Кстати, подскажите, как сделать, чтоб когда я обращаюсь из программы к функциям класса-наследника, не видеть функции базового класса? Ну, если это возможно. 

 
Maxim Kuznetsov #:

вспомнилось :-)

для тех кому не для маркета, хочется более-менее сложного но красивого, и DLL при этом писать лень, существует GtkServer https://sourceforge.net/projects/gtk-server/ и к нему дизайнер форм Glade

методика: GtkServer запускается как tcp listener, советник используя SocketOpen/SocketSend отсылает текстом "загрузить форму" (или сам по шагам формирует gtk виджеты) и так-же читает результат..

И вы туда же :)

Да я вообще слова типа   tcp listener, SocketOpen/SocketSend  воспринимаю как матершинные, без гугла даже их значение не знаю, а вы предлагаете ещё и воспользоваться этим.

Господа продвинутые, ну имейте совесть, хватит пугать людей своей терминологией)))

 
Aleksandr Slavskii #:

Станислав, ну ё-ма-ё, под статьёй для начинающих скидываете ссылку на статью для продвинутых  :)

Почитал, не прочитал, а всего лишь почитал, так как мой уровень в программировании намного ниже, чем нужен для понимания того, что там написано.

Пользоваться тем, чего не понимаю, стараюсь как можно меньше. Недавняя ситуация ещё сильнее укоренила меня в этом.

С ПО, к сожалению, вырисовывается такая ситуация, что невозможно самому во всем разобраться. По такой логике и операционку нужно под себя "пилить" (чем некоторые апологеты Линукса занимаются).

Поэтому современный подход заключается в том, чтобы взять готовые кирпичики (которые делают более-менее то, что нужно) и состыковать (не углубляясь в реализацию).

Я всего лишь отвечал на вопрос, как сделать более универсально. С тем, что моя статья сложная, не поспоришь, но суть то её в том, что можно (не вникая в устройство) описать нужный GUI как шаблон и без программирования, только подключив инклуды, получить контролы, перетаскивание окон, ресайз и прочее.

 
Отлично, очень хорошо, я могу возиться с тем, что не умею кодировать, но есть некоторые функции, с которыми я не могу справиться, легко ли помочь мне модифицировать? Добавьте поле ввода со знаком +-. Спасибо!