在 JTextField 的一个框架/类/窗口中输入数字并在另一个 JLabel 中显示它 型号查看控制器

问题描述

我目前正在开发自己的 Java 小项目,以学习和更好地理解面向对象编程。 这是一个银行应用程序,可让您存取款并查看余额,但我认为我的代码到处都是。

我无法将 TextField 的值从一帧获取到另一帧中的 Label。我什至如何将两个 JFrame 链接在一起?

这是平衡课:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Balance implements ActionListener {






    JFrame balanceFrame = new JFrame("Balance");
    JPanel balancePanel = new JPanel();
    JLabel balanceLabel = new JLabel("Balance:");
    JLabel refreshBalanceLabel = new JLabel();
    JButton exitBalanceButton = new JButton("EXIT");
    JButton backToMenuButton = new JButton("MENU");
    JButton refreshButton = new JButton("REFRESH");



    public void balance(){

        balanceFrame.setSize(420,400);
        balanceFrame.add(balancePanel);
        balancePanel.setLayout(null);
        balanceFrame.setVisible(true);
        balanceFrame.setDefaultCloSEOperation(balanceFrame.EXIT_ON_CLOSE);


        balanceLabel.setFont(new Font("Segoe UI",Font.PLAIN,14));
        balanceLabel.setBounds(10,50,80,25);
        balancePanel.add(balanceLabel);

        refreshBalanceLabel.setFont(new Font("Segoe UI",14));
        refreshBalanceLabel.setBounds(80,25);
        balancePanel.add(refreshBalanceLabel);


        refreshButton.setBounds(100,220,100,25);
        refreshButton.setFocusPainted(false);
        balancePanel.add(refreshButton);
        refreshButton.addActionListener(this);


        exitBalanceButton.setBounds(100,160,25);
        exitBalanceButton.setFocusPainted(false);
        balancePanel.add(exitBalanceButton);


        backToMenuButton.setBounds(240,25);
        backToMenuButton.setFocusPainted(false);
        balancePanel.add(backToMenuButton);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Deposit depositObj = new Deposit();
        refreshBalanceLabel.setText(depositObj.newBalanceAmount);

    }

}

这是存款类:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Deposit implements ActionListener {

    String newBalanceAmount;


    JFrame depositFrame = new JFrame("Deposit");
    JPanel depositPanel = new JPanel();
    JLabel amount = new JLabel("Amount:");
    JTextField amountTextField = new JTextField();
    JButton depositAmountButton = new JButton("DEPOSIT");



    public void depositing() {





        depositFrame.setSize(420,400);
        depositFrame.add(depositPanel);
        depositPanel.setLayout(null);
        depositFrame.setVisible(true);
        depositFrame.setDefaultCloSEOperation(depositFrame.EXIT_ON_CLOSE);


        amount.setFont(new Font("Segoe UI",14));
        amount.setBounds(10,25);
        depositPanel.add(amount);


        amountTextField.setBounds(100,165,25);
        depositPanel.add(amountTextField);


        depositAmountButton.setBounds(130,25);
        depositAmountButton.setFocusPainted(false);
        depositPanel.add(depositAmountButton);
        depositAmountButton.addActionListener(this);

    }


    @Override
    public void actionPerformed(ActionEvent e) {
        String newBalanceAmount = amountTextField.getText();
        Balance newBalance = new Balance();
        amountTextField.setText(newBalanceAmount);




    }

}

还有其他类和框架,但它们现在与我的问题无关。

这里的大部分代码是我的,有些来自互联网,所以它们都挤在一起,它不起作用,我被卡住了。

我了解 Java 的基础知识,目前在 OOP 方面做得很好,但我还不明白这一点。

如何将TextField(amountTextField) 的输入从Deposit 类复制到Balance 类中的(refreshBalanceLabel) 中?

另外,我的代码有什么问题,我该如何整体改进?

解决方法

简介

让我们看看。我将您的 Deposit 类复制到我的 GUI 中。它不会编译。我修复了编译错误并添加了一个静态 main 方法,这样我就可以运行它并查看您的 GUI 是什么样的。这是一团糟。你为什么把 GUI 设为固定大小?为什么对 Swing 组件使用绝对定位。究竟为什么存款需要三个按钮?

这是您创建单个 JFrame GUI 的一种方法,该 GUI 结合了存款功能和取款功能。

Checkbook GUI

当您创建 Swing GUI 时,您应该尝试使其尽可能小。如果用户希望它更大,可以拉伸 JFrame

为了创建这样的 GUI,您必须了解如何布局 Swing GUI。因为这个 GUI 看起来像一个表单,所以我使用了 GridBagLayout 来构建这个 GUI。我没有使用绝对定位。

我创建了一个应用程序模型,用于保存帐户信息和交易信息。 Account 类包含姓名、帐号和余额。 Transaction 类包含支票号码(可选)、日期、收款人和金额。

一旦我有了应用程序模型,组成 GUI 的 Swing 组件就很简单了。我用一个 JPanel 来保存所有这些组件。我将组件一一添加到我的 JPanel 中,添加每个组件后运行测试。并非每次测试都成功。由于我一次只添加一个组件,所以我大致知道错误在哪里。

正如我在评论中所说,请阅读 Oracle 教程,Creating a GUI With JFC/Swing。跳过 Netbeans 部分。了解如何构建合适的 Swing GUI。

编辑添加

我创建了一个有点完整的支票簿 GUI。左边的 JTable 包含所有交易的寄存器。右边是控件 JPanel,它允许我添加事务。

Checkbook GUI 2

我没有做任何错误检查。日期必须以 M/d/yy 格式输入。

如您所见,每次输入存款或取款交易后,余额都会更新。

GUI 相当宽,为 1309 x 525 像素。也许收银机应该显示在 JDialog 中,但我喜欢看到交易出现在 JTable 中的即时反馈。

说明

当我创建 Swing GUI 时,我使用 model / view / controller (MVC) 模式。这种模式使我能够将我的关注点分开,并一次专注于应用程序的一个部分。

我创建了 3 个模型类、一个视图类和 4 个控制器类。两个控制器类处理 JTable 显示,另外两个控制器类是 ActionListener 类用于存款和取款 JButtons

型号

Checkbook 类是主要的纯 Java getter/setter 类,它包含 Account 的实例和 java.util.List 实例的 Transaction

Account 类是一个普通的 Java getter/setter 类,它包含帐户名称、帐号和帐户余额。帐户余额是一个存放便士的 int 字段。这样可以确保添加存款和扣除取款不会导致任何浮点舍入错误。

Transaction 类是一个普通的 Java getter/setter 类,其中包含支票号码、交易日期、收款人、描述和金额。由于我们不对交易进行任何算术运算,因此金额以双精度形式存储。

我希望你注意到这里的一个趋势。所有应用程序模型类都是普通的 Java getter/setter 类。该视图将处理 Swing 组件。

查看

视图由一个 JFrame、一个表 JPanel 和一个控件 JPanel 组成。 JFrame 有一个默认值 BorderLayout,因此我将表 JPanel 放在中心,将控件 JPanel 放在右侧。如果您展开 JFrame,所有额外的空间都会转到表 JPanel

JPanel 包含一个 JScrollPane,它包含一个 JTable。表 JPanel 使用 BorderLayout。我为 JTable 创建了一个表格模型和一个单元格渲染器。这些类改进了 JTable 的视觉外观,并允许我按底层类对表列进行排序。例如,金额列是 Double 值,但显示为逗号分隔的 String 值。

控件 JPanel 包含存款和取款交易的所有输入字段。我使用 GridBagLayout 放置 Swing 组件。这个 JPanel 上有很多 Swing 组件。也许,我应该让控件 JPanel 成为一个单独的类。

控制器

我不打算讨论 JTable 控制器。这个答案已经很长了。

我创建了两个单独的 ActionListener 类,一个用于存款,一个用于取款。我没有做任何错误检查。通过编写单独的 ActionListener 类,每个类都保持简单明了。

结语

我花了几个小时来创建这个 GUI。我一次编码一小块,并多次测试每个小块。在编写此答案时,我发现代码中有几个错误。

这是完整的可运行代码。我把所有的类都放在了内部类中,所以我可以把它作为一个块发布。复制代码并在您的 IDE 中运行它以查看它是如何工作的。

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;

public class CheckbookGUI implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new CheckbookGUI());
    }
    
    private final Checkbook checkbook;
    
    private CheckbookTableModel tableModel;
    
    private JFrame frame;
    
    private JTable transactionTable;
    
    private JTextField balanceField;
    private JTextField depositDateField;
    private JTextField depositAmountField;
    private JTextField withdrawalCheckNumberField;
    private JTextField withdrawalDateField;
    private JTextField withdrawalPayeeField;
    private JTextField withdrawalDescriptionField;
    private JTextField withdrawalAmountField;
    
    public CheckbookGUI() {
        this.checkbook = new Checkbook();
    }

    @Override
    public void run() {
        frame = new JFrame("Checkbook GUI");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.add(createTablePanel(),BorderLayout.CENTER);
        frame.add(createTransactionPanel(),BorderLayout.AFTER_LINE_ENDS);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
        
        System.out.println(frame.getSize());
    }
    
    private JPanel createTablePanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(5,5,5));
        
        String[] headers = { "Check #","Date","Payee","Description","Deposit","Withdrawal"};
        tableModel = new CheckbookTableModel();
        
        for (int index = 0; index < headers.length; index++) {
            tableModel.addColumn(headers[index]);
        }
        
        for (int index = 0; index < checkbook.getTransactions().size(); index++) {
            Transaction transaction = checkbook.getTransactions().get(index);
            updateTableModel(transaction);
        }
        
        transactionTable = new JTable(tableModel);
        transactionTable.setAutoCreateRowSorter(true);
        int[] width = { 75,100,250,75,75 };
        int totalWidth = 0;
        CheckbookCellRenderer cellRenderer = new CheckbookCellRenderer();
        TableColumnModel columnModel = transactionTable.getColumnModel();
        for (int index = 0; index < headers.length; index++) {
            columnModel.getColumn(index).setCellRenderer(cellRenderer);
            columnModel.getColumn(index).setPreferredWidth(width[index]);
            totalWidth += width[index];
        }
        
        JScrollPane scrollPane = new JScrollPane(transactionTable);
        panel.add(scrollPane,BorderLayout.CENTER);
        
        Dimension d = panel.getPreferredSize();
        d.width = totalWidth + 50;
        panel.setPreferredSize(d);
        
        return panel;
    }
    
    public void updateTableModel(Transaction transaction) {
        Object[] object = new Object[6];
        object[0] = transaction.getCheckNumber();
        object[1] = transaction.getTransactionDate();
        object[2] = transaction.getPayee();
        object[3] = transaction.getDescription();
        
        double amount = transaction.getAmount();
        if (amount > 0.0) {
            object[4] = transaction.getAmount();
            object[5] = 0.0;
        } else {
            object[4] = 0.0;
            object[5] = -transaction.getAmount();
        }
        
        tableModel.addRow(object);
    }
    
    private JPanel createTransactionPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(5,5));
        Font titleFont = new Font("Segoe UI",Font.PLAIN,24);
        Font font = new Font("Segoe UI",14);
        
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.LINE_START;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(5,5);
        gbc.gridwidth = 1;
        gbc.weightx = 1.0;
        
        gbc.gridx = 0;
        gbc.gridy = 0;
        JLabel nameLabel = new JLabel(checkbook.getAccount().getAccountName());
        nameLabel.setFont(titleFont);
        panel.add(nameLabel,gbc);
        
        gbc.gridx++;
        JLabel accountNumberLabel = new JLabel(
                checkbook.getAccount().getAccountNumber());
        accountNumberLabel.setFont(titleFont);
        accountNumberLabel.setHorizontalAlignment(JLabel.TRAILING);
        panel.add(accountNumberLabel,gbc);
        
        gbc.gridx = 0;
        gbc.gridy++;
        JLabel label = new JLabel("Balance:");
        label.setFont(font);
        panel.add(label,gbc);
        
        gbc.gridx++;
        balanceField = new JTextField(20);
        balanceField.setEditable(false);
        balanceField.setFont(font);
        balanceField.setHorizontalAlignment(JTextField.TRAILING);
        balanceField.setText(String.format("%,.2f",checkbook.getAccount().getBalance()));
        panel.add(balanceField,gbc);
        
        gbc.gridx = 0;
        gbc.gridy++;
        label = new JLabel("Deposit");
        label.setFont(titleFont);
        panel.add(label,gbc);
        
        gbc.gridx = 0;
        gbc.gridy++;
        label = new JLabel("Date:");
        label.setFont(font);
        panel.add(label,gbc);
        
        gbc.gridx++;
        depositDateField = new JTextField(20);
        depositDateField.setFont(font);
        panel.add(depositDateField,gbc);
        
        gbc.gridx = 0;
        gbc.gridy++;
        label = new JLabel("Amount:");
        label.setFont(font);
        panel.add(label,gbc);
        
        gbc.gridx++;
        depositAmountField = new JTextField(20);
        depositAmountField.setFont(font);
        depositAmountField.setHorizontalAlignment(JTextField.TRAILING);
        panel.add(depositAmountField,gbc);
        
        gbc.gridwidth = 2;
        gbc.gridx = 0;
        gbc.gridy++;
        JButton button = new JButton("Deposit");
        button.addActionListener(new DepositListener(this,checkbook));
        button.setFont(font);
        panel.add(button,gbc);
        
        gbc.gridx = 0;
        gbc.gridy++;
        label = new JLabel("Withdrawl");
        label.setFont(titleFont);
        panel.add(label,gbc);
        
        gbc.gridx = 0;
        gbc.gridy++;
        label = new JLabel("Check Number:");
        label.setFont(font);
        panel.add(label,gbc);
        
        gbc.gridx++;
        withdrawalCheckNumberField = new JTextField(20);
        withdrawalCheckNumberField.setFont(font);
        withdrawalCheckNumberField.setHorizontalAlignment(JTextField.TRAILING);
        panel.add(withdrawalCheckNumberField,gbc);
        
        gbc.gridx++;
        withdrawalDateField = new JTextField(20);
        withdrawalDateField.setFont(font);
        panel.add(withdrawalDateField,gbc);
        
        gbc.gridx = 0;
        gbc.gridy++;
        label = new JLabel("Payee:");
        label.setFont(font);
        panel.add(label,gbc);
        
        gbc.gridx++;
        withdrawalPayeeField = new JTextField(20);
        withdrawalPayeeField.setFont(font);
        panel.add(withdrawalPayeeField,gbc);
        
        gbc.gridx = 0;
        gbc.gridy++;
        label = new JLabel("Description:");
        label.setFont(font);
        panel.add(label,gbc);
        
        gbc.gridx++;
        withdrawalDescriptionField = new JTextField(20);
        withdrawalDescriptionField.setFont(font);
        panel.add(withdrawalDescriptionField,gbc);
        
        gbc.gridx++;
        withdrawalAmountField = new JTextField(20);
        withdrawalAmountField.setFont(font);
        withdrawalAmountField.setHorizontalAlignment(JTextField.TRAILING);
        panel.add(withdrawalAmountField,gbc);
        
        gbc.gridwidth = 2;
        gbc.gridx = 0;
        gbc.gridy++;
        button = new JButton("Withdrawal");
        button.addActionListener(new WithdrawalListener(this,gbc);
        
        return panel;
    }
    
    public void pack() {
        frame.pack();
    }
    
    public void updateBalanceField() {
        this.balanceField.setText(String.format("%,checkbook.getAccount().getBalance()));
    }

    public JTextField getDepositDateField() {
        return depositDateField;
    }

    public JTextField getDepositAmountField() {
        return depositAmountField;
    }

    public JTextField getWithdrawalCheckNumberField() {
        return withdrawalCheckNumberField;
    }

    public JTextField getWithdrawalDateField() {
        return withdrawalDateField;
    }

    public JTextField getWithdrawalPayeeField() {
        return withdrawalPayeeField;
    }

    public JTextField getWithdrawalDescriptionField() {
        return withdrawalDescriptionField;
    }

    public JTextField getWithdrawalAmountField() {
        return withdrawalAmountField;
    }
    
    public class CheckbookTableModel extends DefaultTableModel {

        private static final long serialVersionUID = 1L;

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            switch (columnIndex) {
            case 0:
                return Integer.class;
            case 1:
                return LocalDate.class;
            case 4:
            case 5:
                return Double.class;
            default:
                return String.class;
            }
        }

        @Override
        public boolean isCellEditable(int rowIndex,int columnIndex) {
            return false;
        }
        
    }
    
    public class CheckbookCellRenderer implements TableCellRenderer {
        
        private DateTimeFormatter formatter;
        
        private JLabel label;
        
        public CheckbookCellRenderer() {
            this.formatter = DateTimeFormatter.ofPattern("MMM d,yyyy");
            Font font = new Font("Segoe UI",14);
            this.label = new JLabel();
            label.setFont(font);
            
        }

        @Override
        public Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected,boolean hasFocus,int row,int column) {
            label.setHorizontalAlignment(JLabel.LEADING);
            
            switch (column) {
            case 0:
                if (Integer.valueOf(value.toString()) <= 0) {
                    label.setText("");
                } else {
                    label.setHorizontalAlignment(JLabel.TRAILING);
                    label.setText(value.toString() + "  ");
                }
                break;
            case 1:
                LocalDate date = (LocalDate) value;
                label.setText("  " + formatter.format(date));
                break;
            case 4:
            case 5:
                double amount = Double.valueOf(value.toString());
                if (amount <= 0.0) {
                    label.setText("");
                } else {
                    label.setHorizontalAlignment(JLabel.TRAILING);
                    label.setText(String.format("%,amount) + "  ");
                }
                break;
            default:
                label.setText("  " + value.toString());
                break;
            }
            
            return label;
        }
        
    }
    
    public class DepositListener implements ActionListener {
        
        private final CheckbookGUI view;
        
        private final Checkbook model;
        
        public DepositListener(CheckbookGUI view,Checkbook model) {
            this.view = view;
            this.model = model;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            String date = view.getDepositDateField().getText().trim();
            Double amount = Double.valueOf(view.getDepositAmountField().getText().trim());
            Transaction transaction = new Transaction(null,date,"",amount);
            
            model.addTransaction(transaction);
            model.getAccount().addDeposit(amount);
            
            view.updateBalanceField();
            view.updateTableModel(transaction);
            view.getDepositAmountField().setText("");
            view.getDepositDateField().setText("");
        }
        
    }
    
    public class WithdrawalListener implements ActionListener {
        
        private final CheckbookGUI view;
        
        private final Checkbook model;
        
        public WithdrawalListener(CheckbookGUI view,Checkbook model) {
            this.view = view;
            this.model = model;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            String checkNumberString = view.getWithdrawalCheckNumberField().getText().trim();
            String date = view.getWithdrawalDateField().getText().trim();
            String payee = view.getWithdrawalPayeeField().getText().trim();
            String description = view.getWithdrawalDescriptionField().getText().trim();
            Double amount = Double.valueOf(view.getWithdrawalAmountField().getText().trim());
            
            Integer checkNumber = null;
            try {
                checkNumber = Integer.valueOf(checkNumberString);
            } catch (NumberFormatException e) {
            }
            
            Transaction transaction = new Transaction(checkNumber,payee,description,-amount);
            
            model.addTransaction(transaction);
            model.getAccount().subtractWithdrawal(amount);
            
            view.updateBalanceField();
            view.updateTableModel(transaction);
            view.getWithdrawalCheckNumberField().setText("");
            view.getWithdrawalDateField().setText("");
            view.getWithdrawalPayeeField().setText("");
            view.getWithdrawalDescriptionField().setText("");
            view.getWithdrawalAmountField().setText("");
        }
        
    }

    public class Checkbook {
        
        private final Account account;
        
        private final List<Transaction> transactions;
        
        public Checkbook() {
            this.transactions = new ArrayList<>();
            this.account = new Account("10002939","John H. Smith");
            this.account.addDeposit(1400.00);
            Transaction transaction = new Transaction(
                    null,"4/1/21","Starting Balance",1400.00);
            addTransaction(transaction);
        }
        
        public void addTransaction(Transaction transaction) {
            this.transactions.add(transaction);
        }

        public Account getAccount() {
            return account;
        }

        public List<Transaction> getTransactions() {
            return transactions;
        }
        
    }
    
    public class Account {
        
        private int balance;
        
        private final String accountNumber;
        private final String accountName;
        
        public Account(String accountNumber,String accountName) {
            this.accountNumber = accountNumber;
            this.accountName = accountName;
            this.balance = 0;
        }

        public String getAccountNumber() {
            return accountNumber;
        }

        public String getAccountName() {
            return accountName;
        }

        public double getBalance() {
            return 0.01 * balance;
        }

        public void addDeposit(double amount) {
            this.balance += (int) (100.0 * amount);
        }
        
        public void subtractWithdrawal(double amount) {
            this.balance -= (int) (100.0 * amount);
        }
        
    }
    
    public class Transaction {
        
        private final double amount;
        
        private final int checkNumber;
        
        private final DateTimeFormatter inputFormatter;
        
        private final LocalDate transactionDate;
        
        private final String description;
        private final String payee;

        public Transaction(Integer checkNumber,String transactionDateString,String payee,String description,double amount) {
            if (checkNumber == null) {
                this.checkNumber = 0;
            } else {
                this.checkNumber = checkNumber;
            }
            
            this.inputFormatter = DateTimeFormatter.ofPattern("M/d/yy");
            this.transactionDate = LocalDate.parse(transactionDateString,inputFormatter);
            this.payee = payee;
            this.description = description;
            this.amount = amount;
        }

        public double getAmount() {
            return amount;
        }

        public int getCheckNumber() {
            return checkNumber;
        }

        public LocalDate getTransactionDate() {
            return transactionDate;
        }

        public String getPayee() {
            return payee;
        }

        public String getDescription() {
            return description;
        }
        
    }

}