我已经摆弄这个问题有一段时间了,我能找到的所有解决方案和工作示例都包含使用内置 boolean TableCellRenderers 渲染的复选框,即一个单元格只能有一个复选框。我没有找到任何工作示例,其中在同一单元格中的复选框旁边会有一些文本,或者更具体地说,是一个允许复选框和文本的 JCheckBox。
最佳答案
当您的数据/要求不符合默认可用功能时,您需要寻求提供定制解决方案
我建议您首先查看 Using custom renderers
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
public class Test {
public static void main(String[] args) {
new Test();
}
public class Data {
private String text;
private boolean selected;
public Data(String text, boolean selected) {
this.text = text;
this.selected = selected;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean state) {
this.selected = state;
}
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
DefaultTableModel model = new DefaultTableModel(new String[] {"Something"}, 0) {
@Override
public Class<?> getColumnClass(int columnIndex) {
return Data.class;
}
};
model.addRow(new Object[]{new Data("Hello", true)});
model.addRow(new Object[]{new Data("Goodbye", false)});
model.addRow(new Object[]{new Data("Do you want to play a game?", true)});
model.addRow(new Object[]{new Data("Yesturday", false)});
model.addRow(new Object[]{new Data("Tomorrow", true)});
model.addRow(new Object[]{new Data("Java", false)});
model.addRow(new Object[]{new Data("Swift", false)});
model.addRow(new Object[]{new Data("Helicopter", true)});
JTable table = new JTable(model);
table.setDefaultRenderer(Data.class, new DataTableCellRenderer());
add(new JScrollPane(table));
}
}
public class DataTableCellRenderer extends JCheckBox implements TableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
setBackground(table.getSelectionBackground());
setForeground(table.getSelectionForeground());
} else {
setBackground(table.getBackground());
setForeground(table.getForeground());
}
if (value instanceof Data) {
Data data = (Data)value;
setText(data.getText());
setSelected(data.isSelected());
}
return this;
}
}
}
此时,我想知道 JTable
是否是最佳解决方案,以及 JList
是否可能更好
当然,另一种可能更适合 JTable
的选择是设计一个自定义 TableModel
,它可以将数据分解为单独的列...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableModel;
public class Test {
public static void main(String[] args) {
new Test();
}
public class Data {
private String text;
private boolean selected;
public Data(String text, boolean selected) {
this.text = text;
this.selected = selected;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean state) {
this.selected = state;
}
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
DataTableModel model = new DataTableModel();
model.add(new Data("Hello", true));
model.add(new Data("Goodbye", false));
model.add(new Data("Do you want to play a game?", true));
model.add(new Data("Yesturday", false));
model.add(new Data("Tomorrow", true));
model.add(new Data("Java", false));
model.add(new Data("Swift", false));
model.add(new Data("Helicopter", true));
JTable table = new JTable(model);
add(new JScrollPane(table));
}
}
public class DataTableModel extends AbstractTableModel {
private List<Data> rows = new ArrayList<>(25);
public void add(Data data) {
int rowCount = getRowCount();
rows.add(data);
fireTableRowsInserted(rowCount, rowCount);
}
@Override
public String getColumnName(int column) {
switch (column) {
case 0: return "";
case 1: return "Option";
}
return null;
}
@Override
public int getRowCount() {
return rows.size();
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0: return Boolean.class;
case 1: return String.class;
}
return Object.class;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Data row = rows.get(rowIndex);
switch (columnIndex) {
case 0: return row.isSelected();
case 1: return row.getText();
}
return null;
}
}
}
恕我直言,这是使用 JTable
的更好解决方案
关于java - 在 Jtable 单元格中的复选框旁边插入文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47851299/