Galerie der in MQL geschriebenen UIs - Seite 54

 

Ich habe auch eine Vollbildleinwand, die bei jeder Änderung komplett neu gezeichnet wird, aber das dauert nicht länger als 50 ms....

Am aufwendigsten ist das Zeichnen von Text. Damit ich nicht jedes Mal TextOut verwenden muss, speichere ich sie in Arrays. Das geht viel schneller.

 

Die größte Herausforderung besteht nun darin, dem Benutzer die programmatische Kontrolle über die Steuerung der Schnittstelle zu geben.

Technisch gesehen ist die Aufgabe nicht schwierig, denn in der symbiotischen Verbindung von Benutzerprogramm und Engine ist der grafische Kern auf globaler Ebene für die Algorithmen beider Parteien sichtbar. Das Problem ist, dass der Benutzer nicht weiß, wie er mit dem Kernel arbeiten soll. Er kennt und versteht die Prinzipien der Elementverwaltung nicht. Daher müssen vertraute Wrapper zur Verfügung gestellt werden - Funktionen, über die er auf den Kernel zugreifen und Werte ändern kann.

Aber es gibt eine Nuance. Die Namen der Funktionen sind zu lang. Schließlich sollte jeder funktionale Wrapper eines interaktiven Elements die Namen des Elements und des Fensters enthalten. Dies ist für die Orientierung unter den Namen notwendig. Andernfalls wird der Benutzer leicht verwirrt und versteht seine Funktionsumhüllungen nicht. Außerdem können sich die Namen überschneiden, und das ist überhaupt nicht gut. Es stellt sich also heraus, dass man Namen aus zwei Komponenten erzeugen muss: dem Namen des Elements und dem Namen des Fensters. Dann gibt es keine Verwirrung, aber die Namen von Wrappern werden zu lang. Besonders mit der Seite der übergebenen Parameter. Außerdem müssen Sie den Funktionen Präfixe hinzufügen, um sie über Intellisense schnell zu finden. Dies ermöglicht eine effiziente Filterung des Pop-up-Beispiels. Praktisch. ABER LANG!

Und nicht nur das. Das Problem sind die Parameter, die übergeben werden. Entweder man schreibt Wrapper für jedes voreingestellte get/set-properties von Elementen und Fenstern, oder jeder Wrapper akzeptiert die komplette Liste der Parameter eines Benutzeraufrufs. Das ist furchtbar unbequem. Und was am wichtigsten ist, es ist schwer zu erklären.


Es gibt einen Ausweg und er ist einfach. Und das ist er: eine Gruppe von abstrakten Eigenschaften. Globale Variablen, die sowohl vom Programm des Benutzers als auch von der Engine aus sichtbar sind.

So wird es funktionieren:

1. Alle Wrapper von Elementen und Fenstern werden die zentrale Funktion ansprechen und ihre Indizes übergeben. Anhand dieser Indizes wird das Zielelement/Fenster des Aufrufs bestimmt.

2. Nach diesem Aufruf setzt der Benutzer die ausgewählten abstrakten Eigenschaften auf die gewünschten Werte.

3. Rufen Sie die zentrale Funktion auf und übergeben Sie das c.word "Set".

4. Central setzt die Werte der abstrakten Eigenschaften aus ihren globalen Variablen auf die Zieleigenschaften des jeweiligen Elements oder Fensters.

5. Es aktualisiert das Element/Fenster und setzt die abstrakten Eigenschaften auf Null zurück.

Das war's.

Meiner Meinung nach ist dies eine einfache und effiziente Lösung, die Folgendes bietet:

a) Einfacher Zugriff auf die Eigenschaften beliebiger Elemente und Fenster, ohne Parameter an eine Funktion zu übergeben, die strikte Konsistenz erfordert. (Plus - Begrenzung der Anzahl der übergebenen Parameter. Und der Aufruf wird lang und unleserlich).

c) Freie Kombination einer Reihe von Eigenschaften von Elementen und Fenstern beim Setzen/Empfangen von Werten irgendwo im Programm.


Wenn jemand Nachteile sieht - bitte melden. Es wäre schön, diese Frage vor der Freigabe zu koordinieren.

 
Nikolai Semko CCanvas-Klasse ein (falls Sie diese verwenden) und drucken Sie diesen Zähler aus, z. B. wenn count%100 == 0.

Nicholas, es lohnt sich zu bedenken, dass wir über mehrere GUI-Fenster sprechen. In der letzten Version gab es 17 davon, von denen jedes Hunderte von Elementen hat. Und jedes Element ist komplex. Es besteht aus einer Reihe von Teilen. Jedes Detail ist ein Abschnitt der Leinwand, den Sie durchlaufen und an der richtigen Stelle mit den erforderlichen Werten füllen müssen.

Nimmt man die durchschnittliche Anzahl von 10 Fenstern (Papkov hat, wenn ich mich recht erinnere, eine Schnittstelle mit 11 Fenstern bestellt) und stellt sich vor, dass jedes Fenster aus einer Reihe von Elementen oder einer Tabelle besteht, dann wird klar, warum das vollständige Rendern der gesamten Schnittstelle so viel Zeit in Anspruch nimmt. Ich möchte Sie daran erinnern, dass es in der Benutzeroberfläche Icons, Schatten, Oberflächenverläufe, verschiedene Rahmen gibt.... dann dauert das komplette Zeichnen der gesamten Oberfläche mindestens 500 ms. Daran können Sie nichts ändern.

Es kann schneller gehen, wenn Sie die Anzahl der Fenster reduzieren oder die Grafiken vereinfachen.

Zum Thema Redrawing - ich habe fast keine reinen ChartRedraw()-Aufrufe. Das _ChartRedraw-Flag wird überall verwendet. Wenn dieses Flag gesetzt ist, wird die ChartRedraw()-Funktion bei der nächsten Timer-Iteration, nach 25 ms, aufgerufen. Das heißt - einmal. Auf diese Weise vermeide ich unnötige Neuaufrufe. Nur in seltenen Fällen erfolgt ein direkter Aufruf von ChartRedraw().

 
Andrey Barinov #:

Ich habe auch die Vollbildleinwand vollständig neu gezeichnet jedes Mal, wenn ich ändern, aber es dauert nicht länger als 50 ms ...

Am teuersten ist es, Text zu zeichnen. Daher, um nicht jedes Mal TextOut zu verwenden, speichere ich sie in Arrays. Es stellt sich heraus, viel schneller.

Nun, einfache Arithmetik funktioniert hier: die Summe der Flächen von 10 - 17 Fenstern ist viel größer als der gesamte Bildschirm. Einverstanden. Plus sekundäre zusätzliche Zeichnung notwendig, um Schatten, Icons, Frames zu erstellen....

Und über TextOut werde ich prüfen und schreiben. Interessante Idee.

 

Ich habe einen Test durchgeführt:

Ich ging in die Datei Demo project 1.mqh und setzte alle Fenster auf OOI-Flag. (Öffnen bei Initialisierung).

Insgesamt 15 Fenster unterschiedlicher Größe und unterschiedlichen Inhalts. 2 Fenster mit Bildlaufleisten und Tabellen (so dass ihre Leinwand teilweise versteckt ist und tatsächlich 2-3 mal länger. Die volle Länge kann anhand des Verhältnisses von Schieberegler zu Bildlaufleiste beurteilt werden). Gesamte Zeichenfläche(Minimum) 2000*1000 Pixel. Aber ich denke, es ist mehr als das. Insgesamt 1158 gezeichnete Teile (nach dem Drucken des Kerns geprüft). Zeit des vollständigen Zeichnens aller Leinwände von Null an von 1600 - bis 1900 ms.

Achten Sie auch hier auf die Menge der Details, die gezeichnet werden mussten. Schatten, Icons, Farbverläufe, Rahmen, Texte.


Die Zeichenzeit ist auf dem Bildschirmfoto zu sehen:


 
Vielleicht gibt es eine Möglichkeit, das Zeichnen zu beschleunigen. Entfernen Sie die untere Basis der Fensterplattformen. Das sind große Leinwände hinter der Vorderseite, auf denen sich die Elemente befinden. Wenn du sie entfernst, wird es 2 Mal schneller gehen. Ich werde darüber nachdenken müssen.
 
Ist es möglich, bestimmte Fenster nur zu zeichnen, wenn sie geöffnet sind? Es ist selten, dass man ein Dutzend Fenster gleichzeitig geöffnet hat. Es besteht keine Notwendigkeit, dies zu tun.
 
hini #:
Kann ich bestimmte Fenster nur zeichnen, wenn sie geöffnet sind? Es ist selten, dass man Dutzende von Fenstern gleichzeitig geöffnet hat. Das ist auch nicht nötig.

Das ist das Einzige, was passiert, glauben Sie mir. Ich spreche nur vom ersten Zeichnen aller Schnittstellenfenster auf einmal. Das erste Zeichnen nimmt die meiste Zeit in Anspruch. Und danach sind alle Bilder bereits gespeichert und werden bei Bedarf aus dem Speicher geholt. Mit einem einzigen Aufruf sind sie in wenigen Millisekunden an ihre Leinwände angehängt. Das ist kein Problem. Sie wollen nur die Zeit der ersten Zeichnung komprimieren.

 
Реter Konow #:
Vielleicht gibt es eine Möglichkeit, das Zeichnen zu beschleunigen. Entfernen Sie die untere Basis der Fensterplattformen. Das sind große Leinwände hinter der Vorderseite, auf denen sich die Elemente befinden. Wenn man sie entfernt, geht es 2-mal schneller. Darüber muss ich noch nachdenken.

Dies ist die Leinwand, die ich meine:

1. die Vorderseite, auf der sich die Elemente befinden:


2. die Rückseite, auf der sich die Schaltflächen des Fensters (Kreuz, Minimierer), das Symbol und der Namenstext befinden. Das gesamte Fenster ist jedoch grün gefärbt, und es wurde Zeit darauf verwendet. Der Benutzer sieht jedoch nur die Rahmen und den Fensterkopf. Es stellt sich heraus, dass die Zeichnung an dieser Stelle umsonst ist:


 
Ich glaube, wenn du den unsichtbaren Teil der Rückseite nicht zeichnest, kannst du das erste Zeichnen des Fensters um mindestens ein Drittel beschleunigen. Ich kann es noch nicht mit Sicherheit sagen, du musst es überprüfen. Lass es nur den Rahmen und den Hut zeichnen. Überspringen Sie den Rest. Auf jeden Fall wird es einen Gewinn geben.