【发布时间】:2021-06-24 17:58:52
【问题描述】:
问题
所以我的程序接收一个 .csv 文件并加载数据并显示它。加载数据时,它会为数据中的每个列标题创建一个新的JCheckBox。如何添加ActionListener 以便当用户勾选/取消勾选任何框时,它应该执行特定功能?
加载数据时,通过代码更新JPanel:
public void updateChecklistPanel(){
checklistPanel.removeAll();
checklistPanel.setLayout(new GridLayout(currentData.getColumnNames().length, 1, 10, 0));
for (String columnName : currentData.getColumnNames()){
JCheckBox checkBox = new JCheckBox();
checkBox.setText(columnName);
checklistPanel.add(checkBox);
}
checklistPanel.revalidate();
checklistPanel.repaint();
}
我在底部还有以下内容:
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == newDataFrameItem){
newFile();
System.out.println("New DataFrame Loaded in");
}
if (e.getSource() == loadDataFrameItem){
loadFile();
System.out.println(".csv Data loaded into DataFrame.");
}
if (e.getSource() == saveDataFrameItem){
System.out.println("Saved the data to a .csv file");
}
}
我想要做的是,当取消选中复选框时,它应该隐藏JTable 中的一列,并且在选中时,它应该重新显示该列。
当前解决方案
我想出的解决方案是创建一个变量allColumnHeaders,它是一个字符串的ArrayList。然后我还有一个变量shownColumnHeaders,它是一个布尔数组列表。当用户想要显示/隐藏列时,showColumn(String columnName) 和 hideColumn(String columnName) 函数会在 allColumnHeaders 中找到列 Name 的索引,并将 shownColumnHeaders 中索引的布尔值设置为 true/false。
它继续创建一个新的表模型,其中仅当该列的布尔值为 true 时才添加列。然后它将表的模型设置为新的表模型。
以下代码如下:
import java.awt.*;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
public class MRE extends JPanel {
private static JTable table;
private static ArrayList<String> allColumnHeaders = new ArrayList<>();
private static ArrayList<Boolean> shownColumnHeaders = new ArrayList<>();
private static void createAndShowGUI()
{
table = new JTable(5, 7);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane( table );
JPanel buttons = new JPanel( new GridLayout(0, 1) );
for (int i = 0; i < table.getColumnCount(); i++) {
String column = table.getColumnName(i);
allColumnHeaders.add(column);
JCheckBox checkBox = new JCheckBox(column);
checkBox.addActionListener(event -> {
JCheckBox cb = (JCheckBox) event.getSource();
if (cb.isSelected()) {
System.out.println(checkBox.getText() + " is now being displayed");
showColumn(checkBox.getText());
} else {
System.out.println(checkBox.getText() + " is now being hidden");
hideColumn(checkBox.getText());
}
table.setModel(createTableModel());
});
checkBox.setSelected( true );
buttons.add( checkBox );
shownColumnHeaders.add(true);
}
JPanel wrapper = new JPanel();
wrapper.add( buttons );
JFrame frame = new JFrame("MRE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(scrollPane, BorderLayout.CENTER);
frame.add(wrapper, BorderLayout.LINE_END);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static DefaultTableModel createTableModel(){
DefaultTableModel tableModel = new DefaultTableModel(0, 0);
String[] columnValues = new String[1];
for (int i = 0; i < shownColumnHeaders.size(); i++){
if (shownColumnHeaders.get(i)){
tableModel.addColumn(allColumnHeaders.get(i), columnValues);
}
}
return tableModel;
}
public static void showColumn(String columnName){
for (int i = 0; i < allColumnHeaders.size(); i++) {
if (allColumnHeaders.get(i).equals(columnName)){
shownColumnHeaders.set(i, true);
}
}
}
public static void hideColumn(String columnName){
for (int i = 0; i < allColumnHeaders.size(); i++) {
if (allColumnHeaders.get(i).equals(columnName)){
shownColumnHeaders.set(i, false);
}
}
}
public static void main(String[] args) throws Exception
{
SwingUtilities.invokeLater( () -> createAndShowGUI() );
}
}
【问题讨论】:
-
A JCheckBox 是 JToggleButton 的子类。您可以使用 addActionListener 方法为每个 JCheckBox 添加一个 ActionListener。
-
@GilbertLeBlanc 所以在生成checkBox的时候,我也在"checkBox.addActionListener(this);"这一行添加了但是我如何执行一个操作,因为我不知道它来自哪个源,因为它没有保存到变量或任何东西中
-
它应该做一个特定的功能 - 定义特定的功能。功能是否通用。例如,在计算器面板上,如果您单击 1、2、3、4 等,功能相同,您会在显示屏上添加一个数字。不同的是添加到显示中的数字。所以在这种情况下,可以使用相同的 ActionListener。如果函数的列标题名称不同,那么您可以在 Hashmap 中预定义每个 ActionListener。
-
您应该在创建 JCheckBox 时创建一个动作监听器。
checkBox.addActionListener(this)将不起作用,因为您使用的是e.getSource()==...,但源将是复选框。你想做什么? -
@Ryan 这不是minimal reproducible example。我无法编译和测试该代码。 MRE 的重点是简化问题并展示您创建的可重用解决方案。我发布了一个答案,这不是一个答案,但它是一个仅包含相关组件的起点。您应该能够通过添加到每个复选框的 ActionListener 添加您的“可重用”类来控制列的可见性。如果您努力发布正确的 MRE,我将使用使用我的可重用类所需的 4 行代码来更新我的答案。
标签: java swing jframe jpanel actionlistener