K
Kaffeemaschinist
Gast
Hallo!
Ich habe zu diesem Thema die letzten zwei Tage jede Menge Posts hier gelesen, aber so richtig zum Schluss kommt keines.
Es geht darum, dass ein JTable angezeigt wird, der 1 Spalte mit einem JButton besitzt (welcher der Darstellung wg. auf einem JPanel sitzt). Der Button ist sozusagen ein Singleton, da er nur dafür da ist, eine Aktion auszulösen, dessen wichtige Daten ich mir später über den aktuellen JTable-Zustand holen möchte.
Folgende Probleme treten auf: Bei Druck auf den Button funktioniert die Sache, drückt man mit der Maus aber auf das darunterliegende JPanel, dann passieren die wildesten Sachen, vor allem Darstellungsfehler. In meinem Beispiel ist ein sehr einfaches TableModel, ein TableCellRenderer, ein TableCellEditor, die Button-Klasse und die Start-Klasse enthalten.
Meine Frage ist, warum der Klick auf das Panel so seltsame Aktionen auslöst und ob mein Ansatz evtl. in die richtige Richtung geht.
Den Quellcode hab ich mal hier ins Forum hochgeladen:
Starter.java
JTableButton.java
ButtonRenderer.java
ButtonEditor.java
JTableModel.java
Ich habe zu diesem Thema die letzten zwei Tage jede Menge Posts hier gelesen, aber so richtig zum Schluss kommt keines.
Es geht darum, dass ein JTable angezeigt wird, der 1 Spalte mit einem JButton besitzt (welcher der Darstellung wg. auf einem JPanel sitzt). Der Button ist sozusagen ein Singleton, da er nur dafür da ist, eine Aktion auszulösen, dessen wichtige Daten ich mir später über den aktuellen JTable-Zustand holen möchte.
Folgende Probleme treten auf: Bei Druck auf den Button funktioniert die Sache, drückt man mit der Maus aber auf das darunterliegende JPanel, dann passieren die wildesten Sachen, vor allem Darstellungsfehler. In meinem Beispiel ist ein sehr einfaches TableModel, ein TableCellRenderer, ein TableCellEditor, die Button-Klasse und die Start-Klasse enthalten.
Meine Frage ist, warum der Klick auf das Panel so seltsame Aktionen auslöst und ob mein Ansatz evtl. in die richtige Richtung geht.
Den Quellcode hab ich mal hier ins Forum hochgeladen:
Starter.java
Code:
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class Starter extends JFrame {
public Starter () {
this.setLayout(new GridLayout(2,1));
/* table init */
TableModel model = new TableModel((ActionListener)null, "actionCommand", "x");
JTable table = new JTable(model);
table.setPreferredScrollableViewportSize(new Dimension (300,60));
table.setFillsViewportHeight(true);
/* set default renderer for table buttons */
table.setDefaultRenderer(JTableButton.class, new ButtonRenderer());
table.setDefaultEditor (JTableButton.class, new ButtonEditor());
/* add table on a scroll pane to this panel */
this.add(new JScrollPane(table));
this.add(new JButton("A useless button"));
this.pack();
this.setVisible(true);
}
public static void main(String[] args) {
Starter starter = new Starter();
}
}
JTableButton.java
Code:
import java.awt.event.ActionListener;
import javax.swing.JButton;
public class JTableButton
extends JButton {
public JTableButton (
final String caption,
final String actionCmd,
final ActionListener actionListener) {
super(caption);
this.addActionListener(actionListener);
this.setActionCommand(actionCmd);
}
}
ButtonRenderer.java
Code:
import java.awt.Component;
import java.awt.FlowLayout;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
public class ButtonRenderer extends JPanel implements TableCellRenderer {
public ButtonRenderer() {
super(new FlowLayout(FlowLayout.CENTER,0,0));
this.setOpaque(true);
}
public Component getTableCellRendererComponent(
final JTable table, final Object value,
final boolean isSelected, final boolean hasFocus,
final int row, final int column) {
JTableButton tableButton = (JTableButton) value;
this.add(tableButton);
/* emphasize selection by changing label's background color */
if (isSelected) {
this.setBackground(table.getSelectionBackground());
} else {
this.setBackground(table.getBackground());
}
return this;
}
}
ButtonEditor.java
Code:
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractCellEditor;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;
public class ButtonEditor extends AbstractCellEditor implements TableCellEditor, ActionListener {
private JTableButton originalButton;
private JPanel buttonPanel;
private boolean isPushed;
public ButtonEditor () {
this.buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER,0,0));
this.buttonPanel.setOpaque(true);
}
public Component getTableCellEditorComponent(
final JTable table,
final Object value,
final boolean isSelected,
final int row,
final int column) {
/* return same button on panel */
this.originalButton = (JTableButton) value;
this.originalButton.addActionListener(this);
this.buttonPanel.add(this.originalButton);
isPushed = true;
return this.buttonPanel;
}
public Object getCellEditorValue() {
if (isPushed) {
System.out.println("getCellEditorValue()");
}
isPushed = false;
return this.originalButton;
}
public boolean stopCellEditing() {
/* TODO: oeffne hier einen Dialog */
/* ... */
isPushed = false;
return super.stopCellEditing();
}
protected void fireEditingStopped() {
super.fireEditingStopped();
}
public void actionPerformed(ActionEvent e) {
this.fireEditingStopped();
}
}
JTableModel.java
Code:
import java.awt.Color;
import java.awt.Insets;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.table.AbstractTableModel;
public class TableModel extends AbstractTableModel {
private final String[] columnNames = {"Delete field", "Field name", "Show distinct value"};
/** button for showing "distinct values" */
private JTableButton distinctValuesButton;
private Object[][] data = {
{false, "name 1", null},{false, "name 2", null},{false, "name 3", null},
};
public TableModel (
final ActionListener actionListener,final String actionCommand, final String caption) {
/* create button */
this.distinctValuesButton = new JTableButton(caption, actionCommand,actionListener);
this.distinctValuesButton.setMargin(new Insets(0,0,0,0));
this.distinctValuesButton.setBorder(BorderFactory.createLineBorder(Color.BLACK));
/* set button */
for (int i=0; i<data.length; i++) {
data[i][2] = this.distinctValuesButton;
}
}
public int getColumnCount() {
return this.columnNames.length;
}
public int getRowCount() {
return this.data.length;
}
public Object getValueAt(final int rowIndex,final int columnIndex) {
return this.data[rowIndex][columnIndex];
}
@Override
public Class<?> getColumnClass( final int columnIndex) {
return getValueAt(0, columnIndex).getClass();
}
@Override
public String getColumnName(final int column) {
return this.columnNames[column];
}
@Override
public boolean isCellEditable(final int rowIndex,final int columnIndex) {
return true;
}
@Override
public void setValueAt( final Object value, final int rowIndex, final int columnIndex) {
this.data[rowIndex][columnIndex] = value;
/* fire event */
this.fireTableCellUpdated(rowIndex,columnIndex);
}
}