问题描述
所以我的程序接收一个.csv文件并加载数据并显示它.加载数据后,它将为数据中存在的每个列标题创建一个新的 JCheckBox
.如何添加 ActionListener
,以便当用户勾选/取消选中任何框时,它应该执行某些功能?
So my program takes in a .csv file and loads the data and displays it. When data is loaded in, it creates a new JCheckBox
for every column header there is in the data. How do I add an ActionListener
such that when the user ticks/unticks any of the boxes, it should do a certain function?
加载数据后,它将通过以下代码更新 JPanel
:
When data is loaded in, it updates the JPanel
by the code:
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();
}
我在底部也有以下内容:
I also have the following at the bottom:
@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
中隐藏一列,而在选中时,它应该重新显示该列.
What I'm trying to do is that when a checkbox is unticked, it should hide a column in the JTable
and when ticked, it should redisplay the column.
我想出的解决方案是使变量 allColumnHeaders
成为字符串的ArrayList.然后,我还有一个变量 shownColumnHeaders
,它是布尔值的ArrayList.当用户想要显示/隐藏列时, showColumn(String columnName)
和 hideColumn(String columnName)
函数在 allColumnHeaders中找到列名的索引
并将 shownColumnHeaders
中索引的布尔值设置为true/false.
The solution that I have come up with is to make a variable allColumnHeaders
that is an ArrayList of Strings. I then also have a variable shownColumnHeaders
that is an ArrayList of Booleans. When the user wants to show/hide a column, the showColumn(String columnName)
and hideColumn(String columnName)
function finds the index of the column Name in allColumnHeaders
and sets the Boolean value of the index in shownColumnHeaders
to either true/false.
此过程将创建一个新的表模型,仅在该列的布尔值为true时才添加该列.然后,它将表的模型设置为新的表模型.
It the proceeds to create a new table model where the columns are only added if the Boolean value for that column is true. It will then set the model for the table to the new table model.
下面的代码如下所示:
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() );
}
}
推荐答案
这仅演示如何创建基本的MRE:
This only demonstrates how to create a basic MRE:
- csv文件不相关.
- 模型中的数据无关.
- 您的loadFile,newFile和saveFile按钮无关.
- TableModel不相关
您的问题是有关基于表的列向动态创建的复选框添加ActionListener.
Your question is about adding an ActionListener to dynamically created checkboxes based on the columns of the table.
因此,您需要的是一个带有一些列和相应复选框的表.
So all you need is a table with some columns and the resulting checkboxes.
import java.awt.*;
import javax.swing.*;
public class MRE extends JPanel
{
private static void createAndShowGUI()
{
JTable 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);
JCheckBox checkBox = new JCheckBox("Display " + column);
checkBox.setSelected( true );
buttons.add( checkBox );
}
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 void main(String[] args) throws Exception
{
SwingUtilities.invokeLater( () -> createAndShowGUI() );
}
}
如果您可以修改此内容以演示如何使用可重用类",则为了管理列的可见性,那么我将更新上面的代码,以将我的可重用类与另外4行代码一起使用.
If you can modify this to demonstrate how to use your "reusable class" to manage column visibility, then I will update the above code to use my reusable class with 4 additional lines of code.
建议对代码进行改进:
- 使代码可重用且自包含
- 不要使用静态方法
- 请勿更改数据.
您最初的问题是:
如何将ActionListener添加到JCheckBox?
为此,您需要一个类:
- 实现一个
ActionListener
- 是自包含的,可以实现您所需的功能.
所以基本结构可能如下:
So the basic structure could be like the following:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SomeFunction implements ActionListener
{
private JTable table;
public SomeFunction(JTable table)
{
this.table = table;
}
@Override
public void actionPerformed(ActionEvent e)
{
if (e.getSource() instanceof AbstractButton)
{
String command = e.getActionCommand();
AbstractButton button = (AbstractButton)e.getSource();
if (button.isSelected())
doSelected( command );
else
doUnselected( command );
}
}
private void doSelected(String command)
{
System.out.println(command + " selected");
}
private void doUnselected(String command)
{
System.out.println(command + " unselected");
}
private static void createAndShowGUI()
{
JTable table = new JTable(5, 7);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane( table );
JPanel buttons = new JPanel( new GridLayout(0, 1) );
SomeFunction listener = new SomeFunction( table ); // added
// TableColumnManager listener = new TableColumnManager(table, false);
// ColumnListener listener = new ColumnListener();
for (int i = 0; i < table.getColumnCount(); i++)
{
String column = table.getColumnName(i);
JCheckBox checkBox = new JCheckBox("Display " + column);
checkBox.setSelected( true );
checkBox.setActionCommand( column ); // added
checkBox.addActionListener( listener ); // added
buttons.add( checkBox );
}
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 void main(String[] args) throws Exception
{
SwingUtilities.invokeLater( () -> createAndShowGUI() );
}
}
无论您执行什么功能,它都只需要知道应该对它进行操作的表.
Whatever your function does it only needs to know about the table it should act upon.
因此,尝试将代码重组为可重用的类.
So try to restructure your code into a reusable class.
如果要使用Gilberts代码,则需要将 ColumnListener
类重组为一个单独的可重用的自包含类.
If you want to use Gilberts code, then you need to restructure the ColumnListener
class into a separate reusable self contained class.
最后,您也可以尝试我的可重用课程.请查看表列管理器以下载该类.
Finally you can also try my reusable class. Check out Table Column Manager for the class to download.
无论您决定使用哪种可重用类,您都只需要更改上述示例中的一行代码即可(一旦您的功能包含在可重用类中).
Whatever reusable class you decide to use, you will only need to change a single line of code from the above example (once your functionality is contained in a reusable class).
请注意,静态方法将不属于最终类.它们只是在那里,因此简化了MRE的测试和在单个类文件中的发布.
Note the static methods would not be part of the final class. They are only there so simplify testing and posting of an MRE in a single class file.
希望这有助于将来的设计考虑.
Hope this helps with future design considerations.
这篇关于如何将ActionListener添加到JCheckBox?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!