DefaultTableCellRenderer non capisco..

di il
12 risposte

DefaultTableCellRenderer non capisco..

Qualcuno saprebbe dirmi perchè questo codice NON mi colora le scritte delle celle?

routine..:

// for nidificata all'interno di una lettura di record da database (quindi questa for viene 
// ripetuta ad ogni record letto nel database)
                    for (int x=0; x<2; x++)
                    {
                        if ("A".equals(Stato_TempRoutine))
                        {
                            jTM.getColumnModel().getColumn(x).setCellRenderer(new CustomRendererCYAN());                        
                        }  
                        else
                        {
                            jTM.getColumnModel().getColumn(x).setCellRenderer(new CustomRendererNULL());                         
                        }                           
                    }
classi chiamate..:

    class CustomRendererCYAN extends DefaultTableCellRenderer 
    {
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
        {
            Component cellComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            cellComponent.setForeground(Color.CYAN); 
            return cellComponent; 
        }
    }  
    
    class CustomRendererNULL extends DefaultTableCellRenderer 
    {
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
        {
            Component cellComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            cellComponent.setForeground(null); 
            return cellComponent; 
        }
    }  
ovviamente da debug ho la conferma che ci sono record del database che soddisfano questa if ("A".equals(Stato_TempRoutine)) ed altri che non la soddisfano.

Grazie!

12 Risposte

  • Re: DefaultTableCellRenderer non capisco..

    LucaM ha scritto:


    
    // for nidificata all'interno di una lettura di record da database (quindi questa for viene 
    // ripetuta ad ogni record letto nel database)
                        for (int x=0; x<2; x++)
                        {
                            if ("A".equals(Stato_TempRoutine))
                            {
                                jTM.getColumnModel().getColumn(x).setCellRenderer(new CustomRendererCYAN());                        
                            }  
                            else
                            {
                                jTM.getColumnModel().getColumn(x).setCellRenderer(new CustomRendererNULL());                         
                            }                           
                        }
    
    Dato che questo codice è eseguito per ciascuna riga, allora NON ha granché senso. Il renderer è unico per l'intera colonna .. non per ciascuna cella o riga.
  • Re: DefaultTableCellRenderer non capisco..

    ..

    In che senso? allora come faccio a colorare le righe a seconda di un "value" di un'altra colonna ma sulla stessa riga (record)?
  • Re: DefaultTableCellRenderer non capisco..

    LucaM ha scritto:


    In che senso?
    Che "di serie", cioè per come è fatto JTable, la riga non conta per la scelta del renderer. In realtà tutto il nocciolo di questo sta nel getCellRenderer(int row, int column) di JTable che in modo predefinito ignora il parametro row nella scelta del renderer.
    Ma tecnicamente questa logica sarebbe ridefinibile (anche se in genere non si fa praticamente mai).

    LucaM ha scritto:


    allora come faccio a colorare le righe a seconda di un "value" di un'altra colonna ma sulla stessa riga (record)?
    Questo è uno dei casi più complessi, perché dipende dai dati e su un'altra colonna rispetto a quella in gestione da un certo renderer.

    Se la scelta es. del background non dipendesse dai dati, si può ridefinire il prepareRenderer di JTable e infatti è quanto ho fatto nel mio esempio Rows Background Pattern.

    Se invece una caratteristica della cella dipende da un'altra cella (su stessa o diversa riga), allora dovrebbe essere il renderer che va a prendere il dato (e hai tutti gli elementi per farlo) ed agisce di conseguenza. Questo è meno bello come design, perché "lega" il renderer ad una certa struttura e conoscenza del model. Ma se lo si deve fare ... lo si fa anche.
  • Re: DefaultTableCellRenderer non capisco..

    Caspita..

    andbin ha scritto:


    Se invece una caratteristica della cella dipende da un'altra cella (su stessa o diversa riga), allora dovrebbe essere il renderer che va a prendere il dato (e hai tutti gli elementi per farlo) ed agisce di conseguenza...
    Cioè prima creo la tabella completa e poi al render gli si può dire di estrarre un "value" a tal row/column e quindi con una if decidere come colorare la cella, ed il tutto chiamando il render in un ciclo for row.. con nidificato all'interno un ciclo for column.. ?

    Mazza..
  • Re: DefaultTableCellRenderer non capisco..

    Intanto l'effetto finale vorrebbe essere come da tuo esempio

    Noname.png
    Noname.png

  • Re: DefaultTableCellRenderer non capisco..

    Che poi sbirciando nel tuo codice.. sembrerebbe esserci già la risposta x mè
    
    	@Override
    	public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
    		// Invokes the standard implementation of prepareRenderer in JTable.
    		Component rendererComponent = super.prepareRenderer(renderer, row, column);
    
    		if (!isCellSelected(row, column)) {
    			// If the cell is *not* selected, then calculates the index into
    			// the pattern array and sets the background of the component.
    			// If the cell is selected, the component certainly already has an
    			// appropriate background color configured by the renderer.
    			int index = row % rowColorsPattern.length;
    
    			rendererComponent.setBackground(rowColorsPattern[index]);
    		}
    
    		return rendererComponent;
    	}
    
    Cosi' come chiami la funzione isCellSelected si dovrebbe poter chiamare value (se esiste questa funzione..). C'è un topic dove spieghi il codice?
  • Re: DefaultTableCellRenderer non capisco..

    LucaM ha scritto:


    ed il tutto chiamando il render in un ciclo for row.. con nidificato all'interno un ciclo for column.. ?
    NO assolutamente. Il renderer viene invocato ogni volta che una cella deve essere aggiornata. E tipicamente i renderer forniscono sempre la stessa identica istanza del componente, solo settato diversamente e poi letteralmente "stampato" nella cella a mo' di timbro o stampino.
    Questo perché l'obiettivo è giocare molto al risparmio di risorse.

    LucaM ha scritto:


    Intanto l'effetto finale vorrebbe essere come da tuo esempio
    Ok ma .. nel mio esempio la colorazione di background non dipende dai dati (solo dall'indice di riga).
  • Re: DefaultTableCellRenderer non capisco..

    Questo codice copiato da internet e da mè riadattato alla bene in meglio (dalle mie non complete conoscenze di java.. ) sembrerebbe colorare le righe a seconda del contenuto di una cella, è già qualcosa ma vorrei arrivare a colorare le singole celle(row,column)
    
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.border.LineBorder;
    import javax.swing.table.*;
    
    public class TablePrepareRenderer extends JFrame {
    
        private static final long serialVersionUID = 1L;
        private JTable table;
        private String tableFlag = "";
    
        public TablePrepareRenderer() {
            Object[] columnNames = {"Field1", "Field2", "Flag"};
            Object[][] data = 
            {
                {"1", "2", "A"},
                {"1", "2", "A"},
                {"1", "2", "F"},
                {"1", "2", "R"},
                {"1", "2", "R"},
                {"1", "2", "C"},
                {"1", "2", "T"},
                {"1", "2", "X"},
            };
    
            DefaultTableModel model = new DefaultTableModel(data, columnNames) 
            {
                private static final long serialVersionUID = 1L;
    
                @Override
                public Class getColumnClass(int column) {
                    return getValueAt(0, column).getClass();
                }
            };
    
            table = new JTable(model) 
            {
                private static final long serialVersionUID = 1L;
    
                @Override
                public Component prepareRenderer(TableCellRenderer renderer, int row, int column) 
                {
                    Component c = super.prepareRenderer(renderer, row, column);
                    if (!isRowSelected(row)) {
                        if (table.getColumnCount() >= 0) {
                            tableFlag = (String) table.getValueAt(row, 2);
                            if ((tableFlag != null) && 
                                (!tableFlag.isEmpty()))    
                            {
                                c.setFont(new Font("Serif", Font.BOLD, 12));
                                c.setBackground(Color.RED);
                                switch(tableFlag)
                                {
                                    case "A":
                                        c.setBackground(Color.LIGHT_GRAY);
                                        break;  
                                    case "T":
                                        c.setBackground(Color.LIGHT_GRAY);
                                        break;                          
                                    case "F":
                                        c.setBackground(Color.blue);
                                        break;                          
                                    case "R":
                                        c.setBackground(Color.GREEN);
                                        break;       
                                    case "C":
                                        c.setBackground(Color.GREEN);
                                        break;                          
                                }
                            }
                        }
                    }
                    if (isRowSelected(row) && isColumnSelected(column)) {
                        ((JComponent) c).setBorder(new LineBorder(Color.red));
                    }
                    return c;
                }
            };
            table.setPreferredScrollableViewportSize(table.getPreferredSize());
            JScrollPane scrollPane = new JScrollPane(table);
            getContentPane().add(scrollPane);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    TablePrepareRenderer frame = new TablePrepareRenderer();
                    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
                    frame.pack();
                    frame.setLocation(150, 150);
                    frame.setVisible(true);
                }
            });
        }
    }
    


    Medito anche l'abbandono di jtable a favore di un'array di textfield
  • Re: DefaultTableCellRenderer non capisco..

    LucaM ha scritto:


    è già qualcosa ma vorrei arrivare a colorare le singole celle(row,column)
    Innanzitutto, mettere della logica molto particolare per configurare le celle nel renderer oppure nel prepareRenderer, tecnicamente cambia poco. Cambia dal punto di vista del "design", cioè chi/dove è legato alla conoscenza sulla struttura dei dati nel model.

    Comunque, se noti nel codice che hai postato, il prepareRenderer usa column solo per invocare il prepareRenderer "super" e per invocare isColumnSelected. Insomma, detto in altro modo, qualunque aspetto particolare imposta sul Component, è per la riga intera, visto che per questo non fa distinzione sulla colonna!
    E quindi alla fin fine si tratta solo di "logica" che devi applicare tu.

    LucaM ha scritto:


    Medito anche l'abbandono di jtable a favore di un'array di textfield
    Uhm ..... bruttino (graficamente parlando) e avresti sicuramente MOLTO da scrivere per gestirlo. Oltre al fatto che non offriresti all'utente alcuna facility per ridimensionare le colonne, selezionare righe e altro. E se volessi offrire aspetti come questi, dovresti scrivere almeno 10 volte tanto e non sarebbe banale.
  • Re: DefaultTableCellRenderer non capisco..


    In questo esempio c'è tutto quello che mi serve? (cosi' me lo studio) http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/examples/components/TableRenderDemoProject/src/components/TableRenderDemo.java
  • Re: DefaultTableCellRenderer non capisco..

    LucaM ha scritto:


    In questo esempio c'è tutto quello che mi serve?
    A dire il vero ... no. Non implementa un renderer custom, né personalizza le caratteristiche del Component fornito dal renderer. Usa solo dei renderer pre-esistenti per ottenere informazioni sulla larghezza e poi in setUpSportColumn usa un DefaultTableCellRenderer solo per poter settare un tooltip.
  • Re: DefaultTableCellRenderer non capisco..

    Mazza.. sai leggere il codice come fosse un libro aperto. COMPLIMENTI

    E grazie
Devi accedere o registrarti per scrivere nel forum
12 risposte