![](/img/trans.png)
[英]How do I add a JCheckBox to DefaultTableModel by adding a Boolean column?
[英]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。 這是開始的顯示。
這是我刪除項目描述后的 GUI。
這是我刪除商品價格后的 GUI。
這是我添加列后的 GUI。
我創建了一個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:
您的問題是關於將 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 行代碼。
編輯:
對代碼的建議改進:
你原來的問題是:
How do I add an ActionListener to a JCheckBox?
所以要做到這一點,你需要一個 class :
ActionListener
所以基本結構可能如下所示:
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.