Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 11
  1. #1
    Utente di HTML.it
    Registrato dal
    Jan 2014
    Messaggi
    305

    Colorare riga jtable in seguito ad un evento

    Allora ho letto che per disegnare o colorare una cella della jtable devo scrivere un renderer che implementa TableCellRenderer o far estendere DefaultTableCellRender.
    Se volessi far si che il disegno delle celle avviene in seguito ad un evento tipo la pressione di un bottone , oppure come evento programmato con timertask come potrei fare? perchè ho letto che il metodo getTableCellRendererComponent(....), viene chiamato automaticamente dalla JTable quando deve disegnare le celle, supponendo che la JTable è gia sta disegnata ,ed è giaà aperta in un frame, come posso colorarne una riga in seguito a un evento?

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da linux_r Visualizza il messaggio
    Allora ho letto che per disegnare o colorare una cella della jtable devo scrivere un renderer che implementa TableCellRenderer o far estendere DefaultTableCellRender.
    Dipende ... nel senso che non sempre è necessario creare un apposito renderer. Ad esempio se si vogliono colorare alternativamente le righe della tabella (quindi indipendentemente dai renderer e dai dati), la cosa più semplice è estendere JTable e ridefinire il metodo prepareRenderer.

    Quote Originariamente inviata da linux_r Visualizza il messaggio
    Se volessi far si che il disegno delle celle avviene in seguito ad un evento tipo la pressione di un bottone , oppure come evento programmato con timertask come potrei fare?
    Chiaramente bisogna chiedere un "refresh" della cella (almeno di quella implicata).
    Il modo più banale (ma drastico) e fare un repaint() sulla tabella .... ma così aggiorna tutto! Un'altra possibilità è invocare tableChanged su JTable passando un TableModelEvent che descrive l'update di una singola cella.
    Non è molto "bello" (e generalmente non si fa così esplicitamente), perché JTable implementa TableModelListener (quindi tableChanged) principalmente per ricevere le notifiche dal table model.

    Altre possibilità devo andarle a verificare ...
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Utente di HTML.it
    Registrato dal
    Jan 2014
    Messaggi
    305
    ci sono novita??

  4. #4
    Utente di HTML.it
    Registrato dal
    Mar 2012
    Messaggi
    28
    Io ho risolto con una soluzione semplice, che ho utilizzato tante volte... In pratica puoi utilizzare una matrice "parallela" di booleani in cui riporti quale cella colorare... Forse uno snippet è più comprensibile di tante parole:

    codice:
    Object rowData[][] = new Object[nrRow][nrCol];
     
    boolean redColoring[][] = new boolean[nrRow][nrCol];
      
    String columnNames[] = new String[nrCol];
    
    JTable table = new JTable(rowData, columnNames);
        
        table.setDefaultRenderer(Object.class, new TableCellRenderer() {
        
          @Override
          public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column){
            
            JLabel label = new JLabel(value.toString());
            
            label.setOpaque(true);
    
            if (redColoring[row][column]) {
            
              label.setBackground(Color.RED);
            
            }
                   
            return label;
                   
            }
        
        });
    A questo punto ti gestisci il vettore di booleani, alzando o abbassando l'elemento che vuoi colorare. In soldoni, quando si scatena l'evento che aspetti fai un semplice

    codice:
    redColoring[h][k] = true;
    e vedi che la cella (h,k) si colora immediatamente di rosso.

  5. #5
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da javatore Visualizza il messaggio
    codice:
        table.setDefaultRenderer(Object.class, new TableCellRenderer() {
        
          @Override
          public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column){
            
            JLabel label = new JLabel(value.toString());
            
            label.setOpaque(true);
    
            if (redColoring[row][column]) {
            
              label.setBackground(Color.RED);
            
            }
                   
            return label;
                   
            }
        
        });
    Le principali questioni su questo codice sono:
    - innanzitutto restituisci un nuovo JLabel ad ogni aggiornamento della cella. I renderer "buoni" normalmente giocano molto al "risparmio" e restituiscono sempre la stessa identica istanza del componente. E anzi la classe del renderer generalmente è il componente stesso!
    - non tratti per niente i flag isSelected/hasFocus.

    Se andassi a sbirciare nel sorgente di DefaultTableCellRenderer scopriresti che già solo questo renderer di "default" fa molte, molte più cose e inoltre sovrascrive "vuoti" una serie di metodi per ragioni di performance.
    Ultima modifica di andbin; 22-05-2014 a 12:39
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  6. #6
    Utente di HTML.it
    Registrato dal
    Jan 2014
    Messaggi
    305
    Ecco la mia soluzione almeno parzialmente , perchè non funzione ancora bene:
    codice:
    package jcallremember.client;
    
    
    import jCallRemember.libreria.ClienteDB;
    import java.awt.Color;
    import java.lang.reflect.InvocationTargetException;
    import java.util.concurrent.locks.ReentrantLock;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.swing.SwingUtilities;
    
    
    /**
     *
     * @author Linux
     */
    public final class TaskAppuntamento extends java.util.TimerTask {
        private static ReentrantLock lock=new ReentrantLock();
        private FormSchedaCliente F;
        private Thread T;
        public ClienteDB getInfo() {
            return info;
           
        }
    
    
        public void setInfo(ClienteDB info) {
            this.info = info;
        }
        private ClienteDB info;
    
    
        TaskAppuntamento(ClienteDB cliente) {
            T=new Thread(this);
            this.setInfo(cliente);
        }
        public void start(){
            T.start();
        }
        public void threadTimer(){
            F = new FormSchedaCliente(this.getInfo());
            SwingUtilities.invokeLater(F);
        }
        public void threadT(){
            try {
                    
                    while (!F.isSceltaEffettuata()) {
                        lock.lock();
                        int row = FormClientiOggi.getInstance().getModelTable().findRow(info);
                        try {
                            FormClientiOggi.getInstance().getTable().setRowSelectionInterval(row, row);
                            FormClientiOggi.getInstance().getTable().setSelectionBackground(Color.MAGENTA);
                            Thread.sleep(1000);
                            FormClientiOggi.getInstance().getTable().setSelectionBackground(Color.CYAN);
                             FormClientiOggi.getInstance().getTable().repaint();
                        } finally {
                            lock.unlock();
                        }
                    }
    
    
                } catch (InterruptedException ex) {
                    Logger.getLogger(TaskAppuntamento.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        
        @Override
        public void run() {
            if(Thread.currentThread().getId()!=this.T.getId()){
                
                this.threadTimer();
                this.start();
                
            }
            else if (Thread.currentThread().getId() == T.getId()){
                this.threadT();
            }
        }
    
    
    }
    il thread del Timer si occupa solo di creare il form e di dire all'edt di disegnarlo, mentre l'altro thread si occupa di gestire il colore delle righe della jtable, ogni formschedacliente, fa riferimento a un cliente nella jtable, quando il form viene creato le righe del corrispondente cliente dovrebbero
    lampeggiare.. Pero secondo me c'è qualche problema di sincronizzazione, considerando che Jtable non è thred safe ,e quel FormClientiOggi è un singleton.. help me please
    Inoltre la seconda volta non me lo colora anche se ho testato che l'istruzione viene eseguita,ovvero non colora di blu, ma il ciclo si ripete
    Vorrei far lampeggiare le righe contemporaneamente anche nel caso di più task.
    ho anche una domanda ma se invoco repaint() su un istanza jtable, il repaint mica è eseguito dall'edt?
    Ultima modifica di linux_r; 22-05-2014 a 12:50

  7. #7
    Utente di HTML.it
    Registrato dal
    Jan 2014
    Messaggi
    305
    Ho scritto questo renderer per la tabella, funziona bene se estendo JPanel, no JLabel (perche?) , l'unico problema è che colora le righe ma cancella il contenuto delle celle. Praticamente dovrebbe colorare le celle in base al contenuto
    codice:
    /*
     * To change this license header, choose License Headers in Project Properties.
     * To change this template file, choose Tools | Templates
     * and open the template in the editor.
     */
    package jCallRemember.libreria;
    
    
    import java.awt.Color;
    import java.awt.Component;
    import javax.swing.JPanel;
    import javax.swing.JTable;
    import javax.swing.table.TableCellRenderer;
    
    
    /**
     *
     * @author Linux
     */
    public class RendererFormListaClienti extends JPanel implements TableCellRenderer {
    
    
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value,
                boolean isSelected, boolean hasFocus, int row, int column) {
            setOpaque(true);
            switch (table.getValueAt(row, 8).toString()) {
                case "PR":
                    setBackground(Color.yellow);
                    break;
                case "OK":
                    setBackground(Color.GREEN);
                    break;
                default:
                    setBackground(Color.RED);
                    break;
            }
            return this;
    
    
        }
    
    
    }
    /*
    Ultima modifica di linux_r; 28-05-2014 a 10:43

  8. #8
    Utente di HTML.it
    Registrato dal
    Jan 2014
    Messaggi
    305
    public void setDefaultRenderer(Class<?> columnClass,
    TableCellRenderer renderer)Sets a default cell renderer to be used if no renderer has been set in a TableColumn. If renderer is null, removes the default renderer for this column class.
    Parameters:columnClass - set the default cell renderer for this columnClassrenderer - default cell renderer to be used for this columnClass


    Ho risolto anche il problema precedente adesso il mio problema è questo praticamente se invoco il metodo sopra , e gli passo come primo parametro Object.class, il renderer non funziona per Integer , mentre per String si, come mai ?

  9. #9
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da linux_r Visualizza il messaggio
    Ho risolto anche il problema precedente adesso il mio problema è questo praticamente se invoco il metodo sopra , e gli passo come primo parametro Object.class, il renderer non funziona per Integer , mentre per String si, come mai ?
    JTable usa questa logica per determinare il renderer da usare per una cella:
    1) C'è un renderer assegnato specificatamente alla colonna (TableColumn)? Sì: usa quello. No: chiede il renderer a getDefaultRenderer passando il "column class" (da getColumnClass).

    2) getDefaultRenderer prima cerca un renderer per quel class X, se non c'è allora per la superclasse di X, se non c'è per la superclasse della superclasse di X, ecc...

    JTable ha già di serie dei renderer predefiniti per vari tipi tra cui Object e Number. Se registri un renderer di default per Object (sostituendo quindi quello di serie), funziona per valori String (perché non ce n'é uno di serie per String) ma non per valori Integer (perché prende il renderer di serie per Number).
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  10. #10
    Utente di HTML.it
    Registrato dal
    Jan 2014
    Messaggi
    305
    dove posso leggere ste cose??

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.