Galleria di interfacce utente scritte in MQL - pagina 54

 
C'è qualcosa che non va, Peter.
Un ritardo di un secondo è un ritardo proibitivo. La formazione dell'interfaccia più complicata per l'intera finestra non dovrebbe superare i 50 millisecondi.
Sembra proprio che la logica di rendering sia sovraccaricata dalle funzioni Update (in realtà ChartRedraw).
Per verificare questa ipotesi, inserire un contatore statico nella funzione Update della classe CCanvas (se la si utilizza) e stampare questo contatore, ad esempio quando count%100 == 0.
 

Ho anche una tela a schermo intero che viene ridisegnata completamente a ogni modifica, ma non richiede più di 50 ms....

La cosa più costosa è disegnare il testo. Pertanto, per non usare TextOut ogni volta, li memorizzo in array. Il risultato è molto più veloce.

 

La sfida principale è ora quella di dare all'utente un controllo programmatico sui controlli dell'interfaccia.

Tecnicamente, il compito non è difficile, perché nell'unione simbiotica del programma utente e del motore, il nucleo grafico è visibile a livello globale agli algoritmi di entrambe le parti. Il problema è che l'utente non sa come lavorare con il kernel. Non conosce e non capisce i principi della gestione degli elementi. Pertanto, è necessario fornire dei wrapper familiari, ovvero delle funzioni attraverso le quali l'utente può accedere al kernel e modificare i valori.

Ma c'è una sfumatura. I nomi delle funzioni sono troppo lunghi. Dopo tutto, ogni involucro funzionale di un elemento interattivo dovrebbe includere i nomi dell'elemento e della finestra. Questo è necessario per orientarsi tra i nomi. Altrimenti, l'utente si confonderà facilmente e non riuscirà a capire i propri involucri funzionali. Inoltre, i nomi possono coincidere e questo non è affatto positivo. È quindi necessario generare i nomi da due componenti: il nome dell'elemento e il nome della finestra. In questo modo non si crea confusione, ma i nomi dei wrapper diventano troppo lunghi. Soprattutto con il lato dei parametri passati. Inoltre, è necessario aggiungere dei prefissi alle funzioni per trovarle rapidamente tramite intellisense. Questo permette di filtrare efficacemente il campione a comparsa. Pratico. MA LUNGO!

Non solo. Il problema sono i parametri che vengono passati. La scelta è tra scrivere wrapper per ogni preimpostazione di get/set-properties di elementi e finestre, oppure ogni wrapper accetta l'intero elenco di parametri da una chiamata dell'utente. Questo è terribilmente scomodo. E soprattutto è difficile da spiegare.


C'è una via d'uscita ed è semplice. Ecco cos'è: un gruppo di proprietà astratte. Variabili globali visibili contemporaneamente dal lato del programma dell'utente e del motore.

Come funziona:

1. Tutti i wrapper di elementi e finestre si rivolgeranno alla funzione centrale e le passeranno i loro indici. Questa li utilizzerà per determinare l'elemento/finestra di destinazione della chiamata.

2. Dopo questa chiamata, l'utente imposterà l'insieme di proprietà astratte selezionate sui valori richiesti.

3. Chiamare la funzione centrale e passare la parola c.word "Set".

4. Central imposterà i valori delle proprietà astratte dalle loro variabili globali alle proprietà di destinazione del particolare elemento o finestra.

5. Aggiorna l'elemento o la finestra e azzera le proprietà astratte.

Tutto qui.

A mio parere, si tratta di una soluzione semplice ed efficiente che fornisce:

a) Facile accesso alle proprietà di qualsiasi elemento e finestra, senza passare parametri a una funzione che richiede una stretta coerenza. (Inoltre - limitazione del numero di parametri passati. E la chiamata risulta lunga e illeggibile).

c) Combinazione libera di un insieme di proprietà di elementi e finestre quando si impostano/ricevono valori in qualsiasi punto del programma.


Se qualcuno vede degli svantaggi, parli. Sarebbe bello coordinare questo problema prima del rilascio.

 
Nikolai Semko classe CCanvas (se la si utilizza) e stampare questo contatore, ad esempio quando count%100 == 0.

Nicholas, vale la pena di considerare che stiamo parlando di finestre GUI multiple. Nell'ultima versione ce n'erano 17. Ognuna ha centinaia di elementi. E ogni elemento è complesso. È costituito da un insieme di parti. Ogni dettaglio è una sezione della tela che è necessario attraversare e nel posto giusto per riempire con i valori necessari.

Se prendiamo il numero medio di finestre 10 (Papkov, ricordo, ordinò un'interfaccia di 11 finestre), e immaginiamo che ognuna abbia un insieme di elementi o una tabella, allora diventa chiaro perché il rendering completo dell'intera interfaccia richiede così tanto tempo. Vi ricordo che nell'interfaccia ci sono icone, ombre, gradiente di superficie, cornici varie.... quindi, in totale, il disegno completo di TUTTA l'interfaccia richiederà almeno 500 ms. Non si può fare nulla al riguardo.

Si può essere più veloci se si riduce il numero di finestre o si semplifica la grafica.

Per quanto riguarda il ridisegno, non ho quasi nessuna chiamata pura a ChartRedraw(). Il flag _ChartRedraw viene utilizzato ovunque. Quando questo flag è impostato, la funzione ChartRedraw() viene richiamata all' iterazione successiva del timer, dopo 25 ms. Cioè una volta sola. In questo modo evito di ridisegnare inutilmente. Solo in rari casi faccio una chiamata diretta a ChartRedraw().

 
Andrey Barinov #:

Inoltre la tela a schermo intero viene ridisegnata completamente ogni volta che cambio, ma non impiega più di 50 ms...

La cosa più costosa è disegnare il testo. Pertanto, per non utilizzare TextOut ogni volta, li memorizzo in array. Il risultato è molto più veloce.

Beh, la semplice aritmetica funziona: la somma delle aree di 10 - 17 finestre è molto più grande dello schermo intero. Concordo. Più il disegno aggiuntivo secondario necessario per creare ombre, icone, cornici....

E riguardo a TextOut controllerò e scriverò. Idea interessante.

 

Ho effettuato un test:

Sono entrato nel file 1.mqh del progetto demo e ho impostato tutte le finestre sul flag OOI. (apertura all'inizializzazione).

In totale - 15 finestre di dimensioni diverse e contenuti diversi. 2 finestre con barre di scorrimento e tabelle (quindi la loro tela è parzialmente nascosta e in realtà 2-3 volte più lunga. La lunghezza totale può essere valutata in base al rapporto tra cursore e barra di scorrimento). Area di disegno totale(minimo) 2000*1000 pixel. Ma credo che sia più di questo. Totale delle parti disegnate 1158 (controllato dopo la stampa del nucleo). Tempo di disegno completo di tutte le tele da zero da 1600 - a 1900 ms.

Anche in questo caso bisogna prestare attenzione alla quantità di dettagli che è stato necessario disegnare. Ombre, icone, gradienti, cornici, testi.


Il tempo di disegno è riportato nello screenshot:


 
Potrebbe esserci un modo per velocizzare il disegno. Rimuovere la base inferiore delle piattaforme delle finestre. Si tratta di grandi tele dietro il lato anteriore dove si trovano gli elementi. Se li si rimuove, il disegno sarà 2 volte più veloce. Dovrò pensarci su.
 
È possibile disegnare determinate finestre solo quando sono aperte? È raro avere una dozzina di finestre aperte contemporaneamente. Non è necessario farlo.
 
hini #:
Posso disegnare determinate finestre solo quando sono aperte? È raro avere decine di finestre aperte contemporaneamente. Non è necessario.

È l'unica cosa che succede, credetemi. Sto parlando solo del primo disegno di tutte le finestre dell'interfaccia in una volta sola. Il primo disegno è quello che richiede più tempo. Dopo di che, tutte le immagini sono già salvate e recuperate dalla memoria, se necessario. Con una sola chiamata vengono attaccate alle tele in pochi millisecondi. Questo non è un problema. Si vuole solo comprimere il tempo del primo disegno.

 
Реter Konow #:
Potrebbe esserci un modo per velocizzare il disegno. Rimuovere la base inferiore delle piattaforme delle finestre. Si tratta di grandi tele dietro il lato anteriore dove si trovano gli elementi. Se li si rimuove, il disegno sarà 2 volte più veloce. Dovrò pensarci su.

Questa è la tela di cui parlo:

1. Il lato anteriore dove si trovano gli elementi:


2. Il lato posteriore dove si trovano i pulsanti della finestra (croce, minimizzatore), l'icona e il testo del nome. Tuttavia, l'intera finestra è colorata di verde e su di essa è stato speso del tempo. Ma l'utente vede solo le cornici e l'intestazione della finestra. Si scopre che in questo punto il disegno è stato fatto invano: