# JButton in Zelle von JTable



## Olli123 (26. Mrz 2011)

Hallo liebe Java-Community!

Mein erster Beitrag ist gleich eine Frage zum Thema "Wie bekomme ich einen JButton in eine Zelle von einem JTable". Nachdem ich mehrere Stunden mich mit dem Thema Cellrenderer befasst habe, stellt sich bei mir die Frage ob es auch möglich ist nur in eine einzige Zelle einen Button zu implementieren, der sich nach einmaligen drücken "auflöst" und einen String mit der aktuellen Uhrzeit hinterlässt, die ich zuvor in einem JLabel generieren lasse. 
Das heißt der Benutzer soll die Möglichkeit haben den Button zu klicken, sodass in diese Zelle wo der Button sich befindet, sich danach die Uhrzeit befindet. 

Ich habe dafür schon einige Überlegungen angestellt wie ich das programmieren könnte und habe folgende Quelltexte für euch:


*Buttonrenderer* erschafft einen Button in einer Tabelle, die übergegeben werden muss.

```
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
/**
 *
 * @author Olli
 */
public class Buttonrenderer implements TableCellRenderer {

    JButton button = new JButton();

    public Component getTableCellRendererComponent(JTable table,
                                                   Object value,
                                                   boolean isSelected,
                                                   boolean hasFocus,
                                                   int row, int column) {
        button.setText(value.toString());
        return button;
}
}
```


*ButtonEditor* gibt die Möglichkeit dem Button eine Funktion beim Klicken zuzuweisen

```
import java.awt.*;
import java.awt.event.*;
import java.util.EventObject;
import javax.swing.*;
import javax.swing.table.*;
/**
 *
 * @author Olli
 */
public class ButtonEditor extends AbstractCellEditor implements TableCellEditor,
                                                         ActionListener {
    JTable table;
    JButton button = new JButton();
    int clickCountToStart = 1;

    public ButtonEditor(JTable table) {
        this.table = table;
        button.addActionListener(this);
    }

    public void actionPerformed(ActionEvent e) {

        meineMainClass.insertTime();// hier steht dann die Methode zum Zeitübertragen in die Zelle
        table.remove(button); // funktionniert nicht so wie ich es mir vorstelle xD
    }

    public Component getTableCellEditorComponent(JTable table,
                                                 Object value,
                                                 boolean isSelected,
                                                 int row, int column) {
        button.setText(value.toString());
        return button;
    }

    public Object getCellEditorValue() {
        return button.getText();
    }

    public boolean isCellEditable(EventObject anEvent) {
        if(anEvent instanceof MouseEvent) {
            return ((MouseEvent)anEvent).getClickCount() >= clickCountToStart;
        }
        return true;
    }

    public boolean shouldSelectCell(EventObject anEvent) {
        return true;
    }

    public boolean stopCellEditing() {
        return super.stopCellEditing();
    }

    public void cancelCellEditing() {
        super.cancelCellEditing();
    }
}
```



im Konstruktor der Main-Klasse:

```
buttonrenderer = new Buttonrenderer();
        meineTabelle.getColumnModel().getColumn(7).setCellRenderer(buttonrenderer);
        meineTabelle.getColumnModel().getColumn(7).setCellEditor(new ButtonEditor(meineTabelle));
```



Methode insertTime() in der MainClass:

```
meineTabelle.setValueAt(jLabel.getText(), currentRow, 7); 
// jLabel generiert die Zeit und currentRow mit Column Platz "7" ist quasi der Vektor oder die Referenz auf die gewünschte Zelle
```






Ich hoffe ich habe alles Nötige dazu gepostet und würde mich riesig freuen wenn mir dabei jemand weiterhelfen könnte. Falls Erklärungen noch fehlen sollten, reiche ich diese natürlich gerne nach, welches hoffentlich nicht der Fall sein sollte =).

Vielen Dank schon mal im Vorraus 

Grüße Olli123


----------



## Michael... (27. Mrz 2011)

Olli123 hat gesagt.:


> Nachdem ich mehrere Stunden mich mit dem Thema Cellrenderer befasst habe, stellt sich bei mir die Frage ob es auch möglich ist nur in eine einzige Zelle einen Button zu implementieren, der sich nach einmaligen drücken "auflöst" und einen String mit der aktuellen Uhrzeit hinterlässt, die ich zuvor in einem JLabel generieren lasse.


Ja sowas ist recht einfach umzusetzen, wobei das JLabel in dem die Uhrzeit "generiert" wird eher überflüssig zu sein scheint -  ausser es wird irgendwo im GUI eingebaut.
Die Lösung liegt hier im TableModel und im Renderer.

Ein ButtonEditor ist m.M. nicht unbedingt nötig, sowas wäre auch mit einem simplen MouseListener/Adapter möglich.

Man könnte dem TableModel für die "Button" Zellen ein eigens definiertes Objekt übergeben. Für diese Objektklasse setzt man per setDefaultTableCellRenderer(...) einen ButtonRenderer (wenn's unbedingt aussehen muss wie ein JButton). Wird auf die Zelle geklickt, setzt der MouseListener/ButtonEditor einfach die Zeit als String ins TableModel und schon wird der normale Renderer für Strings verwendet.


----------



## Olli123 (27. Mrz 2011)

das JLabel ist in der gui verankert und wird dort auch benötigt.



> Man könnte dem TableModel für die "Button" Zellen ein eigens definiertes Objekt übergeben. Für diese Objektklasse setzt man per setDefaultTableCellRenderer(...) einen ButtonRenderer (wenn's unbedingt aussehen muss wie ein JButton). Wird auf die Zelle geklickt, setzt der MouseListener/ButtonEditor einfach die Zeit als String ins TableModel und schon wird der normale Renderer für Strings verwendet.



Wie meinst du das? Könntest du wenn es geht mal nen kleinen Ausschnitt schreiben? Wäre echt nett, da ich gerade nicht verstehe was du genau meinst... Oder wo müsste ich das denn einbauen?

Viele Grüße

Olli123


----------



## Michael... (27. Mrz 2011)

Hatte nicht bedacht, dass die JTable bzw. das TableModel den Datentyp auch nur spaltenweise definieren kann.

Hier mal ein Bsp mit einem "doppelten" Renderer:

```
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.DateFormat;
import java.util.Calendar;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;

public class AnotherTableDemo extends JFrame {

	class Hurz {}

	public AnotherTableDemo() {
		final Hurz hurz = new Hurz();
		final JTable table = new JTable(
				new Object[][] {{hurz}, {hurz}, {"a string"},{hurz}, {"another string"}},
				new String[] {"Press To Change"}) {
			public boolean isCellEditable(int row, int column) {
				return false;
			}
		};
		table.setDefaultRenderer(Object.class, new HurzRenderer());
		this.getContentPane().add(new JScrollPane(table));
		
		table.addMouseListener(new MouseAdapter() {
			DateFormat df = DateFormat.getTimeInstance();
			public void mouseClicked(MouseEvent e) {
				int row = table.rowAtPoint(e.getPoint());
				int column = table.columnAtPoint(e.getPoint());
				if (table.getValueAt(row, column) instanceof Hurz) {
					Calendar calendar = Calendar.getInstance();
					table.setValueAt(df.format(calendar.getTime()), row, column);
				}
			}
		});
	}

	class HurzRenderer extends DefaultTableCellRenderer {
		private JButton button = new JButton("Press Me!");

		public Component getTableCellRendererComponent(JTable table,
				Object value, boolean isSelected, boolean hasFocus, int row, int col) {
			if (value instanceof Hurz)
				return button;
			super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
			return this;
		}
	}

	public static void main(String[] s) {
		JFrame frame = new AnotherTableDemo();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setBounds(0, 0, 300, 300);
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);
	}
}
```


----------



## Olli123 (2. Apr 2011)

Boar stark!!! Viiiiiiiiiiiiiiieeeeeeeeeeelen lieben Dank!!! es funktionniert super!! :applaus::applaus::applaus: genau so soll es funktionieren =). habs ein wenig angepasst und es funktioniert wunderbar!

Ich denke das thema ist damit erledigt =)


grüße

olli123


----------

