[英]How to make JButton clickable in JTable
我有一個程序,其中大多數單元格中有一個帶有文本的 JTable,但是每行中的最后一個單元格我需要有一個 JButton。 我正在使用自定義按鈕渲染器和編輯器(我不希望用戶編輯表中任何內容的內容)。 我不確定如何讓我的按鈕可點擊。 我的主要代碼是:
起點.java
import java.util.Vector;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
public class StartingPoint {
public static void main(String[] args) {
String column_names[] = {"Text", "Button"};
DefaultTableModel dtm = new DefaultTableModel(column_names, 0);
JButton button1 = new JButton();
button1.setText("Button 1");
button1.setToolTipText("Button");
JButton button2 = new JButton();
button2.setText("Button 2");
button2.setToolTipText("Buttonnn");
Vector<Object> row1 = new Vector<Object>();
row1.add("Testing");
row1.add(button1);
Vector<Object> row2 = new Vector<Object>();
row2.add("More Testing");
row2.add(button2);
dtm.addRow(row1);
dtm.addRow(row2);
JTable table = new JTable(dtm);
JScrollPane scrolly = new JScrollPane(table);
table.setFillsViewportHeight(true);
JTableButtonRenderer buttonRenderer = new JTableButtonRenderer();
JTableButtonEditor buttonEditor = new JTableButtonEditor();
table.getColumn("Button").setCellRenderer(buttonRenderer);
table.getColumn("Button").setCellEditor(buttonEditor);
JFrame frame = new JFrame("Testing");
frame.getContentPane().add(scrolly);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
JTableButtonRenderer
import java.awt.Component;
import javax.swing.JButton;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
public class JTableButtonRenderer implements TableCellRenderer {
JTableButtonRenderer() {}
@Override
public Component getTableCellRendererComponent(JTable table, Object
value, boolean isSelected, boolean hasFocus, int rows, int columns) {
JButton button = (JButton)value;
return button;
}
}
JTableButtonEditor.java
import java.awt.Component;
import java.util.EventObject;
import javax.swing.JTable;
import javax.swing.event.CellEditorListener;
import javax.swing.table.TableCellEditor;
public class JTableButtonEditor implements TableCellEditor {
@Override
public void addCellEditorListener(CellEditorListener arg0) {
// TODO Auto-generated method stub
}
@Override
public void cancelCellEditing() {
// TODO Auto-generated method stub
}
@Override
public Object getCellEditorValue() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isCellEditable(EventObject arg0) {
// TODO Auto-generated method stub
return false;
}
@Override
public void removeCellEditorListener(CellEditorListener arg0) {
// TODO Auto-generated method stub
}
@Override
public boolean shouldSelectCell(EventObject arg0) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean stopCellEditing() {
// TODO Auto-generated method stub
return false;
}
@Override
public Component getTableCellEditorComponent(JTable arg0, Object arg1,
boolean arg2, int arg3, int arg4) {
// TODO Auto-generated method stub
return null;
}
}
我需要更改渲染器/編輯器類中的某些內容嗎? 我還嘗試在創建按鈕時在我的開始點類中添加動作偵聽器。
“概念上”,這個想法非常簡單,在如何使用表格中有詳細介紹
您需要從定義編輯器(和渲染器)開始。 為簡單起見,我選擇將兩者包裝在一起,因為兩者都重復了大部分功能。
public class TableDeleteButtonEditor extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
private File source;
private JButton button;
public TableDeleteButtonEditor() {
button = new JButton();
button.addActionListener(new LoadActionListener());
}
@Override
public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
protected JButton prepare(JTable table, Object value, boolean isSelected, int row, int column) {
if (!(value instanceof File)) {
source = null;
button.setEnabled(false);
return null;
}
source = (File) value;
button.setEnabled(true);
button.setText(source.getName());
button.setToolTipText(source.getPath());
return button;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
return prepare(table, value, isSelected, row, column);
}
@Override
public Object getCellEditorValue() {
return source;
}
@Override
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
return prepare(table, value, isSelected, row, column);
}
public class LoadActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent evt) {
// Here, you need to make some decisions about what to do...
// You have a reference to the File instance
System.out.println("You clicked " + source);
stopCellEditing();
}
}
}
由於您可能只有一個活動編輯器,因此在調用getTableCellEditorComponent
時,您需要獲取對基礎數據的引用(即File
引用)。
通常,編輯器會將一個值返回給模型,在這種情況下,我不確定這是否有意義。 不是說你做不到,但我會質疑目的。
對於我的示例,我只需要對File
本身的引用,因此,從技術上講,我只需要一列。 相反,我設計了一個需要兩列的模型,但使用File
的引用來填充這兩列。 這是一個簡潔的示例,它演示了將“簡單”對象擴展為多個部分並以不同方式由模型表示的能力......
public class FileTableModel extends AbstractTableModel {
private List<File> files;
public FileTableModel(List<File> files) {
this.files = files;
}
@Override
public int getRowCount() {
return files.size();
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 1;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 1: return File.class;
default: return String.class;
}
}
@Override
public Object getValueAt(int row, int col) {
File file = files.get(row);
switch (col) {
case 0: return file.getName();
case 1: return file;
}
return null;
}
}
現在,這里的重要部分是isCellEditable
和getColumnClass
方法。 這些有助於確定可以編輯哪些單元格並提供一個入口點來查找JTable
渲染器/編輯器,這將我們帶到下一步,您需要配置JTable
以支持您的自定義編輯器/渲染器
有幾種方法可以做到這一點,但為了簡單起見, setDefaultRenderer
和setDefaultEditor
應該可以正常工作......
List<File> files = Arrays.asList(new File(".").listFiles());
FileTableModel model = new FileTableModel(files);
JTable table = new JTable(model);
table.setDefaultEditor(File.class, new TableDeleteButtonEditor());
table.setDefaultRenderer(File.class, new TableDeleteButtonEditor());
注意:您可以使用TableDeleteButtonEditor
的單個實例,我只是懶得復制和粘貼
從那里,您現在應該能夠在JTable
表示File
的列表,其中最后一列是一個按鈕(帶有文件名),在此示例中,單擊時將打印File
引用
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.Arrays;
import java.util.EventObject;
import java.util.List;
import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
List<File> files = Arrays.asList(new File(".").listFiles());
FileTableModel model = new FileTableModel(files);
JTable table = new JTable(model);
table.setDefaultEditor(File.class, new TableDeleteButtonEditor());
table.setDefaultRenderer(File.class, new TableDeleteButtonEditor());
add(new JScrollPane(table));
}
}
public class FileTableModel extends AbstractTableModel {
private List<File> files;
public FileTableModel(List<File> files) {
this.files = files;
}
@Override
public int getRowCount() {
return files.size();
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 1;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 1:
return File.class;
default:
return String.class;
}
}
@Override
public Object getValueAt(int row, int col) {
File file = files.get(row);
switch (col) {
case 0:
return file.getName();
case 1:
return file;
}
return null;
}
}
public class TableDeleteButtonEditor extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
private File source;
private JButton button;
public TableDeleteButtonEditor() {
button = new JButton();
button.addActionListener(new LoadActionListener());
}
@Override
public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
protected JButton prepare(JTable table, Object value, boolean isSelected, int row, int column) {
if (!(value instanceof File)) {
source = null;
button.setEnabled(false);
return null;
}
source = (File) value;
button.setEnabled(true);
button.setText(source.getName());
button.setToolTipText(source.getPath());
return button;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
return prepare(table, value, isSelected, row, column);
}
@Override
public Object getCellEditorValue() {
return source;
}
@Override
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
return prepare(table, value, isSelected, row, column);
}
public class LoadActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent evt) {
// Here, you need to make some decisions about what to do...
// You have a reference to the File instance
System.out.println("You clicked " + source);
stopCellEditing();
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.