PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : JButton in JTable


Gast
2004-02-13, 17:07:02
Kann man JButtons in ein JTable legen, so daß diese auch angezeigt werden?
Bei mir steht da nur "javax.swing.JButton[,0,0,0x0,invalid,layout=javax.swing.OverlayLayout,alignmentX=0.0,alignmentY=0.5, border=com.sun.java.swing.plaf.windows.XPStyle$XPEmptyBorde......."

HellHorse
2004-02-13, 17:44:19
Was hast du gemacht?
Ich würde einfach einenTableCellRenderer (http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/table/TableCellRenderer.html) machen, der einen JButton zurückgibt.

public class ButtonCellRenderer implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int column) {
return new JButton(value.toString());
}
}

Und dann die Buttons in einem Map oder so speichern und nicht immer neu generieren.

Gast
2004-02-14, 10:13:01
Danke, hat geklappt. Aber leider kann ich den Button in der Tablle nicht anklicken.
Wie kann ich das ändern? Außerdem hab ich mit einem Doppelklick wieder den Text da stehen, die Tabelle aber soll bis auf die Spalte in der die Buttons sind editierbar sein.

HellHorse
2004-02-14, 13:36:53
Damit du den Button anclicken kannst, muss die Zelle editierbar sein => TableModel.
Damit du mein anclicken des Buttons den Button und nicht ein JTextField erwischt musst du den CellEditor ändern. Falls das nur in einer Spalte geschehen soll, machst du das in der TableRow (http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/table/TableColumn.html#setCellEditor(javax.swing.table.TableCellEditor))

Hier ein Beispiel. Damit es funktioniert müssen der CellEditor und der CellRenderer das gleiche Objekt sein. Dafür bleiben die Buttons die gleichen und es werden nicht immer neue generiert.

public class ButtonCellRenderer implements TableCellEditor, TableCellRenderer {
private Map<Point, JButton> buttons;

private Set<CellEditorListener> editorListeners;

private JButton lastSelected;

public ButtonCellRenderer() {
this.buttons = new HashMap<Point, JButton>();
this.editorListeners = new HashSet<CellEditorListener>();
}

private JButton getButton(int row, int column, String label) {
JButton button = this.buttons.get(new Point(row, column));
if (button == null) {
button = new JButton();
button.addActionListener(new TableButtonListener(row, column));
}
button.setText(label);
return button;
}

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

public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected,
int row, int column) {
this.lastSelected = this.getButton(row, column, value.toString());
return this.lastSelected;
}

public Object getCellEditorValue() {
return this.lastSelected.getText();
}

public void addCellEditorListener(CellEditorListener l) {
this.editorListeners.add(l);
}

public void cancelCellEditing() {
ChangeEvent changeEvent = new ChangeEvent(this);
for (CellEditorListener nextListener : this.editorListeners) {
// ev synchronisieren, ev neuen Thread aufmachen
nextListener.editingCanceled(changeEvent);
}
}

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

public void removeCellEditorListener(CellEditorListener l) {
this.editorListeners.remove(l);
}

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

public boolean stopCellEditing() {
ChangeEvent changeEvent = new ChangeEvent(this);
for (CellEditorListener nextListener : this.editorListeners) {
// ev synchronisieren, ev neuen Thread aufmachen
nextListener.editingStopped(changeEvent);
}
return true;
}

private class TableButtonListener implements ActionListener {
private int x;
private int y;

public TableButtonListener(int x, int y) {
this.x = x;
this.y = y;
}

public void actionPerformed(ActionEvent e) {
System.out.println("button("+x+", "+y+") pressed");
}
}
}


Und da hätten wir noch das JTable Tutorial von Sun:
http://java.sun.com/docs/books/tutorial/uiswing/components/table.html

ethrandil
2004-02-14, 14:10:26
Dazu nochmal eine Anmerkung von mir:

@ Threadstarter:
HellHorses Beispiel ist für Java 1.5, das soltlest du vielleicht wissen, bevor du versuchst das mit 1.4 zu kompilieren :)

download hier (http://java.sun.com/j2se/1.5.0/download.jsp)

Gast
2004-02-14, 15:00:34
Original geschrieben von HellHorse
Damit du den Button anclicken kannst, muss die Zelle editierbar sein => TableModel.
Damit du mein anclicken des Buttons den Button und nicht ein JTextField erwischt musst du den CellEditor ändern. Falls das nur in einer Spalte geschehen soll, machst du das in der TableRow (http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/table/TableColumn.html#setCellEditor(javax.swing.table.TableCellEditor))

Hier ein Beispiel. Damit es funktioniert müssen der CellEditor und der CellRenderer das gleiche Objekt sein. Dafür bleiben die Buttons die gleichen und es werden nicht immer neue generiert.

public class ButtonCellRenderer implements TableCellEditor, TableCellRenderer {
private Map<Point, JButton> buttons;

private Set<CellEditorListener> editorListeners;

private JButton lastSelected;

public ButtonCellRenderer() {
this.buttons = new HashMap<Point, JButton>();
this.editorListeners = new HashSet<CellEditorListener>();
}

private JButton getButton(int row, int column, String label) {
JButton button = this.buttons.get(new Point(row, column));
if (button == null) {
button = new JButton();
button.addActionListener(new TableButtonListener(row, column));
}
button.setText(label);
return button;
}

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

public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected,
int row, int column) {
this.lastSelected = this.getButton(row, column, value.toString());
return this.lastSelected;
}

public Object getCellEditorValue() {
return this.lastSelected.getText();
}

public void addCellEditorListener(CellEditorListener l) {
this.editorListeners.add(l);
}

public void cancelCellEditing() {
ChangeEvent changeEvent = new ChangeEvent(this);
for (CellEditorListener nextListener : this.editorListeners) {
// ev synchronisieren, ev neuen Thread aufmachen
nextListener.editingCanceled(changeEvent);
}
}

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

public void removeCellEditorListener(CellEditorListener l) {
this.editorListeners.remove(l);
}

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

public boolean stopCellEditing() {
ChangeEvent changeEvent = new ChangeEvent(this);
for (CellEditorListener nextListener : this.editorListeners) {
// ev synchronisieren, ev neuen Thread aufmachen
nextListener.editingStopped(changeEvent);
}
return true;
}

private class TableButtonListener implements ActionListener {
private int x;
private int y;

public TableButtonListener(int x, int y) {
this.x = x;
this.y = y;
}

public void actionPerformed(ActionEvent e) {
System.out.println("button("+x+", "+y+") pressed");
}
}
}


Und da hätten wir noch das JTable Tutorial von Sun:
http://java.sun.com/docs/books/tutorial/uiswing/components/table.html

Gibts das Ganze nicht auch in Java 1.4 ??
Mal ebenso Java 1.5 mit ISDN runterladen ist irgendwie ungünstig :(.

HellHorse
2004-02-14, 15:45:08
Original geschrieben von Gast
Gibts das Ganze nicht auch in Java 1.4 ??
Mal ebenso Java 1.5 mit ISDN runterladen ist irgendwie ungünstig :(.
Ja, konnte mich nicht zurückhalten, sorry ;)
Aber du kannst es ja leicht nach 1.4 konvertieren,
<E> weglassen, dafür casts beim holen machen und Iterators verwenden so wird aus

private Map<Point, JButton> buttons;
this.buttons = new HashMap<Point, JButton>();
JButton button = this.buttons.get(new Point(row, column));
for (CellEditorListener nextListener : this.editorListeners) {
...
}

dann

private Map buttons;
this.buttons = new HashMap();
JButton button = (JButton) this.buttons.get(new Point(row, column));
Itertor listenersIterator = this.editorListeners.iterator();
while (listenersIterator.hasNext()) {
CellEditorListener nextListener = (CellEditorListener) listenersIterator.next();
...
}


Und copy-paste ist sowieso böse ;)


Gibt es keine Möglichkeit Simley's zwischen [code] zu deaktivieren und sonst zu aktivieren?

Gast
2004-02-14, 17:33:11
Juhuu, jetzt funktionierts! :)