none
"Scrivere su grafico" più velocemente ?? RRS feed

  • Domanda

  • Ciao a tutti ,

    1. prelevo  dei  dati  su  file
    2. li seleziono  per  eliminare quelli che non mi interessano
    3. ordino secondo uno o più campi  i  dati  rimasti
    4. costruisco  un  grafico  che  contiene  un diagramma cartesiano
    5. 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 .

    venerdì 19 agosto 2022 13:14

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
    lunedì 29 agosto 2022 18:01
  • 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
    domenica 21 agosto 2022 13:24

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???

    venerdì 19 agosto 2022 20:26
  • 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  ??

    sabato 20 agosto 2022 07:52
  • 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...

    sabato 20 agosto 2022 18:43
  • 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  ??

    domenica 21 agosto 2022 09:28
  • 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
    domenica 21 agosto 2022 13:24
  • Vero , come sempre le soluzioni sono nel semplice

    Ci provo , è l'unico modo per sapere se risparmierò tempo .

    domenica 21 agosto 2022 14:01
  • 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 .

    lunedì 22 agosto 2022 08:03
  • 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  ??

    lunedì 29 agosto 2022 14:52
  • 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
    lunedì 29 agosto 2022 18:01
  • GRANDE   Fabio ,

    FUNZIONA  !!!!!

    martedì 30 agosto 2022 07:32
  • 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 ??

    sabato 10 settembre 2022 10:29
  • 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.

    lunedì 12 settembre 2022 09:13
    Moderatore