# JButton in einer Row in einer JTable



## NochKeinGuru (8. Nov 2011)

Hallo zusammen,

ich suche nun schon eine ganze Weile nach einer Möglichkeit mehrere Buttons in einer Row einer JTable einzufügen.

Ich habe dafür einen CellRenderer geschrieben und einen CellEditor.

Bevor ich nun den ganzen Code hier poste wollte ich mal Fragen woran es liegt das die Buttons zwar erscheinen, aber zum einen nur dann wenn er angeklickt wird und zum anderen nur der Klassenpfad darin steht.

Desweiteren ein ähnlich komisches Verhalten stellt das farbig machen mehrerer Zeilen dar. Hier werden die Zeilen zwar farbig, jedoch wenn ich horizontal scrolle bleiben die Zellfarben nicht konstant auf ihrer zugewiesenen Farbe.

Muss ich irgendwas in der paintComponent Methode schreiben?

Leider finde ich nur immer Beispiele für einen ColumnButton Renderer/Editor.

Ich vermute hier irgend ein Grundsätzliches Problem da ich auch schon einen Renderercode und editorcode reinkopiert habe welche funktionieren sollte.
Evtl. ist das auch ganz schnell gelöst.

JTable, JPanels usw. sind alles Swing Komponenten.

Falls mehr Infos notwendig bitte schreiben 

Danke!
Tobi


----------



## NochKeinGuru (8. Nov 2011)

was ich auch nicht verstehe ist, dass imemr nur einButton sichtbar ist, wenn ich einen anderen anklicke verschwindet der vorherige und es erscheint wieder der Klassenpfad des Buttons in der Tabellenzeile. ..

Ich versteh das ned ???:L


----------



## Marco13 (8. Nov 2011)

Ja, das ist komplizierter als man meinen sollte. Und wenn man im Netz nach sowas sucht, findet man einen Haufen übelst-krampfigste Lösungsvorschläge :autsch: Irgendwann hatte ich es dann mal versucht es einigermaßen überschaubar hinzukriegen, und das hat IMHO geklappt, deswegen hab' ichs jetzt nochmal als KSKB zusammengefasst:

```
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;

class JTableButtonTest
{
    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                JFrame f = new JFrame();
                f.getContentPane().add(createTableComponent());
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setSize(300,300);
                f.setVisible(true);
            }
        });
    }


    private static JComponent createTableComponent()
    {

        // Create the table model: Column 0 contains a
        // string, and columns 1 and 2 contain a button
        DefaultTableModel tableModel = new DefaultTableModel(
            new String[]{"Text", "Button0", "Button1"}, 0)
        {
            public Class<?> getColumnClass(int c)
            {
                if (c == 1 || c == 2)
                {
                    return JButton.class;
                }
                return super.getColumnClass(c);
            }
        };

        // Add some rows...
        addRow(tableModel, 0);
        addRow(tableModel, 1);
        addRow(tableModel, 2);

        // Create the table
        JTable table = new JTable(tableModel);

        // Initialize the renderer and editor for the button columns
        initButtonColumn(table.getColumnModel().getColumn(1));
        initButtonColumn(table.getColumnModel().getColumn(2));


        JScrollPane scrollPane = new JScrollPane(table);
        return scrollPane;
    }


    private static void initButtonColumn(TableColumn column)
    {
        class Renderer implements TableCellRenderer
        {
            @Override
            public Component getTableCellRendererComponent(
                JTable table, Object value, boolean isSelected,
                boolean hasFocus, int row, int column)
            {
                return (Component)value;
            }
        }
        column.setCellRenderer(new Renderer());

        class Editor extends AbstractCellEditor implements TableCellEditor
        {
            private Object currentValue;

            @Override
            public Object getCellEditorValue()
            {
                Object result = currentValue;
                currentValue = null;
                return result;
            }

            @Override
            public Component getTableCellEditorComponent(JTable table,
                Object value, boolean isSelected, int row, int column)
            {
                currentValue = value;
                return (Component)value;
            }
        }
        column.setCellEditor(new Editor());
    }


    private static void addRow(DefaultTableModel tableModel, final int row)
    {
        JButton button0 = new JButton("Row "+row);
        button0.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                System.out.println("Pressed button0 in row "+row);
            }
        });
        JButton button1 = new JButton("Row "+row);

        button1.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                System.out.println("Pressed button1 in row "+row);
            }
        });
        tableModel.addRow(new Object[]{"Row "+row, button0, button1 });
    }


}
```

Aber erstmal warten, was unser JTable-Experte dazu sagt (du weißt schon, dass du gemeint bist )


----------



## NochKeinGuru (8. Nov 2011)

hm.. also erstmal danke für dein Antwort udn dein Verständnis. Man findet im Netz echt nur krampfhafte Dinge.
dein Beispiel handelt nun aber auch wieder von Buttons in einer Column. Wie ist das denn in einer Row?

Also vielleicht kopier ich hier doch mal die wesentliche Codezeilen rein:


```
header[0] = "";
		header[1] = "Monat";
				
		model = new MyTableModel(header,0);		
		table = new MainTable(model);
				
		Vector<Month> m = mm.getMonths();
		Iterator<Month> iter = m.iterator();
		while(iter.hasNext()){
			Month mo = (Month)iter.next();
			Object[] objects = {mo.getOpenPoints()};
			model.addColumn(mo.getName(),objects);
		}		
					
		model.addTableModelListener(this);

                table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		
		JScrollPane scrollPane = new JScrollPane(table);		
		
		table.setDefaultRenderer(JButton.class, new MyCellRenderer());
		table.setDefaultEditor(Object.class, new MyCellEditor());
```

mo.getOpenPoints() der Klasse Month liefert ein Objekt vom Typ JButton zurück (soll später erweitert werden durch Texte die die Column füllen sollen.


Der Celllrenderer:


```
public class MyCellRenderer extends JButton implements TableCellRenderer {

     private static final long serialVersionUID = -5126943784788272911L;
			
    public MyCellRenderer()
    {
         setOpaque(true);            	  
    }
    public Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected,     boolean hasFocus, int row, int column)
    {  	         
   		 		  
	                if (isSelected)
	 		{
	        	 this.setForeground(table.getSelectionForeground());
	        	 this.setBackground(table.getSelectionBackground());
	 		}
	 		else
	 		{
	 			this.setForeground(table.getForeground());
	 			this.setBackground(UIManager.getColor("Button.background"));
	 		}
	         
	        if (value == null)
	 		{
	        	this.setText( "" );
	        	//this.setIcon( null );
	 		}	 		
	 		else
	 		{
	 			this.setText( ((JButton)value).getText());
	 			//this.setIcon( null );
	 		}
        
         return this;
     }  
}
```


und schliesslich noch der Editor:


```
public class MyCellEditor extends AbstractCellEditor implements TableCellEditor
{
  private static final long serialVersionUID = 1800354749469202410L;
  private Object val = null;
      
  public MyCellEditor(){
	  super();		   
  }
  
  public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int rowIndex, int colIndex )
  {
	  if (value instanceof JButton){
		  ((JButton)value).setText( ((JButton)value).getText());
		  ((JButton)value).setIcon( null );
	  }	
	this.val = value;
	return (JButton)value;		
	  
  }
  public Object getCellEditorValue()
  {
    return val;
  }
  
  public boolean isCellEditable(EventObject anEvent)
  {     
     return true;
  }

  
}
```

Also ich hoffe jemand sieht das Problem.. ich hacke da jetzt schon 3 Abende dran rum und bekomms ned hin


----------



## Marco13 (9. Nov 2011)

Ach so, nur in EINER Row und in allen anderen was anderes?  Das dürfte schwierig werden. Überall wird davon ausgegangen, dass getColumnClass die Klasse der Column liefert, und welche sollte das dann sein? Anders gesagt: In einer Tabelle sollten alle Zeilen einer Spalte den gleichen Typ haben - andernfalls ist es keine Tabelle. Überleg' mal ob du die Buttons nicht drüber oder drunter oder sonstwohin legen kannst.
Aber vielleicht hat der besagte ... (jaa, André!  ) ... noch eine Idee....


----------



## NochKeinGuru (9. Nov 2011)

hm...

das ist aber blöd.

Alle Zeilen einer Spalte müssen den selben Typ haben? Wieso ist das sonst keine Tabelle?
Das muss doch irgendwie gehen.

Der CellRenderer prüft ja ab welche Zellen vom Typ JButton sind.

Prinzipiell gehts ja auch. Hab nun Die Buttons und drunter normale Strings.
Nur werden die Buttons nur dann angezeigt wenn ich draufklicke und verschinden dann wieder..

Hm.. zumindest erklärt deine Ausführung warum es nur eine setColumnClass gibt :noe:

Aber irgendwie muss ich die Buttons doch dauerhaft sichtbar machen können?!?

Ich hab übrigends nun auch noch in einem Popup JComboBoxen in einer Column eingebunden.
Die werden auchnur angezeigt wenn man draufklickt.

In beiden Fällen sind die Renderer und die Editoren auf die ganze Tabelle gelegt und nicht einzelne Columns.. müsste doch gehen?!?

ich versuch das bei den Comboboxen mal mit der column noch.

Kann so ein Efekt wie bei mir auftreten wenn man AWT und Swing Komponenten mischt?
Also ich glaube ich hab alles mit Swing Komponenten.. aber bin nicht 100% sicher.


----------



## NochKeinGuru (9. Nov 2011)

hm... also wenn ich den Renderer und den Editor bei der Combobox auf die eine Column lege in der sich diese befinden dann funktionierts  Nur der ausgewähle Text bleibt nicht in der Box aber das ligt glaub dran das man den selected Index im Renderer dann entsprechend setzen muss.

Das heisst es liegt wirklich irgendwie daran dass ich die Buttons nur in einer Row hae. Aber das muss doch irgendwie gehen?!?


----------



## bERt0r (9. Nov 2011)

Ich hab sowas ähnliches mal gemacht, es ist allerdings wirklich keine saubere Lösung:
Da dir bei der getTableCellRendererComponent Methode die Row übergeben wird, kannst du abfragen, ob das jetzt die Row ist, in der du die Buttons hast und dann eben einen Button statt deinen normalen RendererComponents zurückgeben.

```
class BeschriftungsRenderer extends JLabel implements TableCellRenderer
	{
		Border raised,lowered;
		BeschriftungsRenderer()
		{
			this.setOpaque(true);
			this.setBackground(Color.LIGHT_GRAY);
			raised=BorderFactory.createBevelBorder(BevelBorder.RAISED);
			lowered=BorderFactory.createBevelBorder(BevelBorder.LOWERED);
		}

		@Override
		public Component getTableCellRendererComponent(JTable table, Object value,
                boolean isSelected, boolean hasFocus,
                int row, int column) {
			if(column==model.getColumnCount()-1)
			{
				this.setText("#"+row);
			}
			else
			{
				this.setText(columnNames.get((Integer)value));
			}
			if(hasFocus)
			{
				this.setBorder(lowered);
			}
			else
			{
				this.setBorder(raised);
			}
			
			return this;
		}
		
	}
```
Der Code hier ist nur als Beispiel gedacht, der macht keine Buttons sonder imitiert sozusagen das Aussehen der Header Zeile/Spalte nur statt oben und links sind sie unten und rechts (a la Excel nur umgekehrt).


----------



## Marco13 (9. Nov 2011)

Vielleicht kann man was basteln/hacken, damit ein Button nur in einer Zeile erscheint (im Zweifelsfall ist die ColumnClass dann einfach "Object", aber ... in einer Tabelle stehen normalerweise in den Zeilen die Objekte/"Entitäten", und in den Spalten die Eigenschaften - kann's sein, dass du einfach vorhast, deine Tabelle transponiert darzustellen ???:L Was sollen das für Buttons sein, was soll in die Tabelle rein?


----------



## bERt0r (9. Nov 2011)

Das war natürlich der falsche Renderer -.- war schon spät.

```
class MyCellRenderer extends JLabel implements TableCellRenderer
{
JButton button=new JButton("Hui");
JLabel label=new JLabel("Hallo Welt");
public Component getTableCellRendererComponent(JTable table, Object value,
                boolean isSelected, boolean hasFocus,
                int row, int column) 
		{
			if(row==3)
			{
				return button;
			}else
{
return label;
}
}
```
so ungefähr sollte das hinhaun, aber wie gesagt unschön. Mach die Buttons doch einfach unter den Table.


----------



## Michael... (9. Nov 2011)

NochKeinGuru hat gesagt.:


> mo.getOpenPoints() der Klasse Month liefert ein Objekt vom Typ JButton zurück


JButtons in eine TableModel zu stecken ist Unsinn, da man sowas ohnehin über den CellRenderer steuert.
Über einen JButton als Editor kann man streiten - gründsätzlich könnte man auch einfach per MouseListener auf einen Klick in die Zelle reagieren.

Um Zellen einer Spalte unterschiedlich zu rendern, kann man im Renderer abhängig von der Zeilennummer (s. Bsp bERt0r) oder einem anderen Merkmal unterschiedliche Renderingkomponenten zurückgeben.


----------



## Marco13 (9. Nov 2011)

Michael... hat gesagt.:


> JButtons in eine TableModel zu stecken ist Unsinn, da man sowas ohnehin über den CellRenderer steuert.



Jein... im allgemeinen schon, aber wenn man verschiedene Buttons mit verschiedenen Funktionalitäten haben will, muss man doch wieder für jede Zelle einen Button erstellen. Wie gesagt, das ist, wenn man's wirklich mal ausimplementieren will, frickeliger als man im ersten Moment meinen würde...


----------



## NochKeinGuru (9. Nov 2011)

Naja  als Merkmal hab ich ja eine Instanz eines Button an dieser Stelle des Modells  Das hab ich dann auch versucht zurück zu geben.Geht aber auch nur solange ich diesen Button und nicht einen anderen anklicke .


----------



## Michael... (9. Nov 2011)

Marco13 hat gesagt.:


> Jein... im allgemeinen schon, aber wenn man verschiedene Buttons mit verschiedenen Funktionalitäten haben will, muss man doch wieder für jede Zelle einen Button erstellen. Wie gesagt, das ist, wenn man's wirklich mal ausimplementieren will, frickeliger als man im ersten Moment meinen würde...


zu ersterem: OK, zu zweiterem: besitzt ein gerendertes Abbild keine Funktion ;-)

oftmals ändert sich aber nur der Text oder das Icon.


----------



## Michael... (9. Nov 2011)

es wäre hilfreich, wenn Du ein kurzes Code Beispiel posten könntest, anhand dessen wir das nachstellen können.

Dein hier geposteter CellRenderer (MyCellRenderer) gibt ja immer einen JButton zurück und nutzt den JButton im TableModel nur als Container für den Text.


----------



## NochKeinGuru (9. Nov 2011)

Aber das oben ist doch mein Code. Was fehlt denn? Der renderer  und der Editor werden der Tabelle doch als default  übergeben  mit Reaktion auf die Klasse  jbutton


----------



## Michael... (9. Nov 2011)

NochKeinGuru hat gesagt.:


> Aber das oben ist doch mein Code. Was fehlt denn?


Ein kleines Beispielprogramm, dass ich per Copy und Paste bei mir ausfürhen kann um das Problem nachzuvollziehen.
Deine Fehlerbeschreibung ist mir noch unklar.
Wenn der Renderer für JButton Objekte gesetzt ist warum die Überprüfung 
	
	
	
	





```
if (value == null)
```
?
Das mit dem JButton als Editor würde ich mir wie gesagt nochmal überlegen, ob man da nicht einfach mit einem MouseListener arbeitet. Wirft das Programm beim ausführen keine Fehler, wenn der Editor als DefaultEditor gesetzt ist?
Auch das Casten als JButton um sich selbst die eigenen Werte zu setzen macht keinen Sinn...
Ich vermute auch, dass der Editor nicht sauber beendet wird...


----------



## bERt0r (9. Nov 2011)

Schau dir die klammern genau an, ich weis nicht wie ich hier im Browser einrückungen hinkriege, darum ist das return label ganz links, es steht aber im else Zweig.
Weis jemand wie ich Tabulatorabstände hier im Forum machen kann?


----------



## NochKeinGuru (9. Nov 2011)

hallo zusammen,

danke für eure zahlreichen Antworten.

Also ich habe nun noch rausgefunden das es scheinbar geht wenn ich anstatt


```
table.setDefaultRenderer(JButton.class, new ButtonCellRenderer());
```

für jede Column


```
table.getColumnModel().getColumn(col).setCellRenderer(new ButtonCellRenderer());
```

mit col = 1-x schreibe... aber das ist sicherlich nicht so sehr sauber. Ich denke das ist wohl das was du meintest bertor.

Ausserdem musste ich noch das was ich im Editor mache in den Renderer verschieben.

Wenn ich nun eine Zelle anklicke wird nicht mehr die ganze zeile markiert. Es werden nur die Zellen in der Zeile balu gefärbt die nicht den CellRenderer in ihrer Column zugewiesen bekommen haben.

Ihr legt alle ein Objekt eines Button in dem Renderer an. Aber wozu brauche ich das? Ich bekomme doch meinen Button übergeben als Object value?!?


----------



## bERt0r (9. Nov 2011)

Schau mal da: Anhang anzeigen 3659


----------



## NochKeinGuru (9. Nov 2011)

wow super Hinweis.. danke!!

Es funktioniert nun schon besser.

Ein komischer Punkt bleibt jedoch. Ich kann eine Zelle nur wieder verlassen wenn ich ESC drücke... kann also nie einen Text eingeben


----------



## Michael... (9. Nov 2011)

Michael... hat gesagt.:


> Ein kleines Beispielprogramm, dass ich per Copy und Paste bei mir ausfürhen kann um das Problem nachzuvollziehen.
> ...
> Ich vermute auch, dass der Editor nicht sauber beendet wird...


...


----------



## NochKeinGuru (9. Nov 2011)

also ich kopier mal n bissl code zusammen der hoffentlich so dann funktioniert:

ich habs soweit hinbekommen das die buttons angezeigt werden und ich auch felder beschreiben kann. Nur wenn ich was in nen Feld schreibe taucht der Text in anderen Feldern auch auf:


```
package de.bilanz.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.LayoutManager;
import java.awt.event.MouseEvent;
import java.util.EventObject;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;


public class Gui extends JPanel implements TableModelListener{
		
	private static final long serialVersionUID = -1574097328663611091L;

	private MainTable table;
	private DefaultTableModel model;
	
	private Integer rowFixIncome = 1;
	private Integer rowDynIncome = 3;
	private Integer rowFixOutcome = 4;
	private Integer rowDynOutcome = 6;
	
	private Cathegories cath = null;

	public Gui() {
		super();		
	}


	public Gui(boolean isDoubleBuffered) {
		super(isDoubleBuffered);
		// TODO Auto-generated constructor stub
	}


	public Gui(LayoutManager layout, boolean isDoubleBuffered) {
		super(layout, isDoubleBuffered);
		// TODO Auto-generated constructor stub
	}


	public Gui(LayoutManager layout) {
		super(layout);
				
		String[] header = new String[2];
		Integer[] number = new Integer[2];
		for(int i=0;i<2;i++){
			number[i] = 0;
		}
		
		header[0] = "";
		header[1] = "Monat";
				
		model = new DefaultTableModel(header,0);		
		table = new MainTable(model);
		
		String[] row = new String[1];
		row[0] = "Offene Buchungen";
		model.addRow(row);
		row[0] = "Fixe Einnahmen";		
		model.addRow(row);
		row[0] = "Zwischensumme";
		model.addRow(row);
		row[0] = "Einmaleinnahmen";		
		model.addRow(row);
		row[0] = "Fixe Ausgaben";
		model.addRow(row);		
		row[0] = "Zwischensumme";
		model.addRow(row);
		row[0] = "Einmalausgaben";
		model.addRow(row);		
		row[0] = "Einnahmen";
		model.addRow(row);
		row[0] = "Ausgaben";
		model.addRow(row);
		row[0] = "Differenz";
		model.addRow(row);
		row[0] = "Kontostand Monatsende";
		model.addRow(row);
		
						
		for(int i=0;i<5;i++){
			Object[] objects = {new JButton()};
			model.addColumn("test",objects);
		}


						
		model.addTableModelListener(this);
		
		
	
		table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		table.getColumnModel().getColumn(0).setPreferredWidth(150);
		table.getColumnModel().getColumn(1).setPreferredWidth(150);
		table.getColumnModel().getColumn(2).setPreferredWidth(100);
		table.setRowHeight(20);
		
		JScrollPane scrollPane = new JScrollPane(table);		
		
		//FixedColumnTable fixed = new FixedColumnTable(2, scrollPane);
		//fixed.getFixedTable().setRowHeight(20); 
		
		/*table.getColumnModel().getColumn(3).setCellRenderer(new ButtonCellRenderer());
		table.getColumnModel().getColumn(4).setCellRenderer(new ButtonCellRenderer());
		
		table.getColumnModel().getColumn(3).setCellEditor(new ButtonCellEditor());
		table.getColumnModel().getColumn(4).setCellEditor(new ButtonCellEditor());
		*/
		
		TableCellRenderer r = new TableCellRenderer(){

			private JLabel lab = new JLabel();
			JButton button=new JButton();
			
			@Override
			public Component getTableCellRendererComponent(JTable table,
					Object value, boolean isSelected, boolean hasFocus,
					int row, int column) {
				if (row == 0 && value != null && value instanceof JButton){
			  		  //button.setText( ((JButton)value).getText());
			  		  //((JButton)value).setIcon( null );  		  
			  		  //return (JButton)value;
			    		//JButton b = (JButton)value;
			    		//button.setText(value.toString());
			    		//button.setText("jdj"); // text of idle button
			    		return (JButton)value;
			  	  }		
			  	  
			  	  //this.val = value;
			    	if(value!= null)
			    		lab.setText(((String)value));
			    	 if (row > 1 && row < 5) 
			             lab.setBackground(Color.GREEN);
			         else
			        	 lab.setBackground(Color.GREEN);
			    	 table.repaint();
			  	  return lab;
			}			
		};
		table.setDefaultRenderer(Object.class, r);		
		table.setDefaultEditor(Object.class, new MyCellEditor());
		
		//table.setDefaultRenderer(JButton.class, new ButtonCellRenderer());
		//table.setDefaultEditor(Object.class, new ButtonCellEditor());
		//fixed.getFixedTable().setDefaultRenderer(Object.class, new MyCellRenderer());
				
		this.add(scrollPane, BorderLayout.CENTER);
		
	}
	
	public class MyCellEditor extends AbstractCellEditor implements TableCellEditor
	{
	  private static final long serialVersionUID = 1800354749469202410L;
	  
	private JButton button;
	private JTextField lab;
	private String val;
	private boolean isButton = false;
	      
	  
	  public MyCellEditor() {
			super();
			button=new JButton();
			lab=new JTextField();
		}
	  
	  public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int rowIndex, int colIndex )
	  {
		  if(value!=null)
			{
				val=value.toString();
			}
			else
			{
				val="";
			}
			if(rowIndex==0)
			{
				button = (JButton)value;
				//button.setText("tethe"); // text of clicked button
				isButton = true;			
				return button;
			}else
			{
				isButton = false;
				lab.setText(val);
				table.repaint();
				return lab;
			}
		 
	  }
	  public Object getCellEditorValue()
	  {
		  if(isButton)
			{
				return val;
			}
			else
			{
				return lab.getText();
			}
	  }
	  
	  public boolean isCellEditable(EventObject anEvent)
	  {
	     if (anEvent instanceof MouseEvent)
	     {
	        //return ((MouseEvent)anEvent).getClickCount() >= clickCountToStart;
	     }
	     return true;
	 }
	  
	}
			
	@Override
	public void tableChanged(TableModelEvent e) {
		// TODO Auto-generated method stub
		int row = e.getFirstRow();
        int column = e.getColumn();
        MyTableModel model = (MyTableModel)e.getSource();
        String columnName = model.getColumnName(column);
        String data = null;
        if(row > 0 && column > 0)
        	data = (String)model.getValueAt(row, column);  
        else
        	return;
        
        String[] row1 = new String[1];
		row1[0] = "";
		
        if(row == rowFixIncome && column == 1 && !data.isEmpty()){        	
    		model.insertRow(row+1, row1);    
    		rowFixIncome++;
    		rowDynIncome++;
    		rowFixOutcome++;
    		rowDynOutcome++;
    		Cathegories.fixIncome.add((String)data);
        }
        if(row == rowDynIncome && column == 1 && !data.isEmpty()){        	
    		model.insertRow(row+1, row1);    
    		rowDynIncome++;
    		rowFixOutcome++;
    		rowDynOutcome++;
    		Cathegories.dynIncome.add((String)data);
        }
        if(row == rowFixOutcome && column == 1 && !data.isEmpty()){        	
    		model.insertRow(row+1, row1);    
    		rowFixOutcome++;
    		rowDynOutcome++;
    		Cathegories.fixOutcome.add((String)data);
        }
        if(row == rowDynOutcome && column == 1 && !data.isEmpty()){        	
    		model.insertRow(row+1, row1);    
    		rowDynOutcome++;
    		Cathegories.dynOutcome.add((String)data);
        }
        
        table.repaint();
	}
	
	


	public static void main(String args[]) {
					
		// Look and Feel des jeweiligen OS setzen
	      try
	      {
	         UIManager.setLookAndFeel (UIManager.getSystemLookAndFeelClassName ( ));
	      }
	      catch (Exception e)
	      {
	         e.printStackTrace ( );
	      }

	      
		JFrame frame = new JFrame("Bilanz");
		frame.setPreferredSize(new Dimension(1200, 800));
        
		Gui newContentPane = new Gui(new BorderLayout());
        //newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);
                        
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.pack();
        frame.setVisible( true );

	}
	
	
	
}
```


----------



## bERt0r (9. Nov 2011)

Tut mir leid, aber so wird das nix. Nur mit "codeschnipsel" kopieren und zusammensetzen kommst du nicht dahinter wie das läuft. Setz dich hin, lies den code durch, versuche zu verstehen was wo warum und wie gemacht wird.
Da sind so viele Merkwürdige sachen drin, als Lehrer möchte ich sowas nicht benoten, als Kunde setz ich dich vor die Tür:
Was sollen deine Konstruktoren bewirken?


> public Gui(LayoutManager layout, boolean isDoubleBuffered) {
> super(layout, isDoubleBuffered);
> // TODO Auto-generated constructor stub
> }


Warum in aller Welt machst du String-Arrays der Länge 1?


> String[] row = new String[1];
> row[0] = "Offene Buchungen";


Ein Array kannst du komfortabel über diese Schreibweise initialisieren:

```
String[] strings={"Spalte 1","Spalte 2", "Spalte 3"};
```
Du willst irgendwie ein Array aus JButtons direkt in deine Tabellendaten legen, von dem wurde dir bereits abgeraten. Nochdazu addest du das Array mittels addColumn ans model!?!?!?! Du willst sie doch in einer Zeile -.-

Entschuldigung für meinen harten Ton, aber dass du dich sowas hier posten traust zeigt einfach, dass du bei den Grundlagen noch gewisse Probleme hast. Und ohne die Grundlagen hat es echt keinen Sinn sich jetzt auf Tables zu konzentrieren - da heissts nachlernen. Kenne noch von meiner Ausbildung, viele Anfänger brauchen einfach jemanden, der ihnen persönlich und mit Zeitaufwand die Grundkenntnisse beibringt.


----------



## Marco13 (10. Nov 2011)

Vermutlich sollte es nur ein KSKB sein, damit Michael... gezielter helfen kann. (Im Zweifel für den Angeklagten )


----------



## Michael... (10. Nov 2011)

Das schaut ziemlich wild aus.

Warum benutzt Du einen eigene Klasse, die von JTable erbt? In der Regel reicht die Standard JTable für die meisten Zwecke aus?
Du verwendest eine DefaultTableModel. Scheinbar existiert noch ein MyTableModel, in der 
	
	
	
	





```
public void tableChanged(TableModelEvent e) {
```
 castest Du das DefaultTableModel auf ein MyTableModel - warum? Achtung diese Methode reagiert auf Änderungen des Models und Du änderst in dieser das Model, das kann böse ins Auge gehen, wenn man nicht aufpasst...

Grundsätzlich scheint in dem Code einiges im Argen zu liegen, da müsste man mal genauer drüber schaun - wenn man mal Zeit hat.

edit: die Verwendung von JButtons im TableModel ist meiner Meinung nach hier auf jeden Fall Unsinn


----------



## NochKeinGuru (10. Nov 2011)

Heiei.. ich hatte vergeblich gehofft mich nicht unnötig rechtfertigen zu müssen...

Also das mit dem Codeschnipsel zusammenkopieren ist nicht der Fall.. ich habe mich lange damit beschäftigt wie das wohl im Detail funktioniert.

Ich sitz jetzt schon ein paar Abende dran und versuch das mit den Buttons hinzubekommen.
Dabei geht es mir auch nur um diese Funktion... deshalb habe ich in erster Linie auch nicht geschaut wie ich das mit der String[1] schöner lösen kann. Mir ist schon klar das das nicht sauber ist. Aber das ist nun ja auch überhaupt nicht relevant für meine eigentliche Frage.

Die unnötigen Konstruktoren in der GUI Klasse wurden von Eclipse automatisch erzeugt als ich sagte das er die Konstruktoren anlegen soll. Aber auch das ist doch erstmal egal.

Die Buttons adde ich durch addColumn weil ich in Zukunft Strukturen haben werde die sich auf eine Spalte beziehen. Eben ein Monat. Dieser soll dann im optimalfall eben verschiedene Objekte beinhalten und ganz zu Beginn eben einen Button. 


Michael... ich erbe von JTable... ja.. ist vielleicht in Zukunft unnötig. Wer weis. Wennich keine Methoden modifiziert habe am Ende oder welceh hinzufügen möchte dann wird diese Klasse auch wieder rausfliegen.
Genauso mit dem Model. Ich habe ein eigenes Model ja... ich hab nur für euch hier damit der Code kleiner wird mein Klassenobjekt durch das Default erstzt da meines zur zeit auch nicht mehr macht. Aber wie gesagt wird sich am Ende rausstellen. beides hier aber auch unrelevant.

Genauso sind bei mir der Editor und der Renderer in eigenen Dateien... ich hab das nur hier zusammengefasst das es wie gewünscht ausführbar ist.

Wenn man den Kern betrachtet nämlich den Renderer und den Editor und ihr das Ding mal ausführt, dann seht ihr mein Problem das Texte die eingegeben werden in anderen Zellen ebenfalls auftauchen.. ganz egal ob ich nun drumrum den Code sauber implementiert habe (z.b. Array[1]). 
Und darum gehts mir eiegntlich erstmal nur.

Ich wünsche mir ein paar konstruktive Beiträge und etwas Verständnis dafür das ich den Code einfach gerne am Ende aufräumen möchte und sauber implementiere. Für mich zählt erstmal die Grundfunktionalität.

Danke..


----------



## Michael... (10. Nov 2011)

NochKeinGuru hat gesagt.:


> Wenn man den Kern betrachtet nämlich den Renderer und den Editor und ihr das Ding mal ausführt, dann seht ihr mein Problem das Texte die eingegeben werden in anderen Zellen ebenfalls auftauchen.


Um den Kern des Problems wäre es eben hilfreich auch nur den relevanten Kern des Programms als KSKB zu posten.
Ein Fehler liegt im Renderer. Hier wird beim JLabel der Inhalt gesetzt wenn 
	
	
	
	





```
value!=null
```
. Wenn allerdings der Fall 
	
	
	
	





```
value==null
```
 eintritt bleibt der alte Text stehen und die so gerenderte Zelle sieht so aus als hätte sie den selben Inhalt wie die zuvor gerenderte.


----------



## Marco13 (10. Nov 2011)

Ich sehe die Notwendigkeit zur Rechtfertigung auch weniger in irgendwelchen einzelnen Zeilen des Codes (in dem noch MainTable und Cat(h?)egories fehlten) sondern eher in _der Sache an sich_. 

Dass in dem Code dann wahllos Objekte erstellt und ungültig rum-gecastet werden, und der Code den Eindruck von unangemessenem Rumprobieren erweckt, und darüber hinaus das gewünschte Verhalten noch nicht beschrieben wurden, kommt noch dazu. 

Auch ich habe rumprobiert, und Quellcode gelesen, in JTable.java und DefaultTableCellRenderer.java, und versucht, was zusammenzustümpern.


```
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;

class JTableButtonRowTest
{
    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                JFrame f = new JFrame();
                f.getContentPane().add(createTableComponent());
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setSize(300,300);
                f.setVisible(true);
            }
        });
    }


    private static JComponent createTableComponent()
    {

        DefaultTableModel tableModel = new DefaultTableModel(
            new String[]{"Just", "a", "test"}, 0);

        tableModel.addRow(new Object[]{createButton(0, 0), "0,1", "0,2"});
        tableModel.addRow(new Object[]{"1,0", createButton(1, 1), "1,2"});
        tableModel.addRow(new Object[]{"2,0", "2,1", createButton(2, 2)});

        // Create the table
        JTable table = new JTable(tableModel);

        class Renderer extends DefaultTableCellRenderer implements TableCellRenderer
        {
            @Override
            public Component getTableCellRendererComponent(
                JTable table, Object value, boolean isSelected,
                boolean hasFocus, int row, int column)
            {
                if (value instanceof Component)
                {
                    return (Component)value;
                }
                super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                return this;
            }
        }
        table.setDefaultRenderer(Object.class, new Renderer());


        final TableCellEditor defaultEditor = new DefaultCellEditor(new JTextField());

        class Editor extends AbstractCellEditor implements TableCellEditor
        {
            private Object currentValue;


            @Override
            public Object getCellEditorValue()
            {
                Object result = currentValue;
                if (result == null)
                {
                    result = defaultEditor.getCellEditorValue();
                }
                currentValue = null;
                return result;
            }

            @Override
            public Component getTableCellEditorComponent(JTable table,
                Object value, boolean isSelected, int row, int column)
            {
                Component fallback = defaultEditor.getTableCellEditorComponent(
                    table, value, isSelected, row, column);
                if (value instanceof Component)
                {
                    currentValue = value;
                    return (Component)value;
                }
                return fallback;
            }
        }
        table.setDefaultEditor(Object.class, new Editor());


        JScrollPane scrollPane = new JScrollPane(table);
        return scrollPane;
    }


    private static JButton createButton(final int r, final int c)
    {
        JButton button = new JButton(r+","+c);;
        button.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                System.out.println("Pressed button at "+r+" "+c);
            }
        });
        return button;
    }


}
```

Ja, ich weiß, "bei mir geht das nicht, weil dies-und-das so-und-so ist, aber es so-und-so sein sollte und dann dies-und-das passiert". Beschreib' es so genau, dass man darauf eingehen kann.

Hoffentlich kommt André hier bald mal vorbei


----------



## bERt0r (11. Nov 2011)

Die Sache ist ja auch die, dass mein gepostetes Beispiel die Grundfunktionalität (Eine Zeile voller Buttons) vollständig erfüllt hat. Hab auch extra noch einen ActionListener drangehängt. Dass du jetzt einen Teil meines Beispiels rauskopierst, daran herumwerkst und es dann nicht funktioniert ist nicht verwunderlich. Mein Eindruck den du erweckst: entweder verstehst du die gebrachten Beispiele noch nicht (dann heists nachlernen) oder du bist zu faul sie richtig durchzulesen damit du sie verstehst.
Weiters finde ich, dass wenn du von uns Hilfe erwartest, du dir die Mühe machen könntest deinen Code kurz, übersichtlich und leserlich zu gestalten.


----------



## André Uhres (11. Nov 2011)

Hallo Freunde,

ich habe das jetzt nicht alles durchgelesen, aber vielleicht hilft ja schon dieses kleine Beispiel:

```
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.TableCellRenderer;

/**
 * TableLayoutDemo shows an example, how to use the "TableLayout" class.
 * Here it is:
 * http://wiki.byte-welt.net/wiki/TableLayout
 * 
 * @author André Uhres
 */
public class TableLayoutDemo extends JFrame {

    private TableLayout tableLayout;

    /**
     * Create a TableLayoutDemo.
     */
    public TableLayoutDemo() {
        super("TableLayout Demo");
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setSize(600, 600);
        setLocationRelativeTo(null);
        //create empty TableLayout:
        tableLayout = new MyTableLayout();
        tableLayout.setDefaultEditor(Number.class, new NumberEditor());
        //fill the TableLayout:
        for (int row = 0; row < 5; row++) {
            //create a test panel:
            Object[] elements = createTestRow(row);
            //add to TableLayout:
            tableLayout.addRow(elements);
        }
        getContentPane().add(new JScrollPane(tableLayout), BorderLayout.CENTER);
    }

    private Object[] createTestRow(final int row) {
        Object[] elements = new Object[4];
        if (row == 0) {
            for (int column = 0; column < 4; column++) {
                JButton button = new JButton("Button");
                final int buttonColumn = column;
                ActionListener actionListener = new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        JButton source = (JButton) e.getSource();
                        int total = 0;
                        for (int row = 1; row < tableLayout.getRowCount(); row++) {
                            String value = tableLayout.getValueAt(row, buttonColumn).toString();
                            total += Integer.parseInt(value);
                        }
                        source.setText(String.valueOf(total));
                    }
                };
                button.addActionListener(actionListener);
                elements[column] = button;
            }
        } else {
            for (int column = 0; column < 4; column++) {
                elements[column] = row + column;
            }
        }
        return elements;
    }

    /**
     * Method for testing.
     * @param args
     */
    public static void main(final String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TableLayoutDemo().setVisible(true);
            }
        });

    }

    private class NumberEditor extends DefaultCellEditor {

        private DecimalFormatSymbols numberSymbols;

        {
            numberSymbols = new DecimalFormatSymbols();
            numberSymbols.setGroupingSeparator('.');
            numberSymbols.setDecimalSeparator(',');
        }
        private DecimalFormat numberFormatter = new DecimalFormat("#########.##", numberSymbols);

        NumberEditor() {
            super(new JTextField());
            ((JTextField) getComponent()).setHorizontalAlignment(JTextField.RIGHT);
        }

        @Override
        public boolean stopCellEditing() {
            String value = ((JTextField) getComponent()).getText();
            if (!value.isEmpty()) {
                try {
                    numberFormatter.parse(value);
                } catch (ParseException e) {
                    ((JComponent) getComponent()).setBorder(new LineBorder(Color.red));
                    return false;
                }
            }
            return super.stopCellEditing();
        }

        @Override
        public Component getTableCellEditorComponent(final JTable table, final Object value,
                final boolean isSelected, final int row, final int column) {
            JTextField tf = ((JTextField) getComponent());
            tf.setBorder(new LineBorder(Color.black));
            try {
                tf.setText(numberFormatter.format(value));
            } catch (Exception e) {
                tf.setText("");
            }
            return tf;
        }

        @Override
        public Object getCellEditorValue() {
            try {
                return numberFormatter.parse(((JTextField) getComponent()).getText());
            } catch (ParseException ex) {
                return null;
            }
        }
    }

    private class MyTableLayout extends TableLayout {

        private final Color LIGHTGRAY = new Color(240, 240, 240);

        @Override
        public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
            Component c = super.prepareRenderer(renderer, row, column);
            c.setBackground(row % 2 == 0 ? null : LIGHTGRAY);
            return c;
        }
    }
}
```
Das Beispiel benutzt die Klasse TableLayout.

Gruß,
André


----------



## André Uhres (19. Nov 2011)

André Uhres hat gesagt.:


> Das Beispiel benutzt die Klasse TableLayout.



Ich habe versucht, die Verarbeitung von JTable Buttons in der Klasse ButtonHandler etwas zu vereinfachen.

Gruß,
André


----------



## Marco13 (19. Nov 2011)

Da wird man sicher das eine oder andere Mal drauf verlinken können. 

Ist aber schon komisch, dass man (wie im ersten Ansatz) so aufwändig eine eigentlich private Innere Klasse von JTable (?) komplett rausziehen und anpassen muss, bzw. dass es auch mit dem zweiten Ansatz noch so aufwändig ist... Um ComboBoxes und CheckBoxes haben sie sich doch auch gekümmert...?!


----------



## André Uhres (19. Nov 2011)

Ja, die Komplikationen kommen einerseits dadurch, dass JTable keinen Renderer oder Editor für JButtons unterstützt, andrerseits durch das für JTable untypische Erfordernis, mehrere Renderer oder Editor für eine Spalte zu erlauben.

Gruß,
André


----------

