单击 JButton 时不会填充 JTable

Posted

技术标签:

【中文标题】单击 JButton 时不会填充 JTable【英文标题】:JTable Won't populate when clicking JButton 【发布时间】:2017-03-28 18:08:13 【问题描述】:

我正在开发的系统是一个收银系统,JTable 充当orderList。我试过Vector,也试过使用DefaultTableModel,但我不确定如何让按钮拉出数据并将其添加到表格中。我知道这很难理解,但谁能告诉我我应该如何为一个 JButton 做这件事,然后其余的应该是相似的,我可以自己做吗?

我需要从数据库中提取productIDproductNamePrice 并添加到表中。

然后我将合计价格并为订单付款。

Order

//Order class for setting up and managing an order

package classes;

import java.sql.*;
import java.util.ArrayList;
import java.util.Vector;

public class Order 

    // Instance Variables
        private int productID;
        private String productName;
        private String productDescription;
        private String type;
        private String supplierName;
        private double quantity;
        private double price;
    
    // Connection To DB
    // JDBC Driver name and database URL
        final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
        final String DB_URL = "jdbc:mysql://localhost/team_project?useSSL=false";
        final String USER_NAME = "root";
        final String PASSWORD = "password";
        
        // sql variables
        ResultSet resultSet = null;
        private String itemName;
        private double itemPrice;
    
    // Constructors
    public Order()
    
        
    
    
    public Order(int productID, String itemName, double itemPrice, double quantity)
    
        this.itemName = itemName;
        this.itemPrice = itemPrice;
        this.quantity = quantity;
    
    
    
    // Get the details of stock items and add them to the order
    public Vector getOrderItems()
    
         ResultSet rs = null;
        
        Statement statement = null;
        try

            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
            Statement stmt = conn.createStatement();
            String sqlString= "select ProductID, ProductName, Price from product";
            stmt.executeUpdate(sqlString);  
            Vector vector = new Vector();
            Vector<String> orderItem = new Vector<String>();
            int i=0;
            while(rs.next())
             
                Vector<String> items = new Vector<String>();
                rs.getInt("ProductID");
                rs.getString("ProductName");
                rs.getDouble("Price");
            
            return vector;
            catch(Exception e)
            
                e.printStackTrace();
            
        return null;    
    
        
            
         // Getter Methods
            public int getProductID()
            
                return productID;
            
            
            public String getProductName()                                  
            
                return productName;
            
            
            public String getProductDesc()
            
                return productDescription;
            
            
            public String getType()
            
                return type;
            
            
            public String getSupplierName()
            
                return supplierName;
            
            
            public double getQuantity()
            
                return quantity;
            
            
            public double getPrice()
            
                return price;
            
        

Stock

// Stock class
//Team Project
//Stock class for setting up and managing stock

package classes;

import java.sql.*;
import java.util.*;

public class Stock 

    // Instance Variables
    private int productID;
    private String productName;
    private String productDescription;
    private String type;
    private String supplierName;
    private double quantity;
    private double price;



    
    // JDBC Driver name and database URL
    final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
    final String DB_URL = "jdbc:mysql://localhost/team_project?useSSL=false";
    final String USER_NAME = "root";
    final String PASSWORD = "password";

    
    // sql variables
    Statement statement = null;
    ResultSet resultSet = null;
    
    public Stock()
    
        productID=0;
        productName=null;
        productDescription = null;
        type = null;
        supplierName=null;      
        quantity = 0;
        price=0;
    
    
    // Initialisation Constructor that initializes everything in DB
    public Stock(int productID, String productName, String productDescription, String type, String supplierName,
                double quantity, double price)
    
        this.productID = productID;
        this.productName = productName;
        this.productDescription = productDescription;
        this.type = type;
        this.supplierName = supplierName;
        this.quantity = quantity;
        this.price = price;
    
    
    
    
    // Add a new product into the product table
    public void addProduct(int prodID, int amt) 
    
        try
        
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
            
            Statement stmt = conn.createStatement();
            String sqlString="insert into product " + "(ProductID, ProductName, ProductDescrp, type, SupplierName, Quantity, Price)"
            + " values(30, 'Marmalade', 'Homestead', 'Extras', 'Bakersworld', 20, 0.20)";
            stmt.executeUpdate(sqlString);
            conn.close();
        
        catch(Exception e)
        
            e.printStackTrace();
        
    
    
    // Delete a product from the product table
    public void delete(int prodNumIn)
    
        try
        
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
            
            Statement stmt = conn.createStatement();
            String sqlString= "delete from team_Project.product where ProductID=" + prodNumIn;
            stmt.executeUpdate(sqlString);  
        
        catch(Exception e)
        
            e.printStackTrace();
        
    
        
    // Subtracts quantity in stock in the DB When a sale is made on an item
    public int deductStock(int prodID) 
    
        int status =0;
          String sql = ("UPDATE product " + "SET Quantity = " + (getDBQuantity(prodID)-1) + " WHERE ProductID = " + prodID);
          status = databaseUpdate(sql);
          return status;
    
    
    // Add quantity to particular product in the DB if required
    public int addToQuantity(int prodID, int amt) 
    
        int status =0;
        String sql = ("UPDATE product " + "SET Quantity = " + (getDBQuantity(prodID)+ amt) + " WHERE ProductID = " + prodID);
        status = databaseUpdate(sql);
        return status;
        
    
        
    // return quantity of a product in DB
    public int getDBQuantity(int prodID)
    
        int quantity=0;
        try
        
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
        
        statement = (Statement) conn.createStatement();
        resultSet = statement.executeQuery("select Quantity from team_project.product WHERE ProductID = " + prodID);

        while (resultSet.next())
               
            quantity = (resultSet.getInt("Quantity"));
        
        conn.close();
        catch(Exception e)
        
            e.printStackTrace();
        
        return quantity;
        
    
    
    // get price of a particular product 
    public int getItemPrice(int prodID)
    
        int price = 0;      
        
        try
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
            
            statement = (Statement) conn.createStatement();
            resultSet = statement.executeQuery("select Price from team_project.product WHERE ProductID = " + prodID);
           
        while (resultSet.next())
               
            price = (resultSet.getInt("Price"));
        
        conn.close();
        
        catch(Exception e)
        
            e.printStackTrace();
        
        System.out.println("€"+price);
        return price;
        

    
    
    // Method that returns all products in product table
    public ArrayList<Stock> getProducts()
    
        ArrayList<Stock> allStock = new ArrayList<Stock>();
        
    try
    
    Class.forName("com.mysql.jdbc.Driver");
    Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
    
    statement = (Statement) conn.createStatement();
    resultSet = statement.executeQuery("select * from team_project.product");

    while (resultSet.next())
           
        Stock  stock = new Stock(resultSet.getInt("ProductID"), resultSet.getString("ProductName"), 
                resultSet.getString("ProductDescrp"),resultSet.getString("Type"),resultSet.getString("SupplierName"), 
                resultSet.getInt("Quantity"), resultSet.getDouble("Price"));
        allStock.add(stock);
    
    conn.close();

    catch(Exception e)
    
        e.printStackTrace();
    
    return allStock;
    
    
    // update method to call
    // database update method 
         private int databaseUpdate(String sqlUpdate)
         
              int status = 0;
           
              try
                 Class.forName("com.mysql.jdbc.Driver");
                 Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
                 statement = conn.createStatement();
                 status = statement.executeUpdate(sqlUpdate);
                 conn.close(); 
                     
               
              catch (Exception e) 
                 e.printStackTrace();
                 
              return status;
           
         
         // toString method for stock items
         public String toString()
         
             return productName + "";
         
        
    

    // Getter Methods
    public int getProductID()
    
        return productID;
    
    
    public String getProductName()                                  
    
        return productName;
    
    
    public String getProductDesc()
    
        return productDescription;
    
    
    public String getType()
    
        return type;
    
    
    public String getSupplierName()
    
        return supplierName;
    
    
    public double getQuantity()
    
        return quantity;
    
    
    public double getPrice()
    
        return price;
    

    

// 小美式监听器

americanoSmall.addActionListener(
        new ActionListener()
        
            public void actionPerformed(ActionEvent e)
            
                try 
                    String query = "select ProductName, Price from product where ProductID = 24";
                    java.sql.PreparedStatement pst = connection.prepareStatement(query);
                    ResultSet rs = pst.executeQuery();
                    table.setModel(DbUtils.resultSetToTableModel(rs));
                
                     catch (Exception e1) 
                    
                        e1.printStackTrace();
                    
                
            );    
   
    
   
    

【问题讨论】:

那么您是否收到此代码的任何错误?或者你真正的问题是什么? 没有错误,我只是想知道我做错了什么,因为它什么也没做。有什么我想念的吗? 【参考方案1】:

您的代码有点倾斜,您有一个 Stock 对象,但该对象似乎也在管理数据库,作为更长期的解决方案,我建议将这些问题分开,但现在我们将离开暂时是这样。

我要做的第一件事是定义模型的期望,你期望它做什么,你期望它如何工作

public interface MutableStockModel 
    public void add(Stock item) throws ModelException;
    public void remove(Stock item) throws ModelException;

所以这是一个简单的接口,它定义了任何实现类都应该提供的几个动作。但你为什么要问?这是一个很好的问题,我很快就会回答。

您可以从TableModel 扩展MutableStockModel,但这会将您锁定在可能无法满足您的长期需求的特定实施渠道中,此外,使用它的人关心什么,他们只是希望能够添加和删​​除产品

一个示例实现...

public class DefaultStockTableModel extends AbstractTableModel implements MutableStockModel 

    private List<Stock> items;

    public DefaultStockTableModel() 
        items = new ArrayList<>(25);
    

    public DefaultStockTableModel(List<Stock> items) 
        this.items = items;
    

    @Override
    public int getRowCount() 
        return items.size();
    

    @Override
    public int getColumnCount() 
        return 7;
    

    @Override
    public Class<?> getColumnClass(int columnIndex) 
        switch (columnIndex) 
            case 1:
            case 2:
            case 3:
            case 4: return String.class;
            case 0:
            case 5:
            case 7: return int.class;
        
        return Object.class;
    

    @Override
    public String getColumnName(int column) 
        switch (column) 
            case 0: return "ID";
            case 1: return "Name";
            case 2: return "Description";
            case 3: return "Type";
            case 4: return "Supplier Name";
            case 5: return "Quanity";
            case 6: return "Price";
        
        return null;
    

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) 
        Stock item = items.get(rowIndex);
        switch (columnIndex) 
            case 0: return item.getProductID();
            case 1: return item.getProductName();
            case 2: return item.getProductDesc();
            case 3: return item.getType();
            case 4: return item.getSupplierName();
            case 5: return item.getQuantity();
            case 6: return item.getPrice();
        
        return null;
    

    @Override
    public void add(Stock item) throws ModelException 
        // Add the item to the database if required
        items.add(item);
        int row = items.indexOf(item);
        fireTableRowsInserted(row, row);
    

    @Override
    public void remove(Stock item) throws ModelException 
        if (items.contains(item)) 
            // Delete theitem from the database if required
            int row = items.indexOf(item);
            items.remove(row);
            fireTableRowsDeleted(row, row);
        
    


所以这是一个基本示例,您的任何代码都不关心它的实际管理方式,只关心它是否符合合同要求。

要添加或删除产品,只需调用特定方法即可。

现在,您可以扩展此概念以使其更易于使用,例如...

public interface MutableStockTableModel extends MutableStockModel, TableModel 
    public void removeAt(int row) throws ModelException;

这是一个特定的、有针对性的实现,它允许您在特定行中删除一行。这扩展了TableModel,因为TableModel 具有“行”的概念,而MutableStockModel 没有。当然,您必须更新任何实现 implement 这个特定的 interface ;)

好的,但是“为什么”?

简短的回答是,根据数据库,ResultSet 实际上可以直接进行变异,也就是说,您可以通过ResultSet 直接添加/插入、删除和更新行,有关更多详细信息,请参阅Retrieving and Modifying Values from Result Sets .

这意味着您可以创建一个TableModel 的实现,它实现了MutableStockTableModelMutableStockModel 接口,但它引用了原始ResultSet 作为其内部结构。

听起来很简单,但是当您意识到您可以更改 TableModel 的任何实例来满足实现要求而不影响您的任何代码的任何实现时,它就会带来很多可能性。

因此,例如,您可以使用

private MutableStockTableModel tableModel;

//...

tableModel = new ResultSetMutableStockTableModel(resultSet);
table.setModel(tableModel);

//...

tableModel.add(stockItem);

但您可以简单地将 tableModel 更改为不同的实例...

tableModel = new DefaultStockTableModel(listOfItems);

没有什么需要改变的!

所以,这是“编码到接口,而不是实现”的基本示例,我可以进一步解耦代码,但我不想让你不知所措;)​​p>

回到我的第一条评论,OO 提倡Single Responsibility Principle,这意味着任何对象都应该有一个单一的职责(或工作)。

这可能表明,例如,您应该分离 Stock 类的功能。

我的,我会从一个 interface 开始,令人惊讶的是...

public interface Stock 
    public int getProductID();
    public String getProductName();
    public String getProductDesc();
    public String getType();
    public String getSupplierName();
    public double getQuantity();
    public double getPrice();

然后你会有某种实现......

public class DefaultStock implements Stock 
    // Instance Variables

    private int productID;
    private String productName;
    private String productDescription;
    private String type;
    private String supplierName;
    private double quantity;
    private double price;

    public DefaultStock() 
        productID = 0;
        productName = null;
        productDescription = null;
        type = null;
        supplierName = null;
        quantity = 0;
        price = 0;
    

    // Initialisation Constructor that initializes everything in DB
    public DefaultStock(int productID, String productName, String productDescription, String type, String supplierName,
                             double quantity, double price) 
        this.productID = productID;
        this.productName = productName;
        this.productDescription = productDescription;
        this.type = type;
        this.supplierName = supplierName;
        this.quantity = quantity;
        this.price = price;
    

    // toString method for stock items
    @Override
    public String toString() 
        return productName + "";
    

    // Getter Methods
    @Override
    public int getProductID() 
        return productID;
    

    @Override
    public String getProductName() 
        return productName;
    

    @Override
    public String getProductDesc() 
        return productDescription;
    

    @Override
    public String getType() 
        return type;
    

    @Override
    public String getSupplierName() 
        return supplierName;
    

    @Override
    public double getQuantity() 
        return quantity;
    

    @Override
    public double getPrice() 
        return price;
    

然后你可能会有某种经理/控制器/工厂...

(是的,我很想通过某种界面来描述这一点,但这已经是一篇很长的帖子了)

public class StockManager 

    // JDBC Driver name and database URL
    final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
    final String DB_URL = "jdbc:mysql://localhost/team_project?useSSL=false";
    final String USER_NAME = "root";
    final String PASSWORD = "password";

    // sql variables
    Statement statement = null;
    ResultSet resultSet = null;

    // Add a new product into the product table
    public void addProduct(int prodID, int amt) 
        try 
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);

            Statement stmt = conn.createStatement();
            String sqlString = "insert into product " + "(ProductID, ProductName, ProductDescrp, type, SupplierName, Quantity, Price)"
                    + " values(30, 'Marmalade', 'Homestead', 'Extras', 'Bakersworld', 20, 0.20)";
            stmt.executeUpdate(sqlString);
            conn.close();
         catch (Exception e) 
            e.printStackTrace();
        
    

    // Delete a product from the product table
    public void delete(int prodNumIn) 
        try 
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);

            Statement stmt = conn.createStatement();
            String sqlString = "delete from team_Project.product where ProductID=" + prodNumIn;
            stmt.executeUpdate(sqlString);
         catch (Exception e) 
            e.printStackTrace();
        
    

    // Subtracts quantity in stock in the DB When a sale is made on an item
    public int deductStock(int prodID) 
        int status = 0;
        String sql = ("UPDATE product " + "SET Quantity = " + (getDBQuantity(prodID) - 1) + " WHERE ProductID = " + prodID);
        status = databaseUpdate(sql);
        return status;
    

    // Add quantity to particular product in the DB if required
    public int addToQuantity(int prodID, int amt) 
        int status = 0;
        String sql = ("UPDATE product " + "SET Quantity = " + (getDBQuantity(prodID) + amt) + " WHERE ProductID = " + prodID);
        status = databaseUpdate(sql);
        return status;

    

    // return quantity of a product in DB
    public int getDBQuantity(int prodID) 
        int quantity = 0;
        try 
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);

            statement = (Statement) conn.createStatement();
            resultSet = statement.executeQuery("select Quantity from team_project.product WHERE ProductID = " + prodID);

            while (resultSet.next()) 
                quantity = (resultSet.getInt("Quantity"));
            
            conn.close();
         catch (Exception e) 
            e.printStackTrace();
        
        return quantity;
    

    // get price of a particular product 
    public int getItemPrice(int prodID) 
        int price = 0;

        try 
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);

            statement = (Statement) conn.createStatement();
            resultSet = statement.executeQuery("select Price from team_project.product WHERE ProductID = " + prodID);

            while (resultSet.next()) 
                price = (resultSet.getInt("Price"));
            
            conn.close();
         catch (Exception e) 
            e.printStackTrace();
        
        System.out.println("€" + price);
        return price;
    

    // Method that returns all products in product table
    public ArrayList<Stock> getProducts() 
        ArrayList<Stock> allStock = new ArrayList<Stock>();

        try 
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);

            statement = (Statement) conn.createStatement();
            resultSet = statement.executeQuery("select * from team_project.product");

            while (resultSet.next()) 
                Stock stock = new DefaultStock(resultSet.getInt("ProductID"), resultSet.getString("ProductName"),
                                                                resultSet.getString("ProductDescrp"), resultSet.getString("Type"), resultSet.getString("SupplierName"),
                                                                resultSet.getInt("Quantity"), resultSet.getDouble("Price"));
                allStock.add(stock);
            
            conn.close();

         catch (Exception e) 
            e.printStackTrace();
        
        return allStock;
    

    // update method to call
    // database update method 
    private int databaseUpdate(String sqlUpdate) 
        int status = 0;

        try 
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
            statement = conn.createStatement();
            status = statement.executeUpdate(sqlUpdate);
            conn.close();
         catch (Exception e) 
            e.printStackTrace();
        
        return status;
    


我还鼓励您查看Using Prepared Statements 以改进整体代码

【讨论】:

你的解决方案是完美的,它涵盖了所有问题,加 1 ;)【参考方案2】:

第一部分

首先:当你想使用 SELECT 时,你必须使用 stmt.executeQuery(sqlString);stmt.execute(sqlString); 而不是 executeUpdate 当你想要进行插入更新或删除时使用它: p>

stmt.executeQuery(sqlString);

第二:我认为您的 URL 中缺少某些内容,您缺少端口号:

"jdbc:mysql://localhost/team_project?useSSL=false";
//---------------------^--------------------------

应该是这样的,MySQL的默认端口是3306

"jdbc:mysql://localhost:3306/team_project?useSSL=false";

注意使用语句不安全,可能会导致语法错误或SQL注入,我建议使用PreparedStatement,它更安全,更有用

第二部分

为了填充您的 JTable,我通常使用这种方式:

//call this method to fill your Object in your JTable when you click to your button
private void fillData(List<MY_OBJECT> list) //method which take a list of objects 

    DefaultTableModel model = (DefaultTableModel) jTableName.getModel();

    // empty your JTable
    model.setRowCount(0);

    //Fill your JTbale
    for (MY_OBJECT obj : list) 
        model.addRow(new Object[]
            obj.getAttribute1(),
            obj.getAttribute2,
            obj.getAttribute3
        );
    

【讨论】:

好的,我会做出建议的更改,并告诉你它是如何工作的。 java.sql.SQLException:连接属性“useSSL”仅接受以下形式的值:“true”、“false”、“yes”或“no”。值'假;'不在这个集合中.. 从您的 URL @Movillian 中删除 ?useSSL=false 好的,连接错误已修复。谢谢 不,现在连接正常。谢谢你。我只是想试试下面@Timothy Truckle 的例子,看看我是否可以在我的系统中实现它。【参考方案3】:

这里是Minimal, Complete, and Verifiable example (MCVE)如何填充表格:

public class TableAddRowButton 

    public static class Order 
        static int idCounter = 0;
        private int productID = ++idCounter;
        private String productName = "Product" + productID;
        private double quantity = new Random().nextInt(1000);
        private double price = new Random().nextInt(1000);
    

    public static void main(String[] args) 
        Vector<Order> orders = new Vector<>();
        DefaultTableModel tableModel = createTableModel(orders);
        JButton button = createAddRowButton(orders, tableModel);
        JPanel panel = new JPanel(new BorderLayout());
        panel.add(button, BorderLayout.NORTH);
        panel.add(new JScrollPane(new JTable(tableModel)));
        JOptionPane.showMessageDialog(null, panel);

    

    private static JButton createAddRowButton(Vector<Order> orders, DefaultTableModel tableModel) 
        JButton button = new JButton(new AbstractAction("add row") 
            @Override
            public void actionPerformed(ActionEvent arg0) 
                orders.add(new Order());
                tableModel.fireTableRowsInserted(orders.size() - 2, orders.size() - 1);
            
        );
        return button;
    

    private static DefaultTableModel createTableModel(Vector<Order> orders) 
        DefaultTableModel tableModel = new DefaultTableModel(
                new Vector<>(Arrays.asList("ID", "Name", "quantity", "price")), orders.size()) 

            @Override
            public int getRowCount() 
                return orders.size();
            

            @Override
            public Object getValueAt(int row, int column) 
                switch (column) 
                case 0:
                    return orders.get(row).productID;
                case 1:
                    return orders.get(row).productName;
                case 2:
                    return orders.get(row).quantity;
                case 3:
                    return orders.get(row).price;
                default:
                    return "";
                
            

            @Override
            public boolean isCellEditable(int row, int column) 
                return false;
            
        ;
        return tableModel;
    

【讨论】:

(1-) 数据更新应该通过 TableModel 完成,而不是 Vector。所以你需要添加一个像 addOrder(...) 这样的方法。然后由模型负责调用 fireTableRowsInserted(...) 方法。 “数据的更新应该通过 TableModel 完成”您能否发布您自己的答案,表明您的方法是:更短且更具可读性? 这不是关于更短或可读性,而是关于遵循 MVC 设计原则。 “它关于遵循 MVC 设计原则” 那么模式必须在过去 15 年内发生变化仅对象... 那么我现在如何将这个概念应用到我自己的问题中呢?记住我不能使用 Random,我需要尝试从数据库中提取所有需要的数据并添加到 JTable 中跨度>

以上是关于单击 JButton 时不会填充 JTable的主要内容,如果未能解决你的问题,请参考以下文章

单击JButton时如何删除JTable中的当前行?

Java Swing 在单击我要删除的 jpanel 中存在的 Jbutton 时删除 Jpanel

更改可见性时,JButton 大小设置为默认大小

ActionListener添加到JButton但不起作用

JButton 在其边框和按钮本身之间有填充

如何通过单击 JButton 添加 JPanel?