我一直在研究这个问题,我能找到的所有解决方案和工作示例都包含使用内置布尔TableCellRenderers渲染的复选框,即一个单元格只能有一个复选框。我没有找到任何工作示例,其中在该SAME单元格中的复选框旁边会有一些文本,或者更具体地说是允许复选框和文本的JCheckBox。
答案 0 :(得分:1)
如果您的数据/要求不符合默认的可用功能,则需要考虑提供自定义解决方案
我建议您首先查看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