我試圖將以下代碼的邏輯和 UI 設計分離到它們自己的類中,但我無法弄清楚如何在 Controller 類中呼叫與我的 GUI 類的 swing 組件相關聯的某些方法。
我的問題是,當我在 Controller 類中創建 GUI 類的實體時,GUI 中的 JRadioButtons 類變數僅在 GUI 中的 createRBButtonsPanel() 方法中初始化。當我嘗試呼叫 cokeRb.getText() 方法時,這給了我一個 NullPointerException,例如在控制器的 actionPerformed 方法中,因為我沒有呼叫導致它們被初始化的事件鏈。
我試圖避免將它們全部設定為靜態,因為我確信這樣做不是最佳做法。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class GUI {
private CoinAcceptor coinSlot = new CoinAcceptor();
private VMController controller;
GUI(VMController controller) {
this.controller = controller;
}
private JRadioButton cokeRb, lemonadeRb, tangoRb, waterRb, pepsiRb, spriteRb;
private JButton purchaseBtn , clearBtn, cancelBtn, loyaltyCardBTN;
private JTextField moneyRemainingTf, balanceTf;
private GridBagConstraints c = new GridBagConstraints();
//// Getters /////////////////////////////////
public String getMoneyTFText() { return this.moneyRemainingTf.getText(); }
public String getBalanceTF() { return balanceTf.getText(); }
public String getCokeRbText() { return this.cokeRb.getText(); }
public String getTangoRbText() { return this.tangoRb.getText(); }
public String getLemonadeRbText() { return this.lemonadeRb.getText(); }
public String getWaterRbText() { return this.waterRb.getText(); }
public String getPepsiRbText() { return this.pepsiRb.getText(); }
public String getSpriteRbText() { return this.spriteRb.getText(); }
//// Setters /////////////////////////////////
public void setBalanceTF(String text) { balanceTf.setText(text); }
public void setCokeRbText(String text) { this.cokeRb.setText(text); }
public void setLemonadeRbText(String text) { this.lemonadeRb.setText(text); }
public void setTangoRbText(String text) { this.tangoRb.setText(text); }
public void setWaterRbText(String text) { this.waterRb.setText(text); }
public void setPepsiRbText(String text) { this.pepsiRb.setText(text);}
public void setSpriteRbText(String text) { this.spriteRb.setText(text); }
public void deselectRadioButtons(String button) {
switch (button) {
case "COKE":
this.cokeRb.setSelected(true);
this.lemonadeRb.setSelected(false);
this.tangoRb.setSelected(false);
this.waterRb.setSelected(false);
this.pepsiRb.setSelected(false);
this.spriteRb.setSelected(false);
break;
case "LEMONADE":
this.cokeRb.setSelected(false);
this.lemonadeRb.setSelected(true);
this.tangoRb.setSelected(false);
this.waterRb.setSelected(false);
this.pepsiRb.setSelected(false);
this.spriteRb.setSelected(false);
break;
case "TANGO":
this.lemonadeRb.setSelected(false);
this.cokeRb.setSelected(false);
this.tangoRb.setSelected(true);
this.waterRb.setSelected(false);
this.pepsiRb.setSelected(false);
this.spriteRb.setSelected(false);
break;
case "WATER":
this.lemonadeRb.setSelected(false);
this.tangoRb.setSelected(false);
this.cokeRb.setSelected(false);
this.waterRb.setSelected(true);
this.pepsiRb.setSelected(false);
this.spriteRb.setSelected(false);
break;
case "PEPSI":
this.lemonadeRb.setSelected(false);
this.tangoRb.setSelected(false);
this.waterRb.setSelected(false);
this.cokeRb.setSelected(false);
this.pepsiRb.setSelected(true);
this.spriteRb.setSelected(false);
break;
case "SPRITE":
this.lemonadeRb.setSelected(false);
this.tangoRb.setSelected(false);
this.waterRb.setSelected(false);
this.pepsiRb.setSelected(false);
this.cokeRb.setSelected(false);
this.spriteRb.setSelected(true);
break;
default:
this.lemonadeRb.setSelected(false);
this.tangoRb.setSelected(false);
this.waterRb.setSelected(false);
this.pepsiRb.setSelected(false);
this.cokeRb.setSelected(false);
this.spriteRb.setSelected(false);
break;
}
}
public void clearAllFields() {
deselectRadioButtons("");
balanceTf.setText("");
this.moneyRemainingTf.setText("");
}
public boolean isRBSelected() {
JRadioButton[] radioButtons = new JRadioButton[] { cokeRb, lemonadeRb, tangoRb, waterRb, pepsiRb, spriteRb };
for (JRadioButton button : radioButtons) {
if (button.isSelected())
return true;
}
return false;
}
private JPanel createRBButtonsPanel() {
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(3, 6, 5, 5));
panel.setBorder(BorderFactory.createTitledBorder("Select and item"));
cokeRb = new JRadioButton("Coke : £1.50");
cokeRb.addActionListener(controller);
cokeRb.setActionCommand("COKE");
lemonadeRb = new JRadioButton("Lemonade : £1.20");
lemonadeRb.addActionListener(controller);
lemonadeRb.setActionCommand("LEMONADE");
tangoRb = new JRadioButton("Tango : £1.40");
tangoRb.addActionListener(controller);
tangoRb.setActionCommand("TANGO");
waterRb = new JRadioButton("Water : £1");
waterRb.addActionListener(controller);
waterRb.setActionCommand("WATER");
pepsiRb = new JRadioButton("Pepsi : £1.30");
pepsiRb.addActionListener(controller);
pepsiRb.setActionCommand("PEPSI");
spriteRb = new JRadioButton("Sprite : £1.20");
spriteRb.addActionListener(controller);
spriteRb.setActionCommand("SPRITE");
purchaseBtn = new JButton("PURCHASE");
purchaseBtn.addActionListener(controller);
clearBtn = new JButton("CLEAR");
clearBtn.addActionListener(controller);
cancelBtn = new JButton("CANCEL");
cancelBtn.addActionListener(controller);
panel.add(cokeRb);
panel.add(lemonadeRb);
panel.add(tangoRb);
panel.add(waterRb);
panel.add(pepsiRb);
panel.add(spriteRb);
panel.add(purchaseBtn);
panel.add(clearBtn);
panel.add(cancelBtn);
c.gridx = 0;
c.gridy = 0;
c.insets = new Insets(10, 10, 10, 10);
return panel;
}
private JPanel createInputPanel() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
balanceTf = new JTextField();
// balanceTf.setForeground(Color.gray);
// balanceTf.addFocusListener(new FocusListener() {
//
// @Override
// public void focusGained(FocusEvent e) {
// if (balanceTf.getText().equals("2.50")) {
// balanceTf.setText("");
// balanceTf.setForeground(Color.black);
// }
// }
//
// @Override
// public void focusLost(FocusEvent e) {
// if (balanceTf.getText().isEmpty()) {
// balanceTf.setText("2.50");
// balanceTf.setForeground(Color.gray);
// }
// }
// });
moneyRemainingTf = new JTextField();
moneyRemainingTf.setEditable(false);
loyaltyCardBTN = new JButton("Scan Loyalty Card");
loyaltyCardBTN.addActionListener(controller);
loyaltyCardBTN.setActionCommand("SCAN-CARD");
panel.add(new JLabel("Cash"));
panel.add(balanceTf);
panel.add(new JLabel("Remaining Balance"));
panel.add(moneyRemainingTf);
panel.add(loyaltyCardBTN);
c.gridx = 1;
c.gridy = 0;
return panel;
}
private JPanel coinKeypad() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createTitledBorder("Coins"));
panel.setLayout(new GridLayout(3, 2, 5, 5));
JButton button = new JButton("5p");
button.addActionListener(e -> {
coinSlot.depositCoin(0.05);
balanceTf.setText(String.valueOf(coinSlot.getCoinsValue()));
});
panel.add(button);
button = new JButton("10p");
button.addActionListener(e -> {
coinSlot.depositCoin(0.10);
balanceTf.setText(String.valueOf(coinSlot.getCoinsValue()));
});
panel.add(button);
button = new JButton("20p");
button.addActionListener(e -> {
coinSlot.depositCoin(0.20);
balanceTf.setText(String.valueOf(coinSlot.getCoinsValue()));
});
panel.add(button);
button = new JButton("50p");
button.addActionListener(e -> {
coinSlot.depositCoin(0.50);
balanceTf.setText(String.valueOf(coinSlot.getCoinsValue()));
});
panel.add(button);
button = new JButton("£1");
button.addActionListener(e -> {
coinSlot.depositCoin(1);
balanceTf.setText(String.valueOf(coinSlot.getCoinsValue()));
});
panel.add(button);
button = new JButton("£2");
button.addActionListener(e -> {
coinSlot.depositCoin(2);
balanceTf.setText(String.valueOf(coinSlot.getCoinsValue()));
});
panel.add(button);
c.gridx = 0;
c.gridwidth = 2;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridy = 1;
return panel;
}
private JPanel createBody() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
panel.setLayout(new GridBagLayout());
panel.add(createRBButtonsPanel(), c);
panel.add(createInputPanel(), c);
panel.add(coinKeypad(), c);
return panel;
}
private JPanel createHeader() {
JPanel panel = new JPanel();
JLabel label = new JLabel("Vending Machine");
label.setFont(new Font("Helvetica Neue", 3, 48));
panel.add(label);
return panel;
}
private void addComponentsToPane(Container pane) {
JPanel header = createHeader();
JPanel body = createBody();
pane.add(header, BorderLayout.NORTH);
pane.add(body, BorderLayout.CENTER);
}
private void setLookAndFeel() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
| UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
}
public void createAndShowGUI() {
JFrame frame = new JFrame("Vending Machine with a Four Dillabyte Crossfade");
addComponentsToPane(frame.getContentPane());
frame.setSize(800, 500);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
setLookAndFeel();
frame.setVisible(true);
frame.pack();
}
}
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JOptionPane;
public class VMController implements ActionListener {
private PaymentHandler handler = new PaymentHandler();
private double balance;
private String selectedRBText;
private GUI gui = new GUI(this);
VMController() {
this.balance = 0;
}
private double balanceToDouble() {
double balance = 0;
try {
return Double.valueOf(gui.getBalanceTF());
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(null, "Invalid coin deposit.", "Enter numerical amount",
JOptionPane.ERROR_MESSAGE);
return balance;
}
}
private double productPriceToDouble() {
double productPrice = 0;
try {
return Double.valueOf(selectedRBText);
} catch (NullPointerException ex) {
return productPrice;
}
}
@Override
public void actionPerformed(ActionEvent e) {
String action = e.getActionCommand();
switch (action) {
case "COKE":
gui.deselectRadioButtons("COKE");
selectedRBText = gui.getCokeRbText().substring(gui.getCokeRbText().indexOf('£') 1);
break;
case "LEMONADE":
gui.deselectRadioButtons("LEMONADE");
selectedRBText = gui.getLemonadeRbText().substring(gui.getLemonadeRbText().indexOf('£') 1);
break;
case "TANGO":
gui.deselectRadioButtons("TANGO");
selectedRBText = gui.getTangoRbText().substring(gui.getTangoRbText().indexOf('£') 1);
break;
case "WATER":
gui.deselectRadioButtons("WATER");
selectedRBText = gui.getWaterRbText().substring(gui.getWaterRbText().indexOf('£') 1);
break;
case "PEPSI":
gui.deselectRadioButtons("PEPSI");
selectedRBText = gui.getPepsiRbText().substring(gui.getPepsiRbText().indexOf('£') 1);
break;
case "SPRITE":
gui.deselectRadioButtons("SPRITE");
selectedRBText = gui.getSpriteRbText().substring(gui.getSpriteRbText().indexOf('£') 1);
break;
case "PURCHASE":
if (!gui.isRBSelected())
JOptionPane.showMessageDialog(null, "Choose a product to purchase", "Select a product",
JOptionPane.ERROR_MESSAGE);
else {
if (handler.handlePayment(balanceToDouble(), productPriceToDouble()))
gui.setBalanceTF(String.valueOf(handler.getBalance()));
else
JOptionPane.showMessageDialog(null, "Balance is insufficient for product purchase.",
"Insufficient Funds", JOptionPane.ERROR_MESSAGE);
}
break;
case "CANCEL":
if (handler.getBalance() > 0) {
JOptionPane.showMessageDialog(null, "Order Cancelled.\nChange dispensed.\n£" handler.getBalance());
}
JOptionPane.showMessageDialog(null, "Order Cancelled.");
System.exit(0);
break;
case "CLEAR":
gui.clearAllFields();
break;
case "SCAN-CARD":
System.out.println("scan card");
break;
default:
System.out.println("Action command not defined - \"" action "\"");
break;
}
}
}
uj5u.com熱心網友回復:
介紹
我將您的代碼復制到我的 Eclipse IDE 中。缺少一個類,所以我看不到你的 GUI 是什么樣的。
所以我創建了這個 GUI。

我離開了會員卡按鈕。
解釋
Oracle 有一個有用的教程,使用 Swing 創建 GUI。跳過使用 NetBeans IDE 學習搖擺部分。
在創建 Swing 應用程式時,我使用模型-視圖-控制器(MVC) 模式。顧名思義,您首先創建模型,然后是視圖,然后是控制器。
應用程式模型由一個或多個普通的 Java getter/setter 類組成。
視圖由一個JFrame、一個或多個JPanels和 Swing 組件組成。
每個Action或ActionListener類構成控制器。通常沒有一個控制器可以“統治他們所有人”。
模型
我創建的第一個模型類是Item類。該類Item包含一個名稱和一個價格。價格以便士為單位。使用 int 欄位保存價格使計算更容易。我在顯示價格時將便士換算成英鎊。
我創建的第二個模型類是VendingMachineModel類。該類VendingMachineModel包含一個java.util.List專案、一個java.util.List硬幣、一個int余額欄位和一個int找零欄位。
看法
你的觀點很容易理解,結構很好,所以我在這里沒有太多評論。我用 aButtonGroup將選擇限制JRadioButtons為一個。
不要讓所有的 Swing 組件類欄位。這會讓您的代碼的讀者感到困惑。類欄位只能用于不止一種方法中需要的欄位。
從最重要的方法到最不重要的方法對類中的方法進行排序。這使人們更容易閱讀和理解代碼。
控制器
I used lambda expressions for all the JButtons except the purchase button. That ActionPerformed method was too large for a lambda expression, in my opinion, so I created a PurchaseListener class.
Code
Here's the complete runnable code. I made the additional classes inner classes so I could post the code as one block.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
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.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class VendingMachineExample implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new VendingMachineExample());
}
private ButtonGroup buttonGroup;
private JFrame frame;
private JTextField balanceField, changeField;
private final VendingMachineModel model;
public VendingMachineExample() {
this.model = new VendingMachineModel();
}
@Override
public void run() {
frame = new JFrame("Vending Machine with a Four Dillabyte Crossfade");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createHeaderPanel(), BorderLayout.NORTH);
frame.add(createBodyPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createHeaderPanel() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JLabel label = new JLabel("Vending Machine");
label.setFont(new Font("Helvetica Neue", 3, 48));
panel.add(label);
return panel;
}
private JPanel createBodyPanel() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
panel.setLayout(new FlowLayout());
panel.add(createVendingPanel());
panel.add(createDisplayPanel());
panel.add(createCoinKeypad());
return panel;
}
private JPanel createVendingPanel() {
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(0, 3, 5, 5));
panel.setBorder(BorderFactory.createTitledBorder("Select an item"));
buttonGroup = new ButtonGroup();
for (Item item : model.getItems()) {
double price = 0.01 * item.getPrice();
String text = item.getName() ": £" String.format("%.2f", price);
JRadioButton button = new JRadioButton(text);
text = item.getName() ";;;" item.getPrice();
button.setActionCommand(text);
buttonGroup.add(button);
panel.add(button);
}
JButton button = new JButton("Purchase");
button.addActionListener(new PurchaseListener(this, model));
panel.add(button);
button = new JButton("Clear");
button.addActionListener(event -> {
buttonGroup.clearSelection();
});
panel.add(button);
button = new JButton("Cancel");
button.addActionListener(event -> {
buttonGroup.clearSelection();
int amount = model.getBalance();
model.setBalance(0);
model.setChange(amount);
updateDisplayPanel();
});
panel.add(button);
return panel;
}
private JPanel createDisplayPanel() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.add(new JLabel("Cash"));
balanceField = new JTextField(10);
balanceField.setEditable(false);
balanceField.setHorizontalAlignment(JTextField.CENTER);
panel.add(balanceField);
panel.add(new JLabel("Change"));
changeField = new JTextField(10);
changeField.setEditable(false);
changeField.setHorizontalAlignment(JTextField.CENTER);
panel.add(changeField);
updateDisplayPanel();
return panel;
}
public void updateDisplayPanel() {
double amount = 0.01 * model.getBalance();
String text = "£" String.format("%.2f", amount);
balanceField.setText(text);
amount = 0.01 * model.getChange();
text = "£" String.format("%.2f", amount);
changeField.setText(text);
}
private JPanel createCoinKeypad() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createTitledBorder("Coins"));
panel.setLayout(new GridLayout(0, 2, 5, 5));
for (Item item : model.getCoins()) {
JButton button = new JButton(item.getName());
button.setActionCommand(Integer.toString(item.getPrice()));
button.addActionListener(event -> {
model.setChange(0);
model.addCoin(item.getPrice());
updateDisplayPanel();
});
panel.add(button);
}
return panel;
}
public ButtonGroup getButtonGroup() {
return buttonGroup;
}
public JFrame getFrame() {
return frame;
}
public class PurchaseListener implements ActionListener {
private final VendingMachineExample view;
private final VendingMachineModel model;
public PurchaseListener(VendingMachineExample view, VendingMachineModel model) {
this.view = view;
this.model = model;
}
@Override
public void actionPerformed(ActionEvent event) {
ButtonModel buttonModel = view.getButtonGroup().getSelection();
if (buttonModel == null) {
JOptionPane.showMessageDialog(view.getFrame(),
"Please select an item", "Select an item",
JOptionPane.ERROR_MESSAGE);
} else {
String text = buttonModel.getActionCommand();
String[] parts = text.split(";;;");
String name = parts[0];
int amount = Integer.valueOf(parts[1]);
int balance = model.getBalance();
if (balance >= amount) {
displayPurchaseMessage(name, amount, balance);
} else {
displayDifferenceMessage(amount, balance);
}
}
}
private void displayPurchaseMessage(String name, int amount, int balance) {
String text;
text = "You purchased a " name;
JOptionPane.showMessageDialog(view.getFrame(), text, "Item purchased",
JOptionPane.INFORMATION_MESSAGE);
model.purchaseProduct(amount);
int change = balance - amount;
model.setBalance(0);;
model.setChange(change);
view.updateDisplayPanel();
view.getButtonGroup().clearSelection();
}
private void displayDifferenceMessage(int amount, int balance) {
String text;
int difference = amount - balance;
double price = 0.01 * difference;
text = "Please deposit an additional £"
String.format("%.2f", price);
JOptionPane.showMessageDialog(view.getFrame(), text, "Add Coins",
JOptionPane.ERROR_MESSAGE);
}
}
public class VendingMachineModel {
private int balance, change;
private final List<Item> coins, items;
public VendingMachineModel() {
this.balance = 0;
this.change = 0;
this.coins = new ArrayList<>();
this.coins.add(new Item("5p", 5));
this.coins.add(new Item("10p", 10));
this.coins.add(new Item("20p", 20));
this.coins.add(new Item("50p", 50));
this.coins.add(new Item("£1", 100));
this.coins.add(new Item("£2", 200));
this.items = new ArrayList<>();
this.items.add(new Item("Coke", 150));
this.items.add(new Item("Lemonade", 120));
this.items.add(new Item("Tango", 140));
this.items.add(new Item("Water", 100));
this.items.add(new Item("Pepsi", 130));
this.items.add(new Item("Sprite", 120));
}
public List<Item> getCoins() {
return coins;
}
public List<Item> getItems() {
return items;
}
public void addCoin(int amount) {
this.balance = amount;
}
public void purchaseProduct(int amount) {
this.balance -= amount;
}
public void setBalance(int balance) {
this.balance = balance;
}
public int getBalance() {
return balance;
}
public void setChange(int change) {
this.change = change;
}
public int getChange() {
return change;
}
}
public class Item {
private final int price;
private final String name;
public Item(String name, int price) {
this.name = name;
this.price = price;
}
public int getPrice() {
return price;
}
public String getName() {
return name;
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/434897.html
下一篇:使用Java圖形創建2D圓柱體
