JTable Dinamico

Bom Dia a todos!! Eu tenho um TableModel onde a quantidade de linhas esta especificada pelo size() do meu list:

[code]package com.mascarenhas.model.tables;

import java.util.ArrayList;
import java.util.List;

import javax.swing.table.AbstractTableModel;

import com.mascarenhas.model.usuario.OutrosValores;

public class MyTableModelOutrosValores extends AbstractTableModel{

List<OutrosValores> list;

int COLUMN_ORIGEM_DESTINO = 0;
int COLUMN_VALOR = 1;


public MyTableModelOutrosValores(List<OutrosValores> list){
	
	this.list = new ArrayList<OutrosValores>(list);
	
}


@Override
public int getColumnCount() {
	// TODO Auto-generated method stub
	return 2;
}
@Override
public int getRowCount() {
	// TODO Auto-generated method stub
	return this.list.size();
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
	
	OutrosValores ov = list.get(rowIndex);
	
	if(this.COLUMN_ORIGEM_DESTINO == columnIndex){
		
		return ov.getNome();
		
	}
	
	if(this.COLUMN_VALOR == columnIndex){
		
		return ov.getValor();
		
	}
	
	return null;
}

public String getColumnName(int columIndex){
	
	if(this.COLUMN_ORIGEM_DESTINO == columIndex){
		
		return "Origem Destino";
		
	}
	
	if(this.COLUMN_VALOR == columIndex){
		
		return "Valor";
		
	}
	
	return null;
}

}
[/code]

Porém minha JTable nao quer ficar dinamica ou seja, tenho que dar um “jTable.setPreferredSize” pra visualizar as ultimas linhas dela, alguem me ajuda?

Sua table está num ScrollPane?

Em que área da janela ele foi colocado?

[quote=ViniGodoy]Sua table está num ScrollPane?

Em que área da janela ele foi colocado?[/quote]

Opa Vini esta em um ScrollPane quanto á area da janela seria no centro do JDialog? Não entendi bem a segunda pergunta.

Sim, pq isso vai depender do layout manager que você está usando. Se estiver usando o layout null, não há o que fazer.

A tabela só vai se redimensionar automaticamente se você estiver usando um layout dinâmico, como BorderLayout ou GridbagLayout ou o GroupLayout.

Voce fala o layout do meu Scroll? Eu to tentando usar GroupLayout nele mas nao to conseguindo.

alguem?

Boa noite a todos.

Pessoal, estou com uma dúvida no construtor da classe AbstractTableModel.

public MyTableModelOutrosValores(List<OutrosValores> list){
       
       // Este construtor já recebe um parâmetro list já instanciado
       // Neste caso, ao se fazer nova instância dele, ele não cria outra referência do list :?: :?: :?:    
        this.list = new ArrayList<OutrosValores>(list); 

      // Neste caso o correto não seria assim:
      this.list = list; 

      // Ou será que estou enganado  :?: :?: :?: 
           
}   

[quote=discorpio]Boa noite a todos.

Pessoal, estou com uma dúvida no construtor da classe AbstractTableModel.

[code]
public MyTableModelOutrosValores(List list){

   // Este construtor já recebe um parâmetro list já instanciado
   // Neste caso, ao se fazer nova instância dele, ele não cria outra referência do list :?: :?: :?:    
    this.list = new ArrayList<OutrosValores>(list); 

  // Neste caso o correto não seria assim:
  this.list = list; 

  // Ou será que estou enganado  :?: :?: :?: 

}
[/code][/quote]

Opa tudo bom, na verdade as duas maneiras funcionam porém da primeira forma vc so esta usando polimorfismo onde no construtor do ArrayList vc passa sua “lista”, com isso vc nao perde o conteudo do seu list.

Não. A forma que você indicou é incorreta pois viola o encapsulamento da classe AbstractTableModel.

Veja bem, o que o colega está fazendo nesta construção:

this.list = new ArrayList(list);

É tirar uma cópia da lista. Como o TableModel exige que você faça adições e remoções nessa lista apenas pelos métodos add e remove do próprio tablemodel (para assim ele disparar eventos para o JTable), seria errado permitir que o usuário chamasse diretamente o método add da lista.

Se você manter o código assim:

this.list = list;

Nada impedirá seu usuário de fazer isso aqui:

List<OutrosValores> lista = OutrosValoresDao.Carregar(); MyTableModelOutrosValores model = new MyTableModelOutrosValores(lista) lista.remove(10);

Note que isso removeria um elemento da lista que está dentro do model, portanto, uma violação clara do encapsulamento.

Via de regra, sempre que você receber um objeto externamente, você deve copia-lo, ou o usuário ainda poderá modifica-lo fora da sua classe. O mesmo vale para os gets. Um get nunca pode retornar o objeto diretamente assim:

public List<OutrosValores> getLista() { return lista; }

Note que isso permitiria que seu usuário fizesse:

model.getLista().add(outroValor);

E novamente não utilizasse o método do seu próprio model. Por isso, um getter deveria retornar uma cópia da lista, ou uma versão imodificável da lista:

public List<OutrosValores> getLista() { return Collections.unmodifiableList(lista); }

Bom, isso é um problema do código que desenha sua tela. Por isso, ver o seu model não vai adiantar em muita coisa. E, para nós, é difícil compreender o GroupLayout (já que ele é feito para ser editado pelas IDEs).

Agora, a altura de um JTable não se ajusta automaticamente para o número de colunas. O que você faz é definir uma altura fixa, e colocar scroll a partir dessa altura. Se você quiser ajustar, terá que fazer “no braço”, e para isso usar métodos como getCellHeight().

Bom, isso é um problema do código que desenha sua tela. Por isso, ver o seu model não vai adiantar em muita coisa. E, para nós, é difícil compreender o GroupLayout (já que ele é feito para ser editado pelas IDEs).

Agora, a altura de um JTable não se ajusta automaticamente para o número de colunas. O que você faz é definir uma altura fixa, e colocar scroll a partir dessa altura. Se você quiser ajustar, terá que fazer “no braço”, e para isso usar métodos como getCellHeight().[/quote]

Mas com tudo eu tenho uma altura fixa nao? Veja só:

jTable.setPreferredSize(new java.awt.Dimension(911, 1200));

Como o nome diz, você tem uma altura “favorita” para o seu JTable, não fixa. A fixa você obtém com setBounds, se estiver usando nullLayout. A altura final é definida pelo LayoutManger, por isso, sem analisar com cuidado como você está montando sua tela, fica difícil dizer o que está acontecendo.

O problema é q eu to usando o Jigloo :frowning: . Nao tenho dominio de Swing por isso to usando ele, pra ser sincero até me ajudou mas eu sei q esta MUITO LONGE de ser o correto usar esses tipos de plugins…

É, se nem vc sabe direito o que está fazendo, aí fica difícil mesmo te ajudar… hehehehe

Em todo caso, talvez alguém aqui saiba melhor como o jigloo trabalha. Eu nunca usei.

É, se nem vc sabe direito o que está fazendo, aí fica difícil mesmo te ajudar… hehehehe

Em todo caso, talvez alguém aqui saiba melhor como o jigloo trabalha. Eu nunca usei.[/quote]

auhsuhaa, o que acontece no metodo que cria o JTable e o que cria o JScroll eu sei sim o que esta fazendo, não tem mta dificuldade em entender.

Aqui cria o JTable

[code]private JTable getJTable() {
if(jTable == null) {

		jTable = new JTable();
		
		try {
			
			jTable.setModel(new MyTableModelOutrosValores(this.Conexao()));
			
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		jScrollPane.setViewportView(jTable);
	
		jTable.setPreferredSize(new java.awt.Dimension(911, 1200));
				
		ColorirLinhaTable color = new ColorirLinhaTable();  			
		color.getColorirJDialogOutrosValores();//método que chama o meu Renderer

[/code]

Aqui o Scroll

private JScrollPane getJScrollPane() { if(jScrollPane == null) { jScrollPane = new JScrollPane(); jScrollPane.setViewportView(getJTable()); } return jScrollPane; }

O problema pelo menos para mim é entender como o Panell ta adicionando os components, e pelo que entendi sua explicaçao pode ser onde esta o erro, pq aqui esta os Layouts Managers…o GroupLayout no caso.

[code]try {

		GroupLayout thisLayout = new GroupLayout((JComponent)getContentPane());
		getContentPane().setLayout(thisLayout);
		thisLayout.setVerticalGroup(thisLayout.createSequentialGroup()
			.addComponent(getJScrollPane(), 0, 330, Short.MAX_VALUE));
		thisLayout.setHorizontalGroup(thisLayout.createSequentialGroup()
			.addComponent(getJScrollPane(), 0, 914, Short.MAX_VALUE));

		ImageIcon image = new ImageIcon(this.getClass().getResource("/icon/mascarenhas.png"));
		
		this.setIconImage(image.getImage());
		
		pack();
		
		this.setSize(920,355);
		this.setLocationRelativeTo(null);
		this.setResizable(false);
				
	} catch (Exception e) {
		e.printStackTrace();
	}[/code]

É, ali mesmo. Como no caso é mesmo o GroupLayout fica difícil de ajudar. Ele foi feito para IDEs entenderem, não para seres humanos. Mas você teria que baixar uns tutos do netbeans ou do Jigloo e entender certinho como ancorar componentes da maneira certa.

O Jigloo usa o matisse também?

Eu acredito que valha a pena investir um tempo estudando gerenciador de leiautes (eu recomendaria o MigLayout). Veja um exemplo da simplicidade da coisa:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;

import net.miginfocom.swing.MigLayout;

public class TesteTabela extends JFrame implements ActionListener {

	private static final long serialVersionUID = 1L;
	private JTable tabela;
	private StringTableModel modelo;
	private JButton adiciona;
	private JButton remove;

	public TesteTabela() {
		// cria os objetos
		tabela = new JTable();
		modelo = new StringTableModel();
		tabela.setModel(modelo);
		adiciona = new JButton("Adiciona");
		adiciona.addActionListener(this);
		remove = new JButton("Remove");
		remove.addActionListener(this);
		// muda o leiaute e adiciona os componentes
		setLayout(new MigLayout("fill"));
		add(new JScrollPane(tabela), "w :300:, h :300:, grow, span 2, wrap");
		// a linha acima significa:
		// w :300: -> a largura preferida é 300
		// h :300: -> a altura preferida é 300
		// grow -> ele deve se expandir automaticamente
		// span 2 -> serão ocupadas 2 colunas
		// wrap -> após esse componente haverá um "quebra de linha"
		// para mais infomações acesse http://miglayout.com e leia a
		// documentação (Quick Start)
		add(adiciona);
		add(remove);
		// ajusta a janela
		pack();
		setLocationRelativeTo(null);
		setDefaultCloseOperation(DISPOSE_ON_CLOSE);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == adiciona) {
			String valor = JOptionPane.showInputDialog("Valor a ser inserido:");
			modelo.add(valor);
			return;
		}
		if (e.getSource() == remove) {
			int row = tabela.getSelectedRow();
			if (row != -1) {
				modelo.remove(row);
			}
			return;
		}
	}

	public static void main(String[] args) {
		new TesteTabela().setVisible(true);
	}

}

E o TableModel usado:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.table.AbstractTableModel;

public class StringTableModel extends AbstractTableModel {

	private static final long serialVersionUID = 1L;
	private List<String> strings;

	public StringTableModel() {
		this(Collections.<String> emptyList());
	}

	public StringTableModel(List<String> string) {
		strings = new ArrayList<String>(string);
	}

	@Override
	public int getColumnCount() {
		return 2;
	}

	@Override
	public int getRowCount() {
		return strings.size();
	}

	@Override
	public Object getValueAt(int rowIndex, int columnIndex) {
		if (columnIndex == 0) {
			return rowIndex + 1;
		}
		return strings.get(rowIndex);
	}

	@Override
	public Class<?> getColumnClass(int columnIndex) {
		if (columnIndex == 0) {
			return Integer.class;
		}
		return String.class;
	}

	@Override
	public String getColumnName(int column) {
		if (column == 0) {
			return "Índice";
		}
		return "Valor";
	}

	@Override
	public boolean isCellEditable(int rowIndex, int columnIndex) {
		return false;
	}

	public void remove(int row) {
		strings.remove(row);
		fireTableRowsDeleted(row, row);
	}

	public void add(String valor) {
		strings.add(valor);
		fireTableRowsInserted(strings.size(), strings.size());
	}

}

[quote=ViniGodoy]É, ali mesmo. Como no caso é mesmo o GroupLayout fica difícil de ajudar. Ele foi feito para IDEs entenderem, não para seres humanos. Mas você teria que baixar uns tutos do netbeans ou do Jigloo e entender certinho como ancorar componentes da maneira certa.

O Jigloo usa o matisse também?[/quote]

Vini matisse seria a paleta drag and drop dos components, containers etc…? Se for usa…È parecido com o do netbeans mesmo…Porém o codigo eu achei mais legivel…

[quote=marcobiscaro2112]Eu acredito que valha a pena investir um tempo estudando gerenciador de leiautes (eu recomendaria o MigLayout). Veja um exemplo da simplicidade da coisa:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;

import net.miginfocom.swing.MigLayout;

public class TesteTabela extends JFrame implements ActionListener {

	private static final long serialVersionUID = 1L;
	private JTable tabela;
	private StringTableModel modelo;
	private JButton adiciona;
	private JButton remove;

	public TesteTabela() {
		// cria os objetos
		tabela = new JTable();
		modelo = new StringTableModel();
		tabela.setModel(modelo);
		adiciona = new JButton("Adiciona");
		adiciona.addActionListener(this);
		remove = new JButton("Remove");
		remove.addActionListener(this);
		// muda o leiaute e adiciona os componentes
		setLayout(new MigLayout("fill"));
		add(new JScrollPane(tabela), "w :300:, h :300:, grow, span 2, wrap");
		// a linha acima significa:
		// w :300: -> a largura preferida é 300
		// h :300: -> a altura preferida é 300
		// grow -> ele deve se expandir automaticamente
		// span 2 -> serão ocupadas 2 colunas
		// wrap -> após esse componente haverá um "quebra de linha"
		// para mais infomações acesse http://miglayout.com e leia a
		// documentação (Quick Start)
		add(adiciona);
		add(remove);
		// ajusta a janela
		pack();
		setLocationRelativeTo(null);
		setDefaultCloseOperation(DISPOSE_ON_CLOSE);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == adiciona) {
			String valor = JOptionPane.showInputDialog("Valor a ser inserido:");
			modelo.add(valor);
			return;
		}
		if (e.getSource() == remove) {
			int row = tabela.getSelectedRow();
			if (row != -1) {
				modelo.remove(row);
			}
			return;
		}
	}

	public static void main(String[] args) {
		new TesteTabela().setVisible(true);
	}

}

E o TableModel usado:

[code]
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.table.AbstractTableModel;

public class StringTableModel extends AbstractTableModel {

private static final long serialVersionUID = 1L;
private List<String> strings;

public StringTableModel() {
	this(Collections.<String> emptyList());
}

public StringTableModel(List<String> string) {
	strings = new ArrayList<String>(string);
}

@Override
public int getColumnCount() {
	return 2;
}

@Override
public int getRowCount() {
	return strings.size();
}

@Override
public Object getValueAt(int rowIndex, int columnIndex) {
	if (columnIndex == 0) {
		return rowIndex + 1;
	}
	return strings.get(rowIndex);
}

@Override
public Class<?> getColumnClass(int columnIndex) {
	if (columnIndex == 0) {
		return Integer.class;
	}
	return String.class;
}

@Override
public String getColumnName(int column) {
	if (column == 0) {
		return "Índice";
	}
	return "Valor";
}

@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
	return false;
}

public void remove(int row) {
	strings.remove(row);
	fireTableRowsDeleted(row, row);
}

public void add(String valor) {
	strings.add(valor);
	fireTableRowsInserted(strings.size(), strings.size());
}

}
[/code][/quote]

Marcos eu vou começar da uma estudada em layouts mesmo pra nao ficar dependendo de plugins, deixa eu fazer uma pergunta no caso vc esta implementando ActionListener entao ele sobreescreve o actionPerformed porém isso é pra um unico evento? Se no caso vc tivesse mais tres eventos vc teria que criar uma classe no argumento do metodo?

Você tem duas opções para tratar eventos: criar uma classe anônima (definida no argumento do método) para cada evento ou usar uma classe para tratar vários eventos (como eu fiz). Note que no segundo caso você precisa verificar quem originou o evento (o que é feito no método).