Alterações no Registro de uma JTable

Aew Galera to precisando de uma ajudinha com JTable no NetBeans 6.5…

tenho uma JTable populada com registros do banco de dados (MySQL)…agora preciso fazer umas alteraçoes, por exemplo tenho alguns opçoes onde quando o usuario selecionar um JToggleButon e depois disparar um evento (duplo clique, um clique…) na célula escolhida da tabela, mude de cor o conteudo escrito nela, mas isso tem que ser salvo e quando eu carregar novamente do banco essas mudanças sejam carregadas corretamentes onde eu mudei de cor.

quanto a carregar com as mudanças certas eu ja tenho qse q resolvido oq eu mais preciso saber é como fazer mudar de cor o escrito das celulas.

Obrigado.

Para mudar de cor você vai ter que sobrescrever o renderer da JTable.
Agora como você vai fazer para armazenar e restaurar a determinada cor é com você.

entao soh me eplica uma coisa qdo se fala em renderer de uma jTable…seria os metodos da classe??

usando o foreground eu consigo apenas deixar a linha inteira dessa cor…eu teria q reescrever esse metodo entao???

Obrigado.

Na verdade, não :slight_smile:

Quando falei em Renderer, me referi ao responsável por gerar os componentes que serão exibidos em cada uma das células da JTable. Este Renderer é uma implementação da interface TableCellRenderer e, caso você não especifique nenhuma, a JTable utilizará o renderer padrão (que, se eu não me engano, gera JLabels).
Ou seja, o que você precisa fazer é: implementar a interface TableCellRenderer (através de uma classe, classe anônima, classe interna) e no método getTableCellRendererComponent(…) fazer a verificação e configurar a cor conforme desejado.
Não esqueça de configurar seu renderer como renderer padrão da JTable:

table.setDefaultRenderer(Object.class, implementacaoDoRenderer);

Pesquise sobre TableCellRenderer e getTableCellRendererComponent, você vai encontrar bastante coisa.

eu criei a seguinte classe

public class Colorir extends JLabel implements TableCellRenderer{
  public void ColoreSelecionado() {
      
  }

    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column){

     if(Integer.parseInt(value.toString()) < 20){
       setForeground(Color.BLUE);
     }
     else{
       setForeground(Color.BLACK);
     }

     setText(value.toString());

     return this;
  }

e para usar em meu formulario

      TableCellRenderer tcr = new Colorir();
      TableColumn column =
      tbHorarios.getColumnModel().getColumn(1);
      column.setCellRenderer(tcr);

mas nao intendo o seguinte nessa funçao eu soh consigo verificar o valor da celula que se for < 20 fica de tal cor…eu não posso alterar os parametros passados pois eh uma interface certo??

como aplico isso em um evento por exemplo no Pressed do mouse?

ta dificil de intender isso usando o netbeans :oops:

Está indo pelo caminho certo cara.
Na verdade você não invoca o getTableCellRendererComponent, a JTable invoca: No momento em que a JTable vai desenhar/redesenhar as células ele requisita ao CellRenderer qual componente deverá ser denhado na determinada célula.
Por isso, neste método você apenas verifica o que deve ser desenhado.

Você quer dizer alterar a quantidade de parâmetros? Incluir ou retirar parâmetros? Isto não vai ser possível, a não ser que você faça alegorias do tipo extender a classe JTable e modificar manualmente as chamadas ao getCellRenderer, o que acho que não é recomendado.

certo mas nao entendi muito bem ainda…outras linguagens trabalhar com tabelas é totalmente diferente… :smiley:

mas tipo esse Renderer seria como se eu estivesse mudando os padroes da DefaultTable??..estaria usando o AbstractModel??

teria como me explicar algum exemplo em codigo??

eu li toda documentaçao no java.sun sobre esse assunto mas ainda estou meio perdido nao peguei o conceito ainda.

mais uma vez Obrigado.

Não, o renderer não tem relação nenhuma com o model.

O TableModel é a ligação entre a tabela e os dados que ela irá exibir (camada de controle).
O renderer, como citei anteriormente, é responsável apenas por gerar o que será exibido.
Pensando num processo macro, funciona mais ou menos assim:
Uma atualização das informações da jtable é disparada (fireTableCellUpdated). A jtable atualizará as informações de todas as céluas, ou de apenas uma célula específica. Para ambos os casos, o que a JTable fará é consultar o novo valor da célula no tableModel (getValueAt) e passará este valor para o renderer decidir qual componente será desenhado na tela através do método getTableCellRendererComponent. Neste, o parâmetro value representa valor obtido do table model. O renderer então cria o componente em questão e envia o mesmo para a JTable, que ajusta o componente na célula.

Você leu bastante hein?! :lol:

na verdade toda parte de exemplo de how to use JTable… :smiley:
mas to comessando a intender não sabia que era tão extenso o conteudo desse JTable em JAVA…

segue um outro exemplo onde tenho algumas duvidas

public class TableRenderDemo extends JPanel {
    private boolean DEBUG = false;

    public TableRenderDemo() {
        super(new GridLayout(1,0));

        JTable table = new JTable(new MyTableModel());
        table.setPreferredScrollableViewportSize(new Dimension(500, 70));
        table.setFillsViewportHeight(true);

        //Create the scroll pane and add the table to it.
        JScrollPane scrollPane = new JScrollPane(table);

        //Set up column sizes.
        initColumnSizes(table);

        //Fiddle with the Sport column's cell editors/renderers.
        setUpSportColumn(table, table.getColumnModel().getColumn(2));

        //Add the scroll pane to this panel.
        add(scrollPane);
    }

    /*
     * This method picks good column sizes.
     * If all column heads are wider than the column's cells'
     * contents, then you can just use column.sizeWidthToFit().
     */
    private void initColumnSizes(JTable table) {
        MyTableModel model = (MyTableModel)table.getModel();
        TableColumn column = null;
        Component comp = null;
        int headerWidth = 0;
        int cellWidth = 0;
        Object[] longValues = model.longValues;
        TableCellRenderer headerRenderer =
            table.getTableHeader().getDefaultRenderer();

        for (int i = 0; i &lt; 5; i++) {
            column = table.getColumnModel().getColumn(i);

            comp = headerRenderer.getTableCellRendererComponent(
                                 null, column.getHeaderValue(),
                                 false, false, 0, 0);
            headerWidth = comp.getPreferredSize().width;

            comp = table.getDefaultRenderer(model.getColumnClass(i)).
                             getTableCellRendererComponent(
                                 table, longValues[i],
                                 false, false, 0, i);
            cellWidth = comp.getPreferredSize().width;

            if (DEBUG) {
                System.out.println(&quot;Initializing width of column &quot;
                                   + i + &quot;. &quot;
                                   + &quot;headerWidth = &quot; + headerWidth
                                   + &quot;; cellWidth = &quot; + cellWidth);
            }

            column.setPreferredWidth(Math.max(headerWidth, cellWidth));
        }
    }

    public void setUpSportColumn(JTable table,
                                 TableColumn sportColumn) {
        //Set up the editor for the sport cells.
        JComboBox comboBox = new JComboBox();
        comboBox.addItem(&quot;Tolerancia&quot;);
        comboBox.addItem(&quot;Livre&quot;);
        comboBox.addItem(&quot;Automatico&quot;);
        sportColumn.setCellEditor(new DefaultCellEditor(comboBox));

        //Set up tool tips for the sport cells.
        DefaultTableCellRenderer renderer =
                new DefaultTableCellRenderer();
        renderer.setToolTipText(&quot;Click for combo box&quot;);
        sportColumn.setCellRenderer(renderer);
    }

    class MyTableModel extends AbstractTableModel {
        private String[] columnNames = {&quot;First Name&quot;,
                                        &quot;Last Name&quot;,
                                        &quot;Sport&quot;,
                                        &quot;# of Years&quot;,
                                        &quot;Vegetarian&quot;};
        private Object[][] data = {
            {&quot;Mary&quot;, &quot;Campione&quot;,
             &quot;Snowboarding&quot;, new Integer(5), new Boolean(false)},
            {&quot;Alison&quot;, &quot;Huml&quot;,
             &quot;Rowing&quot;, new Integer(3), new Boolean(true)},
            {&quot;Kathy&quot;, &quot;Walrath&quot;,
             &quot;Knitting&quot;, new Integer(2), new Boolean(false)},
            {&quot;Sharon&quot;, &quot;Zakhour&quot;,
             &quot;Speed reading&quot;, new Integer(20), new Boolean(true)},
            {&quot;Philip&quot;, &quot;Milne&quot;,
             &quot;Pool&quot;, new Integer(10), new Boolean(false)}
        };

        public final Object[] longValues = {&quot;Sharon&quot;, &quot;Campione&quot;,
                                            &quot;None of the above&quot;,
                                            new Integer(20), Boolean.TRUE};

        public int getColumnCount() {
            return columnNames.length;
        }

        public int getRowCount() {
            return data.length;
        }

        public String getColumnName(int col) {
            return columnNames[col];
        }

        public Object getValueAt(int row, int col) {
            return data[row][col];
        }

        /*
         * JTable uses this method to determine the default renderer/
         * editor for each cell.  If we didn't implement this method,
         * then the last column would contain text (&quot;true&quot;/&quot;false&quot;),
         * rather than a check box.
         */
        public Class getColumnClass(int c) {
            return getValueAt(0, c).getClass();
        }

        /*
         * Don't need to implement this method unless your table's
         * editable.
         */
        public boolean isCellEditable(int row, int col) {
            //Note that the data/cell address is constant,
            //no matter where the cell appears onscreen.
            if (col &lt; 4) {
                return false;
            } else {
                return true;
            }
        }

        /*
         * Don't need to implement this method unless your table's
         * data can change.
         */
        public void setValueAt(Object value, int row, int col) {
            if (DEBUG) {
                System.out.println(&quot;Setting value at &quot; + row + &quot;,&quot; + col
                                   + &quot; to &quot; + value
                                   + &quot; (an instance of &quot;
                                   + value.getClass() + &quot;)&quot;);
            }

            data[row][col] = value;
            fireTableCellUpdated(row, col);

            if (DEBUG) {
                System.out.println(&quot;New value of data:&quot;);
                printDebugData();
            }
        }

        private void printDebugData() {
            int numRows = getRowCount();
            int numCols = getColumnCount();

            for (int i=0; i &lt; numRows; i++) {
                System.out.print(&quot;    row &quot; + i + &quot;:&quot;);
                for (int j=0; j &lt; numCols; j++) {
                    System.out.print(&quot;  &quot; + data[i][j]);
                }
                System.out.println();
            }
            System.out.println(&quot;--------------------------&quot;);
        }
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame(&quot;TableRenderDemo&quot;);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        TableRenderDemo newContentPane = new TableRenderDemo();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

eu nao intendo como ele consegue usar esse isCellEditable eu tentei fazer esse modelo em uma classe separada e depois chama la em um JFrame mas mesmo assim nao consegui usar esse metodo…o comboBox na coluna da tabela consegui blezinha, oq eu nao intendo eh pq eh criado uma class dentro de outra class

o ruim eh ficar fazendo isso em netbeans ae que me perco mais ainda… :?

Bah cara, quanto código! :slight_smile:

Vou ser bem sincero dizendo que não analisei o código todo, mas pelo que percebi, ele cria uma classe dentro de outra pra encapsular o código. Estas classes são chamadas de inner classes. Isto é bastante comum, mas em proporções menores. Encapsular muitas classes não é recomendado como boa prática de programação.
No caso o autor provavelmente criou as classes dentro de uma principal para simplificar o exemplo e poder colocá-lo dentro de um único arquivo java.

Você precisa implementar o isCellEditable dentro de uma classe que implemente AbstractTableModel ou extenda DefaultTableModel (não muito recomendado). Depois você precisa configurar este modelo como o padrão da jtable através do método

jtable.setModel(tableModel);

Você fez isso?

Mais uma sugestão: você está estudando a utilização da JFrame, certo? Uma sugestão que te dou é deixar o NB de lado por alguns instantes e desenvolver alguns projetinhos no Eclipse. Com isso você vai ser obrigado a escrever todas as configurações e classes utilizadas (claro que o Eclipse vai te ajudar em alguns pontos). Isto pode parecer doloroso, mas vai te trazer bastante conhecimento, acredite.

[quote=davidtiagoconceicao]Bah cara, quanto código! :slight_smile:

jtable.setModel(tableModel);

Você fez isso?[/quote]

não fiz, mas estava quase tentando isso… :lol:

sobre o netbeans o complicado eh q o programa inteiro meu esta feito no netbeans eu precisaria fazer isso funcionar apenas um combobox em uma certa coluna(isso eu fiz)…mas agora tenho q fazer esse combobox ser composto de cores o usuario ira selecionar cor, mas creio q isso seja do JComboBox e nao JTable…pegar o indice da escolha e gravar…isso preciso urgente…mas ja estava aproveitando e dando uma estudada em JTable, vou dar uma estudada usando JCreator mesmo free soh pra servir como um editor e fazer tudo na unha mesmo com netbeans fica complicado mesmo…o problema vai ser tempo mesmo pois preciso dessas funcionalidades urgente

mas vlw mesmo pela ajuda cara…amanha do mais uma fuçada qualq coisa posto mais alguma duvida… :smiley:

Sim, isso você vai precisar implementar dentro do JCombobox que o renderer vai retornar…

soh pra finalizar…o renderer serve então nesse exemplo para adicionar e mostrar um componente (JComboBox) na celula da JTable…certo?

Mais ou menos isso.

Tecnicamente falando, o renderer não adiciona. Ele gera o componente que a JTable irá adicionar.

ok valew vou tentar fazer umas tabelas de exemploa aqui

obrigado.