Java 如何使用 JButton 单击事件关闭基于 JFrame 的窗口

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3114162/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 16:35:03  来源:igfitidea点击:

How to close a JFrame based window with a JButton click event

javaswingawtjframejbutton

提问by LambeauLeap

I am new to the whole Java Swing/AWT dialogs (which explains how amateurish this dialog below looks like, any help in arranging it better is welcome :) and I am struggling to close this popUp window when any of the two JButtons are clicked.

我是整个 Java Swing/AWT 对话框的新手(它解释了下面这个对话框的业余程度,欢迎任何帮助更好地安排它:)并且当单击两个 JButton 中的任何一个时,我正在努力关闭这个弹出窗口。

I have already tried options like frame.dispose(), frame.setVisible(false)and even SwingUtilities.getWindowAncestor(this).dispose();

我已经尝试过类似的选项frame.dispose()frame.setVisible(false)甚至SwingUtilities.getWindowAncestor(this).dispose();

Again, this is a secondary popup window invoked by another main process running, so I just want this particular popUp window to close and not affect the main process. Otherwise I could use System.exit

同样,这是由另一个正在运行的主进程调用的辅助弹出窗口,所以我只想关闭这个特定的弹出窗口而不影响主进程。否则我可以使用System.exit

Like I mentioned, any other suggestions to improve the overall look and feel of the dialog are appreciated.

就像我提到的,任何其他改善对话框整体外观的建议都值得赞赏。

My entire code is as below:

我的整个代码如下:

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class UpgradePopupWindow extends JPanel implements ActionListener {
  public static UpgradePopupWindow mainWindow;

  static final long serialVersionUID = 0;

  final String upgrade = "Continue Upgrade";
  final String restore = "Restore";

  JPanel panels;
  JButton flashMe;
  JButton helpMe;
  JTextArea Message;
  JFrame frame;

  protected JTextArea addText(String text, boolean visible, int fontStyle) {
    JTextArea textArea = new JTextArea(text);

    textArea.setFont(new Font("SansSerif", fontStyle, 12)); //$NON-NLS-1$

    textArea.setLineWrap(true);
    textArea.setWrapStyleWord(true);
    textArea.setEditable(false);
    textArea.setForeground(Color.WHITE);
    textArea.setOpaque(false);
    textArea.setVisible(visible);
    textArea.setAlignmentX(Component.CENTER_ALIGNMENT);

    add(textArea);

    return textArea;
  }

  public UpgradePopupWindow(Object ft) {
    String text = "This is the random text for now. I will bother about the actual content later";
    addLabel(text, Font.PLAIN, 12);

    flashMe = new JButton(upgrade);
    flashMe.setActionCommand("upgrade");
    flashMe.addActionListener(this);
    flashMe.setEnabled(true);
    add(flashMe);


    helpMe = new JButton(restore);
    helpMe.setActionCommand("restore");
    helpMe.addActionListener(this);
    helpMe.setEnabled(true);
    add(helpMe);
  }

  protected JLabel addLabel(String text, int fontStyle, int size) {
    JLabel label = new JLabel(text);
    label.setFont(new Font("SansSerif", fontStyle, size)); 
    label.setAlignmentX(Component.CENTER_ALIGNMENT);
    label.setOpaque(false);
    label.setVisible(true);
    label.setForeground(Color.BLUE);

    add(label);
    return label;
  }

  public void createGUI(Object obj) {
    //Create and set up the frame.
    frame = new JFrame("PopUp Dialog");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //create and setup the content pane
    UpgradePopupWindow popUpContentPane = new UpgradePopupWindow(obj);

    popUpContentPane.setOpaque(true);
    frame.setContentPane(popUpContentPane);

    frame.pack();
    frame.setVisible(true);
  }

  public void actionPerformed(ActionEvent e) {
    if("restore".equals(e.getActionCommand())) {
      System.out.println("restore button selected");
      frame.dispose();
      SwingUtilities.getWindowAncestor(this).dispose();
    } else if ("upgrade".equals(e.getActionCommand())) {
      System.out.println("upgrade button selected");
      frame.dispose();
    }
  }
}

采纳答案by mdma

The problem is that your createGUI method is not static. So I imagine you are creating first a UpgradePopupWindow, calling createGUI on that, which in turn creates a enw UpgradePopupWindow.

问题是您的 createGUI 方法不是静态的。所以我想你首先创建一个 UpgradePopupWindow,在它上面调用 createGUI,然后创建一个 enw UpgradePopupWindow。

Try this instead:

试试这个:

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

public class TempTest
{
    public static void main(String[] args)
    {
        UpgradePopupWindow.createGUI(null);
    }
}


class UpgradePopupWindow extends JPanel implements ActionListener {
  public static UpgradePopupWindow mainWindow;

  static final long serialVersionUID = 0;

  final String upgrade = "Continue Upgrade";
  final String restore = "Restore";

  JPanel panels;
  JButton flashMe;
  JButton helpMe;
  JTextArea Message;
    JFrame frame;


    protected JTextArea addText(String text, boolean visible, int fontStyle) {
    JTextArea textArea = new JTextArea(text);

    textArea.setFont(new Font("SansSerif", fontStyle, 12)); //$NON-NLS-1$

    textArea.setLineWrap(true);
    textArea.setWrapStyleWord(true);
    textArea.setEditable(false);
    textArea.setForeground(Color.WHITE);
    textArea.setOpaque(false);
    textArea.setVisible(visible);
    textArea.setAlignmentX(Component.CENTER_ALIGNMENT);

    add(textArea);

    return textArea;
  }

  public UpgradePopupWindow(JFrame frm, Object ft2) {
    String text = "This is the random text for now. I will bother about the actual content later";
    addLabel(text, Font.PLAIN, 12);
      frame = frm;
    flashMe = new JButton(upgrade);
    flashMe.setActionCommand("upgrade");
    flashMe.addActionListener(this);
    flashMe.setEnabled(true);
    add(flashMe);


    helpMe = new JButton(restore);
    helpMe.setActionCommand("restore");
    helpMe.addActionListener(this);
    helpMe.setEnabled(true);
    add(helpMe);
  }

  protected JLabel addLabel(String text, int fontStyle, int size) {
    JLabel label = new JLabel(text);
    label.setFont(new Font("SansSerif", fontStyle, size));
    label.setAlignmentX(Component.CENTER_ALIGNMENT);
    label.setOpaque(false);
    label.setVisible(true);
    label.setForeground(Color.BLUE);

    add(label);
    return label;
  }

  public static void createGUI(Object obj) {
    //Create and set up the frame.
    JFrame frame = new JFrame("PopUp Dialog");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //create and setup the content pane
    UpgradePopupWindow popUpContentPane = new UpgradePopupWindow(frame, obj);

    popUpContentPane.setOpaque(true);
    frame.setContentPane(popUpContentPane);

    frame.pack();
    frame.setVisible(true);
  }

  public void actionPerformed(ActionEvent e) {
    if("restore".equals(e.getActionCommand())) {
      System.out.println("restore button selected");
      frame.dispose();
      SwingUtilities.getWindowAncestor(this).dispose();
    } else if ("upgrade".equals(e.getActionCommand())) {
      System.out.println("upgrade button selected");
      frame.dispose();
    }
  }

}

The main change is that the createUI is static, and the UpgradePopupWindow takes the frame in the constructor.

主要的变化是 createUI 是静态的,并且 UpgradePopupWindow 在构造函数中采用框架。

回答by camickr

The problem is that you have two instances of your UpgradePopupWindow class. First you need to create an instance so you can invoke the createGUI() method. Then in the createGUI method you create another instance of the class. I'm sure is not what you intended.

问题是您有两个 UpgradePopupWindow 类的实例。首先,您需要创建一个实例,以便您可以调用 createGUI() 方法。然后在 createGUI 方法中创建该类的另一个实例。我肯定不是你想要的。

One solution is to make the createGUI() method static. I removed the "frame" variable from the class and made the following changes:

一种解决方案是将 createGUI() 方法设为静态。我从类中删除了“frame”变量并进行了以下更改:

  public static void createGUI(Object obj) {
    //Create and set up the frame.
    JFrame frame = new JFrame("PopUp Dialog");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //create and setup the content pane
    UpgradePopupWindow popUpContentPane = new UpgradePopupWindow(obj);

    popUpContentPane.setOpaque(true);
    frame.setContentPane(popUpContentPane);

    frame.pack();
    frame.setVisible(true);
  }

  public void actionPerformed(ActionEvent e) {
    if("restore".equals(e.getActionCommand())) {
      System.out.println("restore button selected");
//      frame.dispose();
      SwingUtilities.getWindowAncestor(this).dispose();
    } else if ("upgrade".equals(e.getActionCommand())) {
      System.out.println("upgrade button selected");
//      frame.dispose();
      SwingUtilities.getWindowAncestor(this).dispose();
    }
  }

    public static void main(String[] args)
    {
        UpgradePopupWindow.createGUI(null);
    }

回答by Paul Jowett

Your createGUI() method is a little confused, it creates ANOTHER instance of this class and you end up with one instance with a frame and one instance without. Minimal change to get it working is to change your createGUI method:

你的 createGUI() 方法有点混乱,它创建了这个类的另一个实例,你最终得到一个有框架的实例和一个没有框架的实例。使其工作的最小更改是更改您的 createGUI 方法:

  public void createGUI(Object obj) {
    //Create and set up the frame.
    frame = new JFrame("PopUp Dialog");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//    //create and setup the content pane
//    UpgradePopupWindow popUpContentPane = new UpgradePopupWindow(obj);

    setOpaque(true);
    frame.setContentPane(this);

    frame.pack();
    frame.setVisible(true);
  }

回答by Michael

Inside the createGUI()method, you're instantiating the framevariable and setting its content pane to another instance of UpgradePopupWindow. But you don't instantiate the framevariable of that second instance. When the Restore or Upgrade buttons are clicked, it is invoking the actionPerformed()method of that secondinstance, so frame.dispose()and frame.setVisible(false)won't work because frameis null.

在该createGUI()方法中,您正在实例化frame变量并将其内容窗格设置为 UpgradePopupWindow 的另一个实例。但是您没有实例化frame第二个实例的变量。当点击还原或升级按钮,则调用actionPerformed()该方法第二个实例,因此frame.dispose()frame.setVisible(false)不会工作,因为frame是空的。

I would suggest having your UpgradePopupWindow class extend JFrameinstead of JPanel. That way, you can call the dispose()method directly. Plus, it just makes more sense to have one class == one window (a JPanel isn't a window, just a grouping of GUI widgets). Then, create a JPanel in the constructor and add the widgets to that. You can also get rid of that nasty mainWindowstatic variable.

我建议让您的 UpgradePopupWindow 类扩展JFrame而不是 JPanel。这样,您就可以dispose()直接调用该方法。另外,让一个类 == 一个窗口更有意义(JPanel 不是一个窗口,只是一组 GUI 小部件)。然后,在构造函数中创建一个 JPanel 并将小部件添加到其中。您还可以摆脱那个讨厌的mainWindow静态变量。

Also, I don't think JFrame.EXIT_ON_CLOSEis what you want to use here. You want to close the window, not terminate the entire application. JFrame.DISPOSE_ON_CLOSEwill dispose just the window when it is closed.

另外,我认为这不是JFrame.EXIT_ON_CLOSE您想在这里使用的。您想关闭窗口,而不是终止整个应用程序。 JFrame.DISPOSE_ON_CLOSE将在关闭时仅处理窗口。

You can also more finely-tune the way your dialog reacts to window events by implementing the WindowListenerinterface.

您还可以通过实现WindowListener接口来更精细地调整对话框对窗口事件的反应方式。

The look and feel looks OK to me. Simple and straight forward.

外观和感觉对我来说还不错。简单直接。

public class Main{
  public static void main(String args[]){
    //display the window from your main window
    UpgradePopupWindow upw = new UpgradePopupWindow(obj);
    upw.setVisible(true);
  }
}

public class UpgradePopupWindow extends JFrame implements ActionListener, WindowListener {
  //...

  public UpgradePopupWindow(Object ft) {
    super("PopUp Dialog");
    JPanel panel = new JPanel();
    //...
    setContentPane(panel);
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    pack();
  }

  public void actionPerformed(ActionEvent e) {
    if("restore".equals(e.getActionCommand())) {
      System.out.println("restore button selected");
      dispose();
    } else if ("upgrade".equals(e.getActionCommand())) {
      System.out.println("upgrade button selected");
      dispose();
    }
  }

  public void windowClosed(WindowEvent e) { 
    System.out.println("Window closed!");
  }
  //other WindowListener methods
}