簡體   English   中英

如何將 ActionListener 添加到 JCheckBox?

[英]How do I add an ActionListener to a JCheckBox?

問題

所以我的程序接受一個.csv 文件並加載數據並顯示它。 加載數據時,它會為數據中的每一列 header 創建一個新的JCheckBox 如何添加一個ActionListener以便當用戶勾選/取消勾選任何框時,它應該執行某個 function?

加載數據時,它會通過以下代碼更新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 ,它是布爾值的 ArrayList。 當用戶想要顯示/隱藏列時, showColumn(String columnName)hideColumn(String columnName) function 在allColumnHeaders中查找列 Name 的索引,並將 shownColumnHeaders 中索引的shownColumnHeaders值設置為 true/false。

它將繼續創建一個新表 model,其中僅當該列的 Boolean 值為 true 時才添加列。 然后它將表的 model 設置為新表 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() );
    }

}

介紹

我花了一段時間,但我想出了以下JTable GUI。 這是開始的顯示。

JCheckBox 表 GUI 1

這是我刪除項目描述后的 GUI。

JCheckBox 表 GUI 2

這是我刪除商品價格后的 GUI。

JCheckBox 表 GUI 3

這是我添加列后的 GUI。

JCheckBox 表 GUI 4

解釋

我創建了一個Item class 來容納一個項目。

我創建了一個Inventory class 來保存一個Item實例列表和一個列標題的String數組。

我創建了JFrame和兩個JPanels 一個JPanel持有JTable ,另一個持有JCheckBoxes 我使用 Swing 布局管理器來創建JPanels

到目前為止,很基本。 創建JTable需要一些努力。 我想將商品價格顯示為貨幣,但這對於這個示例 GUI 來說並不重要。

我創建了一個ActionListener來添加和刪除JTable中的列。 我不得不做一些實驗。 TableColumnModel addColumn方法將列附加到表中。

我必須創建一個DisplayTableColumn class 來保存一個TableColumn和一個告訴我是否顯示TableColumn的 boolean 。 我最終從JTable中刪除了所有列,並將所有列添加回JTable以便我可以保持列順序。 我可能運行了 100 次測試才能讓這段代碼工作。

代碼

這是完整的可運行代碼。

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

public class JCheckBoxTableGUI implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new JCheckBoxTableGUI());
    }
    
    private final Inventory inventory;
    
    private final InventoryTableModel tableModel;
    
    private JFrame frame;
    
    private JTable table;
    
    public JCheckBoxTableGUI() {
        this.tableModel = new InventoryTableModel();
        this.inventory = new Inventory();
        
        String[] columns = inventory.getTableHeader();
        for (String column : columns) {
            tableModel.addColumn(column);
        }
        
        List<Item> items = inventory.getInventory();
        for (Item item : items) {
            Object[] object = new Object[5];
            object[0] = item.getItemNumber();
            object[1] = item.getItemName();
            object[2] = item.getItemDescription();
            object[3] = item.getItemQuantity();
            object[4] = item.getItemPrice();
            tableModel.addRow(object);
        }
    }

    @Override
    public void run() {
        frame = new JFrame("JCheckBox Table GUI");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.add(createTablePanel(), BorderLayout.CENTER);
        frame.add(createSelectionPanel(), BorderLayout.AFTER_LINE_ENDS);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    private JPanel createTablePanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
        table = new JTable(tableModel);
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        table.getColumnModel().getColumn(0).setPreferredWidth(100);
        table.getColumnModel().getColumn(1).setPreferredWidth(150);
        table.getColumnModel().getColumn(2).setPreferredWidth(150);
        table.getColumnModel().getColumn(3).setPreferredWidth(100);
        table.getColumnModel().getColumn(4).setPreferredWidth(100);
        JScrollPane scrollPane = new JScrollPane(table);
        scrollPane.setPreferredSize(new Dimension(620, 300));
        panel.add(scrollPane, BorderLayout.CENTER);
        
        return panel;
    }
    
    private JPanel createSelectionPanel() {
        JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
        JPanel innerPanel = new JPanel(new GridLayout(0, 1, 5, 5));
        
        ColumnListener listener = new ColumnListener(this);
        String[] columns = inventory.getTableHeader();
        for (String column : columns) {
            JCheckBox checkBox = new JCheckBox("Display " +  column);
            checkBox.addActionListener(listener);
            checkBox.setActionCommand(column);
            checkBox.setSelected(true);
            innerPanel.add(checkBox);
        }
        
        panel.add(innerPanel);
        
        return panel;
    }
    
    public JTable getTable() {
        return table;
    }
    
    public JFrame getFrame() {
        return frame;
    }
    
    public class ColumnListener implements ActionListener {
        
        private final JCheckBoxTableGUI frame;
        
        private final List<DisplayTableColumn> displayColumns;

        public ColumnListener(JCheckBoxTableGUI frame) {
            this.frame = frame;
            this.displayColumns = new ArrayList<>();
            
            TableColumnModel tcm = frame.getTable().getColumnModel();
            for (int index = 0; index < tcm.getColumnCount(); index++) {
                TableColumn tc = tcm.getColumn(index);
                displayColumns.add(new DisplayTableColumn(tc, true));
            }
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            JCheckBox checkBox =  (JCheckBox) event.getSource();
            String column = event.getActionCommand();
            TableColumnModel tcm = frame.getTable().getColumnModel();
            
            for (int index = 0; index < displayColumns.size(); index++) {
                DisplayTableColumn dtc = displayColumns.get(index);
                if (dtc.isShowTableColumn()) {
                    tcm.removeColumn(dtc.getTableColumn());
                }
            }
            
            int columnIndex = getColumnIndex(column);
            displayColumns.get(columnIndex).setShowTableColumn(
                    checkBox.isSelected());
            
            for (int index = 0; index < displayColumns.size(); index++) {
                DisplayTableColumn dtc = displayColumns.get(index);
                if (dtc.isShowTableColumn()) {
                    tcm.addColumn(dtc.getTableColumn());
                }
            }
            
            frame.getFrame().pack();
        }
        
        private int getColumnIndex(String column) {
            for (int index = 0; index < displayColumns.size(); index++) {
                DisplayTableColumn dtc = displayColumns.get(index);
                if (column.equals(dtc.getTableColumn().getHeaderValue())) {
                    return index;
                }
            }
            
            return -1;
        }
        
    }
    
    public class DisplayTableColumn {
        
        private boolean showTableColumn;
        
        private final TableColumn tableColumn;

        public DisplayTableColumn(TableColumn tableColumn, boolean showTableColumn) {
            this.tableColumn = tableColumn;
            this.showTableColumn = showTableColumn;
        }

        public boolean isShowTableColumn() {
            return showTableColumn;
        }

        public void setShowTableColumn(boolean showTableColumn) {
            this.showTableColumn = showTableColumn;
        }

        public TableColumn getTableColumn() {
            return tableColumn;
        }
        
    }
    
    public class InventoryTableModel extends DefaultTableModel {

        private static final long serialVersionUID = 1L;

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            if (columnIndex <= 2) {
                return String.class;
            } else if (columnIndex == 3) {
                return Integer.class;
            } else {
                return Integer.class;
            }
        }

    }
    
    public class Inventory {
        
        private final List<Item> inventory;
        
        private final String[] tableHeader;
        
        public Inventory() {
            this.tableHeader = new String[] { "Item Number", "Item Name", 
                    "Item Description", "Item Quantity",
                    "Item Price" };
            
            this.inventory = new ArrayList<>();
            
            inventory.add(new Item("X101111", "Samsung Camera", " ", 20, 69.99));
            inventory.add(new Item("X101112", "Samsung Monitor", " ", 10, 279.99));
            inventory.add(new Item("X101113", "Samsung Smartphone", " ", 110, 599.99));
            inventory.add(new Item("X101114", "Apple Watch", " ", 20, 1259.99));
            inventory.add(new Item("X101115", "Sony Playstation 5", " ", 0, 399.99));
        }

        public String[] getTableHeader() {
            return tableHeader;
        }

        public List<Item> getInventory() {
            return inventory;
        }
        
    }
    
    public class Item {
        
        private int itemPrice;
        private int itemQuantity;
        
        private final String itemNumber;
        private final String itemName;
        private final String itemDescription;
        
        public Item(String itemNumber, String itemName, 
                String itemDescription, int itemQuantity, double itemPrice) {
            this.itemNumber = itemNumber;
            this.itemName = itemName;
            this.itemDescription = itemDescription;
            this.itemQuantity = itemQuantity;
            setItemPrice(itemPrice);
        }

        public int getItemPrice() {
            return itemPrice;
        }

        public void setItemPrice(double itemPrice) {
            this.itemPrice = (int) Math.round(itemPrice * 100.0);
        }

        public int getItemQuantity() {
            return itemQuantity;
        }

        public void setItemQuantity(int itemQuantity) {
            this.itemQuantity = itemQuantity;
        }

        public String getItemNumber() {
            return itemNumber;
        }

        public String getItemName() {
            return itemName;
        }

        public String getItemDescription() {
            return itemDescription;
        }
        
    }

}

這僅演示了如何創建一個基本的 MRE:

  1. csv 文件無關緊要。
  2. model 中的數據無關緊要。
  3. 您的 loadFile、newFile 和 saveFile 按鈕無關緊要。
  4. TableModel 無關緊要

您的問題是關於將 ActionListener 添加到基於表的列動態創建的復選框中。

因此,您所需要的只是一個包含一些列和生成的復選框的表格。

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() );
    }
}

如果您可以修改它以演示如何使用“可重用類”來管理列可見性,那么我將更新上面的代碼以使用我的可重用 class 和另外 4 行代碼。

編輯:

對代碼的建議改進:

  1. 使代碼可重用和自包含
  2. 不要使用 static 方法
  3. 不要更改數據。

你原來的問題是:

How do I add an ActionListener to a JCheckBox?

所以要做到這一點,你需要一個 class :

  1. 實現一個ActionListener
  2. 是自包含的以實現您需要的功能。

所以基本結構可能如下所示:

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() );
    }
}

無論您的 function 做什么,它只需要知道它應該操作的表。

因此,嘗試將您的代碼重組為可重用的 class。

如果要使用 Gilberts 代碼,則需要將ColumnListener class 重組為單獨的可重用自包含 class。

最后你也可以試試我的可重復使用的 class。 查看 class 的表格列管理器以進行下載。

無論您決定使用什么可重用 class,您只需更改上述示例中的一行代碼(一旦您的功能包含在可重用類中)。

請注意 static 方法不會成為最終 class 的一部分。 它們只是為了簡化在單個 class 文件中測試和發布 MRE。

希望這有助於未來的設計考慮。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM