# JTable - Aktualisieren / Neu zeichnen.



## shidan (18. Jul 2011)

Hallöchen ich bins wieder,

Ich bräuchte mal einen kleinen Rat wie man ein JTable neuzeichnen kann ohne gleich die komplette GUI neuzustarten, ich brauche das Neuzeichnen da sich dadurch die Werte in der Tabelle sortieren sollen und die Farbsortierung ,die Speziell im Table festgelgt wurde, sich aktualisiert.

Ich habe leider bereits sämtliche repaint,validate usw. Methoden des Tables auspropiert aber nichts scheint zu funktionieren.

Gruß Shidan


----------



## SlaterB (18. Jul 2011)

wenn das Aussehen von den Einstellungen im TableModel abhängt, geht vielleicht dort 
fireTableDataChanged() oder als höchstes Event fireTableStructureChanged()

idealerweise ein vollständiges kleines Testprogramm posten


----------



## shidan (18. Jul 2011)

Uff müsste ich mich drann setzen und mal schaun.

Hier ist die Klassemit der ich mir mein Table einfärbe.


```
class GroupingTable extends JTable {
        /**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		private int keyColumn;
        private Color[] colorModel;
        private int[] colorIndex;   //"Model" zur Speichern der Zeilenfarbe
        
        public GroupingTable(TableModel model, int column) {
            super(model);
            this.keyColumn = column;
            colorModel = new Color[] {this.getBackground(), Color.LIGHT_GRAY};
            determineColor();
        }
        
        //tableChanged Überschrieben, damit das "Farbenmodel" aktualisiert wird
        public void tableChanged(TableModelEvent evt) {
            if (evt.getColumn()==keyColumn)
                determineColor();
            super.tableChanged(evt);
        }
        
        //Methode zum Ermitteln der Zeilenfarbe
        private void determineColor() {
            colorIndex = new int[this.getRowCount()];
            if (colorIndex.length<=0)
                return;
            int colorCount=0;
            colorIndex[0] = colorCount;
            for (int row=1; row<this.getRowCount(); row++) {
            	
                if(this.getValueAt(row, this.convertColumnIndexToView(keyColumn)) != null && this.getValueAt(row, this.convertColumnIndexToView(keyColumn))
                        .equals(this.getValueAt(row-1, this.convertColumnIndexToView(keyColumn))))
                    colorIndex[row] = colorCount & 1;
                else
                    colorIndex[row] = ++colorCount & 1;
            }
        }
        
        //Überschrieben, um die Zeilenfarbe zu setzen.
        public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
            Component c = (Component) super.prepareRenderer(renderer, row, column);
            for (int i=0; i<this.getSelectedRows().length; i++) {
                if (this.getSelectedRows()[i]==row)
                    return c;
            }
            try{
            	c.setBackground(colorModel[colorIndex[row]]);
            }catch(ArrayIndexOutOfBoundsException ex){
            	
            }
            return c;
        }
    }
```

Und hier mal meine DefaultTableModel

```
setDtm(new DefaultTableModel(data, columnNames){			
			 /**Eigenes DefaultTableModel um nur Zahlen auf der Tabelle 
			  * nach Zeile 2 zu zulassen.
			 */
			private static final long serialVersionUID = 1L;


			@Override
			    public void setValueAt(Object aValue, int row, int col)
			    {
			        // Abbruch wenn der Wert kein Integer ist.	
			        if (aValue instanceof Integer)
			        {
			        	//Abbruch wenn der Wert nicht zwischen 0 - 100 liegt.
			          int value = ((Integer)aValue).intValue();		
			        	  if(value < 0 || value > 100){
			        		  return;			        	  
			          }
			        }
			        // Setze den Wert.
			        super.setValueAt(aValue, row, col);
			    }

			 
			    @Override
			    public Class<?> getColumnClass(int col)
			    {
			        if (col >=2)
			            return Integer.class;
			        else{
			        	return String.class;
			        }
			    }			
		});
```

StructureChanged bringt leider auch nichts macht es eher nur schlimmer da meine ersten beiden Columns ComboBoxen sind und diese dann einfach mit normalen ersetzt werden.


----------



## Michael... (18. Jul 2011)

shidan hat gesagt.:


> Hier ist die Klassemit der ich mir mein Table einfärbe.
> 
> 
> ```
> ...


----------



## shidan (18. Jul 2011)

Jap, danke nocheinmal dafür. Hat mir nen gutes Stück arbeit erspart da ich noch kaum Erfahrung hatte mit umschreiben von SwingComponenten.

Ich hab mir hier mal eine GUI zusammengeklickt ( Tut mir Leid für die Faulheit)

Hier sieht man es ungefähr da ich die RefreshMethode genauso habe.

```
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collections;
import java.util.Comparator;
import java.util.Vector;

import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;

import javax.swing.WindowConstants;
import javax.swing.event.TableModelEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import javax.swing.SwingUtilities;




/**
* This code was edited or generated using CloudGarden's Jigloo
* SWT/Swing GUI Builder, which is free for non-commercial
* use. If Jigloo is being used commercially (ie, by a corporation,
* company or business for any purpose whatever) then you
* should purchase a license for each developer using Jigloo.
* Please visit [url=http://www.cloudgarden.com]Cloud Garden (Java Resources)[/url] for details.
* Use of Jigloo implies acceptance of these licensing terms.
* A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR
* THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED
* LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.
*/
public class table extends javax.swing.JFrame {
	private JScrollPane jScrollPane1;
	private JButton jButton1;
	private JButton jButton2;
	private JPanel jPanel1;
	private JTable jTable1;
	private JComboBox comboBox_names;
	private JComboBox comboBox_projekts;
	private DefaultTableModel jTable1Model;
	private JButton jButton3;
	/**
	* Auto-generated main method to display this JFrame
	*/
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				table inst = new table();
				inst.setLocationRelativeTo(null);
				inst.setVisible(true);
			}
		});
	}
	
	public table() {
		super();
		initGUI();
	}
	
	private void initGUI() {
		try {
			BorderLayout thisLayout = new BorderLayout();
			setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
			getContentPane().setLayout(thisLayout);
			{
				jScrollPane1 = new JScrollPane();
				getContentPane().add(jScrollPane1, BorderLayout.CENTER);
				jScrollPane1.setPreferredSize(new java.awt.Dimension(392, 203));
				{
					jButton1 = new JButton();
					jScrollPane1.setViewportView(jButton1);
					jButton1.setText("jButton1");
				}
				{
					jTable1Model = 
						new DefaultTableModel(
								new String[][] { { "Blub:1", "2" }, { "Blub:3", "4" },{"Blub:1","7"},{"Blub:2","8"}},
								new String[] { "Column 1", "Column 2" ,"Column 3"});
					jTable1 = new GroupingTable(jTable1Model,0);
					jScrollPane1.setViewportView(jTable1);
					jTable1.setModel(jTable1Model);			
					
					TableColumn tColumnNames = jTable1.getColumnModel().getColumn(0);
					TableColumn tColumnProjekts = jTable1.getColumnModel().getColumn(1);
					

					comboBox_names = new JComboBox();
			
					//ComboxBox fï¿½r Namen und Projekte werden mit den Namen und Projekten gefï¿½llt.
					comboBox_names.addItem("");			
					for(int i = 0; i < 3; i++){
						comboBox_names.addItem("Blub:"+i);
					}
					
					//CellEditor fï¿½r die ComboBoxen.
					tColumnNames.setCellEditor(new DefaultCellEditor(comboBox_names));			
					jTable1.setPreferredSize(new java.awt.Dimension(390, 178));
				}
			}
			{
				jPanel1 = new JPanel();
				getContentPane().add(jPanel1, BorderLayout.NORTH);
				jPanel1.setPreferredSize(new java.awt.Dimension(392, 33));
				{
					jButton2 = new JButton();
					jPanel1.add(jButton2);
					jButton2.setText("Refresh");
					jButton2.addActionListener(new ActionListener() {
					

						public void actionPerformed(ActionEvent evt) {
							System.out.println("Sortieren");
							sortAllRowsBy(jTable1Model, 0, true);
						}
					});
				}
				{
					jButton3 = new JButton();
					jPanel1.add(jButton3);
					jButton3.setText("Neue Reihe");
					jButton3.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent evt) {
							jTable1Model.addRow(new String[]{});							
						}
					});
				}
			}
			pack();
			setSize(400, 300);
		} catch (Exception e) {
		    //add your error handling code here
			e.printStackTrace();
		}
	}
	
	class GroupingTable extends JTable {
        /**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		private int keyColumn;
        private Color[] colorModel;
        private int[] colorIndex;   //"Model" zur Speichern der Zeilenfarbe
        
        public GroupingTable(TableModel model, int column) {
            super(model);
            this.keyColumn = column;
            colorModel = new Color[] {this.getBackground(), Color.LIGHT_GRAY};
            determineColor();
        }
        
        //tableChanged Überschrieben, damit das "Farbenmodel" aktualisiert wird
        public void tableChanged(TableModelEvent evt) {
            if (evt.getColumn()==keyColumn)
                determineColor();
            super.tableChanged(evt);            
        }
        
        //Methode zum Ermitteln der Zeilenfarbe
        private void determineColor() {
            colorIndex = new int[this.getRowCount()];
            if (colorIndex.length<=0)
                return;
            int colorCount=0;
            colorIndex[0] = colorCount;
            for (int row=1; row<this.getRowCount(); row++) {
            	
                if(this.getValueAt(row, this.convertColumnIndexToView(keyColumn)) != null && this.getValueAt(row, this.convertColumnIndexToView(keyColumn))
                        .equals(this.getValueAt(row-1, this.convertColumnIndexToView(keyColumn))))
                    colorIndex[row] = colorCount & 1;
                else
                    colorIndex[row] = ++colorCount & 1;
            }
        }
        
        //Überschrieben, um die Zeilenfarbe zu setzen.
        public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
            Component c = (Component) super.prepareRenderer(renderer, row, column);
            for (int i=0; i<this.getSelectedRows().length; i++) {
                if (this.getSelectedRows()[i]==row)
                    return c;
            }
            try{
            	c.setBackground(colorModel[colorIndex[row]]);
            }catch(ArrayIndexOutOfBoundsException ex){
            	
            }
            return c;
        }        
	}
	
	
	//Sortiermethoden.
	
	
	public void sortAllRowsBy(DefaultTableModel model, int colIndex, boolean ascending) {
	    Vector<Object> data = model.getDataVector();
	    Collections.sort(data, new ColumnSorter(colIndex, ascending));
	    model.fireTableStructureChanged();
	}
	// This comparator is used to sort vectors of data
	public class ColumnSorter implements Comparator<Object> {
	    int colIndex;
	    boolean ascending;
	    ColumnSorter(int colIndex, boolean ascending) {
	        this.colIndex = colIndex;
	        this.ascending = ascending;
	    }
	    @SuppressWarnings("unchecked")
		public int compare(Object a, Object b) {
	        Vector<Object> v1 = (Vector<Object>)a;
	        Vector<Object> v2 = (Vector<Object>)b;
	        Object o1 = v1.get(colIndex);
	        Object o2 = v2.get(colIndex);

	        // Treat empty strains like nulls
	        if (o1 instanceof String && ((String)o1).length() == 0) {
	            o1 = null;
	        }
	        if (o2 instanceof String && ((String)o2).length() == 0) {
	            o2 = null;
	        }

	        // Sort nulls so they appear last, regardless
	        // of sort order
	        if (o1 == null && o2 == null) {
	            return 0;
	        } else if (o1 == null) {
	            return 1;
	        } else if (o2 == null) {
	            return -1;
	        } else if (o1 instanceof Comparable) {
	            if (ascending) {
	                return ((Comparable<Object>)o1).compareTo(o2);
	            } else {
	                return ((Comparable<Object>)o2).compareTo(o1);
	            }
	        } else {
	            if (ascending) {
	                return o1.toString().compareTo(o2.toString());
	            } else {
	                return o2.toString().compareTo(o1.toString());
	            }
	        }
	    }
	}
}
```

Das Problem ist halt wenn man sich ein paar Reihne dazuklickt und diese mit  Werten füllt, aktualisiert sich die Farbe nicht und wenn ich FireTable-Data oder StructureChange aufrufe sind die ComboBoxen weg.


----------



## Michael... (18. Jul 2011)

```
fireTableStructureChanged
```
 darfst Du nicht aufrufen, da dann die JTable davon ausgehen muss, dass eventuell ein ganz neues TableModel dargestellt werden muss und dadurch gehen dann natürlich solche Sachen wie CellEditoren verloren.
Rufe nach dem Sortieren einfach nur
	
	
	
	





```
fireTableDataChanged()
```
 am Model auf.

Du musst allerdings die Bedingung in der überschriebenen tableChanged() der GroupingTable noch anpassen, da mit dieser Bedingung 
	
	
	
	





```
if (evt.getColumn()==keyColumn)
```
 die Zeilenfarbe nur bei einer Änderung in der konkreten Spalte neu ermittelt wird.
Ersetze sie erst einmal z.B. durch 
	
	
	
	





```
if (this.getColumnCount()>keyColumn)
```
 - nun wird allerdings bei jeder Änderung in der Tabelle das Farbmodel neu berechnet.


----------

