如何通过JButton点击事件关闭基于JFrame的窗口

3

我对Java Swing/AWT对话框还很陌生(这也解释了下面这个对话框看起来多么业余),希望有人能帮我更好地排列它 :) 当任意一个JButton被点击时,我都无法关闭这个popUp窗口。

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

再次说明,这是由另一个正在运行的主进程调用的二级弹出窗口,所以我只想关闭这个特定的popUp窗口而不影响主进程。否则我可以使用System.exit

正如我提到的,欢迎任何其他建议来改善对话框的整体外观和感觉。

我的全部代码如下:

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();
    }
  }
}

1
我无法理解你的意图。是谁调用了 createGUI 方法?传递给构造函数的 Object ft 是什么?我猜测了一些东西,并尝试了一下,frame.dispose 似乎工作正常。 - Lauri Lehtinen
你说你想关闭从其他主方法触发的弹出窗口?如果你没有对它的引用,你就不能关闭它。这个面板在那个弹出窗口中使用吗? - OscarRyz
4个回答

2
问题在于您的createGUI方法不是静态的。所以我想您首先创建了一个UpgradePopupWindow,在其上调用createGUI方法,而该方法又创建了一个新的UpgradePopupWindow。
请尝试改为以下方式:
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();
    }
  }

}

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

不确定为什么您看不到框架关闭。我实际运行了代码,当按钮被点击时,该框架已关闭。您是复制并粘贴了代码吗? - mdma
大家好,有没有想法在哪里设置对话框的固定大小(尺寸)?你可能已经注意到现在它看起来很奇怪,因为两个按钮在句子末尾。然而,当我用一个短的四行段落替换那一行时,对话框看起来更加奇怪,横跨整个显示器。我只是想要一个合理大小的窗口,在其中有几行文本,下面排列着两个按钮。谢谢! - LambeauLeap
@LambeuLeap - 我认为你最好创建一个新问题。你知道JOptionPane吗?它可以创建带有图标和关闭按钮的多行文本。如果符合你的需求,它可能会节省你很多工作。此外,JIDE Common Components库(开源)还具有各种类型的弹出对话框。 - mdma
@camickr - 我认为你更喜欢和支持自己的解决方案是很自然的,获取祖先是一个不错的附加功能,但你在评论中吹嘘自己的解决方案的卓越性有点过分。它们都解决了手头的问题。 - mdma
@mdma,很抱歉我说话有点粗鲁,我想我应该加个眨眼的表情;),我是想指出原帖作者两种解决方案之间微妙的区别。 - camickr
显示剩余3条评论

2

您的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);
  }

+1。而且,@LambeauLeap:你的关闭机制应该只需要使用setVisible,不需要更强有力的方法。 - Noel Ang

0
问题在于您有两个UpgradePopupWindow类的实例。首先,您需要创建一个实例,以便可以调用createGUI()方法。然后,在createGUI方法中,您创建了该类的另一个实例。我确定这不是您想要的。
一种解决方案是使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);
    }

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

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

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

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

外观看起来对我来说还不错。简单明了。

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
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接