Java Swing - GUI 的操作

Posted

技术标签:

【中文标题】Java Swing - GUI 的操作【英文标题】:Java Swing - manipulation of GUI 【发布时间】:2016-09-01 21:08:30 【问题描述】:

我可能遇到了一些微不足道的问题,但我花了几个小时寻找答案。

我想创建一个按钮(ENTER 按钮),一旦单击该按钮,就会删除 GUI 上的某些组件(如小键盘)。问题是定义一旦单击按钮执行的指令的类看不到组件。我尝试将implements ATM 添加到此类,但随后控制台返回了非常奇怪的错误(执行时)。有什么“干净”的方法可以做到这一点吗?

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

public class ATM extends JFrame

// Container
int state = 0; // PIN screen

// ELEMENTS
JPanel container = new JPanel();
JTextArea display = new JTextArea("Please enter your PIN", 10, 50);
JTextField inputArea = new JTextField("");
JPanel buttons = new JPanel();
JButton one = new JButton("1");
JButton two = new JButton("2");
JButton three = new JButton("3");
JButton four = new JButton("4");
JButton five = new JButton("5");
JButton six = new JButton("6");
JButton seven = new JButton("7");
JButton eight = new JButton("8");
JButton nine = new JButton("9");
JButton zero = new JButton("0");
JButton clear = new JButton("Clear");
JButton enter = new JButton("Enter");
JButton quit = new JButton("Quit");

// EVENTS
ButtonPresser buttonPress = new ButtonPresser(inputArea, display);
EnterPresser enterPress = new EnterPresser(inputArea, display, state, buttons);

ATM()
super("ATM Cash Machine");
buildGUI();
pack();
setVisible(true);


private void buildGUI()

  // EVENT BINDINGS
  one.addActionListener(buttonPress);
  two.addActionListener(buttonPress);
  three.addActionListener(buttonPress);
  four.addActionListener(buttonPress);
  five.addActionListener(buttonPress);
  six.addActionListener(buttonPress);
  seven.addActionListener(buttonPress);
  eight.addActionListener(buttonPress);
  nine.addActionListener(buttonPress);
  zero.addActionListener(buttonPress);
  clear.addActionListener(buttonPress);
  quit.addActionListener(buttonPress);
  enter.addActionListener(enterPress);

  // ELEMENT SETTINGS
  inputArea.setEditable(false);
  display.setEditable(false);

  container.setLayout(new BoxLayout(container, BoxLayout.PAGE_AXIS));
  container.add(display);
  container.add(inputArea);

    // Numeric pad
    buttons.setLayout(new GridLayout(5,3));
      buttons.add(one);
      buttons.add(two);
      buttons.add(three);
      buttons.add(four);
      buttons.add(five);
      buttons.add(six);
      buttons.add(seven);
      buttons.add(eight);
      buttons.add(nine);
      buttons.add(clear);
      buttons.add(zero);
      buttons.add(enter);
      buttons.add(quit);
  container.add(buttons);

 add(container, BorderLayout.NORTH);


// Main method
public static void main(String[] args)
  ATM atm = new ATM();



class ButtonPresser implements ActionListener

private JTextField iField;
private JTextArea oArea;

ButtonPresser(JTextField in, JTextArea out)

iField = in;
oArea = out;



public void actionPerformed(ActionEvent e)

switch(e.getActionCommand())
  case "Quit":
    System.exit(0);
    break;
  case "Clear":
    iField.setText("");
    break;
  default:
    String fieldText = iField.getText();
    if(fieldText.length() < 4)
      iField.setText(fieldText+e.getActionCommand());
    
    break;

 





class EnterPresser implements ActionListener

  private JTextField iField;
 private JTextArea oArea;
private int state;
private JPanel buttons;

private final String PIN = "1234";

EnterPresser(JTextField in, JTextArea out, int st, JPanel but)

iField = in;
oArea = out;
state = st;
buttons = but;



 public void actionPerformed(ActionEvent e)

if(state == 0)
  String fieldText = iField.getText();
  if(fieldText.equals(PIN))
    iField.setText("");
    state = 1;
    uiState0To1();
  


 

 public void uiState0To1()
   buttons.remove(one);
  

 

【问题讨论】:

【参考方案1】:

您的问题的解决方案很简单。您需要某种方式让您的 ButtonPresser 类与您的 ATM 类交谈,这是 Observer Pattern 的经典示例

这个想法是,您将提供某种事件通知,您的 ButtonPresser 将在某些条件下触发,然后您的 ATM 类将监听这些事件,然后它会根据这些事件决定它应该做什么.

修改ATM的状态不是ButtonPresser的责任,所以我们很清楚。

您现在正在进入 Model-View-Controller 领域,这可以为您提供一种利用 CardLayout 的方法,这将进一步降低您的问题的整体复杂性,同时隔离责任并解耦您的代码

【讨论】:

【参考方案2】:

我不确定您要删除哪些组件,但您的问题很清楚。 ATM 类中定义的所有组件都不公开。从其他类中操作这些组件的一种方法是将它们设为公开。

最简单的方法是将它们声明为“public static”并通过 ATM 类静态引用它们。根据您的情况,您可能需要多个 ATM 实例,在这种情况下,您不会将它们声明为静态。

这是另一个信息很好的问题:Difference between public static and private static variables

【讨论】:

我总是对理解静态和非静态的东西有疑问。无论如何它都有效,谢谢! 您建议将字段设置为 public 已经够糟糕了,但 static 也是如此,这在这两个方面都是完全错误且非常糟糕的建议 我不确定这是怎么回事。如果他想操作其他班级的组件,那么这是一种方法……我的回答没有错。 创建一个以上的组件实例,看看它有多么错误,将字段设为 public 会移除封装并将组件暴露给不受约束的修改。静态不是跨对象通信机制,应仔细考虑其使用并权衡其产生的问题。公共静态的建议是短视的、限制性的和不专业的,它也鼓励了更好的设计方法可以解决的坏习惯。 “简单”的解决方案总是“正确”的解决方案 在他的帖子中,他试图静态访问它们,但由于组件未公开而失败。他是一个明显的初学者,告诉他重新设计他的整个示例是不切实际的,实际上并不能解决他的问题。你的帖子很有见地,有可取之处,但这并不意味着我的帖子错了……

以上是关于Java Swing - GUI 的操作的主要内容,如果未能解决你的问题,请参考以下文章

Swing 是一个为Java设计的GUI工具包

JAVA GUI窗体及控件

Java 的 Swing 线程

Java Swing 简单介绍

Java Swing学生成绩管理系统(GUI 界面)

14.1-全栈Java笔记: Java语言中GUI到底是神马鬼?| AWT | Swing