Principale utente con più risposte
"Scrivere su grafico" più velocemente ??

Domanda
-
Ciao a tutti ,
- prelevo dei dati su file
- li seleziono per eliminare quelli che non mi interessano
- ordino secondo uno o più campi i dati rimasti
- costruisco un grafico che contiene un diagramma cartesiano
- e successivamente in coda al diagramma un elenco di dati formattati in colonne ( senza righe di separazione ) che può essere di centinaia di righe
Utilizzo :
public Bitmap FA4;
public Graphics g;FA4 = new Bitmap(nColonne, nRighe);
g = Graphics.FromImage(FA4);
g.DrawLine( .... );
g.DrawString( .... );
TUTTO BENE : funziona .
Però , io che sono incontentabile , sono un pò perplesso :
le fasi sopra elencate da 1 a 4 portano via il 5 % del tempo
mentre il punto 5 da solo si prende il 95 % del tempo di esecuzione .
E' normale ?? Grazie in anticipo a quelli che hanno del tempo da dedicare .
Risposte
-
Devi utilizzare un font a larghezza fissa, come i seguenti:
Courier New
Consolas
Lucida Console
così ogni carattere occupa lo stesso spazio in pixel, e tutte le colonne saranno perfettamente allineate.
- Contrassegnato come risposta vittorio 50 martedì 30 agosto 2022 07:30
-
Sì, i dati sono di tipo diverso, ma tu devi scriverli nella bitmap utilizzando DrawString(), quindi comunque andranno trasformati in stringhe. Quindi, crei una matrice stringa bidimensionale:
string[,] a = new string[100, 10];
e ci metti le tue colonne, prendendole come fai già e trasformando ogni elemento in stringa (aggiungendogli .ToString() alla fine).
Poi ricavi le righe della tua matrice, ad una ad una:
prima unisci gli elementi della riga della matrice (sono tutte stringhe), formattandoli per incolonnarli correttamente;
infine usi DrawString() per scrivere questa riga sulla bitmap.
...e così via, per tutte le righe della matrice.
- Contrassegnato come risposta vittorio 50 domenica 21 agosto 2022 13:58
Tutte le risposte
-
Ciao Vittorio,
come letto su altri forum riguardanti lo stesso argomento, ho provato a confrontare il metodo g.DrawString() con l'equivalente TextRenderer.DrawText(), e ho visto che DrawString va almeno 5 volte più veloce, e l'output di di 2000 righe impiega poco più di un secondo.
Sei sicuro che, invece, non sia il calcolo delle "colonne di dati" di cui tu parli, a richiedere parecchio tempo???
-
Grazie Fabio , come sempre per l'attenzione
la singola riga è costruita da diverse istruzioni ( una per ogni incolonnamento ) del tipo :
g.DrawString(Text, font, drawBrush, offColonna, nRiga, drawFormat);
ogni singola istruzione inserisce un tassello tipo "puzzle" nel contesto del grafico
offColonna e nRiga vengono ogni volta calcolate all'interno dell' istruzione
Posso fare di meglio ??
-
Certo:
escludendo che tu voglia cambiare tipo di approccio cioè senza utilizzare la bitmap e inserendo tutti i dati all'interno di una DataGridView, che ti consentirebbe di visualizzarli, prendendoli in tempo reale da una dataSource (es. un database), allora la cosa migliore che ti resta da fare è quella di metterli tutti dentro una matrice bidimensionale, così puoi mantenere l'inserimento "puzzle" che utilizzi adesso (scegliendo ogni volta: riga e colonna).
Poi, per scriverli nella tua bitmap, dovresti comporre la riga di stampa, mettendo insieme tutti gli elementi della stessa riga della matrice, e utilizzando un font a larghezza fissa (non proporzionale), altrimenti l'incolonnamento verrebbe irrimediabilmente perso.
Così potresti scrivere una riga per volta, e andresti velocissimo...
-
Ciao Fabio , è sempre un piacere leggerti .
Non so cos'è una DataGridView nè tantomeno come si usa .
I dati sono di tipo diverso ( interi, stringhe , double ... ) non saprei come inserirli in una matrice bidimensionale .
All’inizio del punto 5 mi trovo con un numero di colonne da visualizzare : totColonne
Ogni colonna contiene un solo tipo di dato . Però ogni colonna può avere dati di tipo diverso dalle altre colonne .
Per ogni colonna ho un puntatore al file che contiene tutti i dati ( secondo quel tipo di dato )
Ho anche un puntatore a memoria che contiene l’indirizzo ( n. di record ) dei soli dati selezionati ed ordinati per un totale di totRecord ( normalmente ridotto per la selezione fatta )
La costruzione del grafico avviene così , colonna dopo colonna :
for ( 1 to totColonne ) for ( 1 to totRecord )
leggo in memoria il record ( selezionato ed ordinato )
leggo nel puntatore del file il dato da visualizzare al record preso in memoria
metto il dato “puzzle” nel grafico : g.DrawString ( ….. ); In realtà è poco "puzzle" : costruisce colonna dopo colonna
Il font è fisso , ovviamente .
E’ questa parte che prende il 95 % del tempo .
Suggerimenti ??
-
Sì, i dati sono di tipo diverso, ma tu devi scriverli nella bitmap utilizzando DrawString(), quindi comunque andranno trasformati in stringhe. Quindi, crei una matrice stringa bidimensionale:
string[,] a = new string[100, 10];
e ci metti le tue colonne, prendendole come fai già e trasformando ogni elemento in stringa (aggiungendogli .ToString() alla fine).
Poi ricavi le righe della tua matrice, ad una ad una:
prima unisci gli elementi della riga della matrice (sono tutte stringhe), formattandoli per incolonnarli correttamente;
infine usi DrawString() per scrivere questa riga sulla bitmap.
...e così via, per tutte le righe della matrice.
- Contrassegnato come risposta vittorio 50 domenica 21 agosto 2022 13:58
-
-
Funziona Fabio ,
il vettore bidimensionale porta il tempo da 100 a 33 circa . E' già un bel risultato , mi sento molto "tonno" per non averci pensato ; era piuttosto semplice . Sono le ruggini dell' età .
Mi hai messo una bella pulce nell' orecchio con la soluzione DataGridView
Ho dato un' occhiata ma mi domando se sarebbe possibile :
Attualmente faccio un test con 8.000 righe e 10 colonne . Questo vuol dire che la tabella viene suddivisa in tre tronconi da 3900 righe ( per 16 pixel ) che affianco orizzontalmente .
Inoltre il documento ( grafico o altro che sia ) viene salvato su file per essere stampato e/o visionato all' occorrenza , quindi deve essere un documento uncico . DataGridView lo consente ??
Ancora grazie .
-
Ciao Fabio ,
l'idea è buona e , credo , fattibile però sto incontrando grosse difficoltà con la formattazione in colonne .
Uso .PadRight e PadLeft ma a giudicare dal risultato sembra che i caratteri corti " iii " e quelli lunghi " www " vengano trattati con diversi numeri di pixel e quindi non si allineano .
Dove sbaglio ??
-
Devi utilizzare un font a larghezza fissa, come i seguenti:
Courier New
Consolas
Lucida Console
così ogni carattere occupa lo stesso spazio in pixel, e tutte le colonne saranno perfettamente allineate.
- Contrassegnato come risposta vittorio 50 martedì 30 agosto 2022 07:30
-
-
Indirizzato a tutti ( in particolare a Fabio ) ,
riprendo l' argomento perchè se è vero che ho ridotto i tempi ad un terzo circa , rispetto a prima , è sorto un problema che , come al solito non so da che parte cominciare per risolverlo .
Prima inserivo singole stringhe come pezzi di "puzzle" nel grafico , adesso compongo tutta la riga e quindi la inserisco nel grafico.
Il grafico che ne deriva , oltre ad una prima parte con un diagramma cartesiano , prosegue con una successione di righe ognuna contenenti dati alfanumerici formattati per risultare incolonnati .
Il problema di cui parlavo sorge dalla volontà di evidenziare una ( o più ) colonna con carattere in "grassetto" .
Dovrei poter trasferire la singola stringa già in "grassetto" nella composizione delle singole righe oppure , a grafico già costruito ,
dovrei poter evidenziare uno spazio ( in questo case verticale largo x ed alto y ) in qualche modo .
Suggerimenti ??
-
Vittorio, buongiorno,
Chiederei che capisca una cosa. Il forum MSDN e costrito in tal modo, che ogni domanda dovrebbe contere un problema singolo - non tanti.
Per lei, esssi sono conessi, visto che si tratta di un singolo progetto. Per chiunque che cerca invece, potrebbero non essere. Poi, ci sono 8, 10, 15 e piu' risposte in un thread, che crea un casino.Gentilmente vorrei chiedere, che ogni domanda, non uguale a quella iniziale, venne chiesta in un thread separato.
Grazie
• Microsoft offre questo servizio gratuitamente, per aiutare gli utenti e aumentare il database dei prodotti e delle tecnologie. Il contenuto fornito “as is“ non comporta alcuna responsabilità da parte dell’azienda.