Java Swing应用程序,当点击按钮时关闭一个窗口并打开另一个窗口。

16

我有一个基于NetBeans的Java应用程序,启动应用程序时应该显示一个具有选项的JFrame(类StartUpWindow继承自JFrame),然后用户点击按钮,该JFrame应关闭并打开一个新的窗口(类MainWindow)。

那么如何正确完成这个任务呢?很明显,在StartupWindow中设置了按钮的单击事件处理程序,但我应该在这个处理程序中放什么内容,以便能够关闭StartUpWindow并打开MainWindow?似乎线程也涉及到这个问题,因为每个窗口似乎都有自己的线程......或者线程问题是否由JFrames自动处理...


3
题目1:使用多个JFrames,是好还是坏的做法? 回答链接:https://dev59.com/Wmkw5IYBdhLWcg3w8O6o#9554657在Swing应用程序中,使用多个JFrames通常被认为是不好的做法。这是因为:
  1. JFrames是重量级组件,每个JFrame都会创建一个新的窗口。如果使用太多的JFrames,可能会导致内存消耗过高。
  2. 维护多个JFrames可能会很麻烦。当用户切换到另一个JFrame时,主要窗口可能会变得不可见,从而使应用程序难以使用。
  3. 通常最好使用单个JFrame并将其他UI组件添加到该JFrame上,或者使用对话框来获取用户输入。
题目2:如何在运行时删除顶层容器? 回答链接:https://dev59.com/T2015IYBdhLWcg3w7wQW要在运行时删除顶层容器,需要先获取该容器的父容器,然后从其父容器中删除该容器。示例如下:Container parent = topLevelContainer.getParent(); parent.remove(topLevelContainer); parent.validate();这将从父容器中删除topLevelContainer,并调用validate()方法重新布置其余组件。请注意,如果您正在关闭应用程序,则还需要调用dispose()方法释放与容器关联的任何资源。
- mKorbel
7个回答

27

这里有一个示例:

输入图片描述

输入图片描述

StartupWindow.java

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;


public class StartupWindow extends JFrame implements ActionListener
{
    private JButton btn;

    public StartupWindow()
    {
        super("Simple GUI");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        btn = new JButton("Open the other JFrame!");
        btn.addActionListener(this);
        btn.setActionCommand("Open");
        add(btn);
        pack();

    }

    @Override
    public void actionPerformed(ActionEvent e)
    {
        String cmd = e.getActionCommand();

        if(cmd.equals("Open"))
        {
            dispose();
            new AnotherJFrame();
        }
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable(){

            @Override
            public void run()
            {
                new StartupWindow().setVisible(true);
            }

        });
    }
}

AnotherJFrame.java

import javax.swing.JFrame;
import javax.swing.JLabel;

public class AnotherJFrame extends JFrame
{
    public AnotherJFrame()
    {
        super("Another GUI");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        add(new JLabel("Empty JFrame"));
        pack();
        setVisible(true);
    }
}

@Eng.Fouad,如何从AnotherJFrame打开StartupWindow?在AnotherJFrame中创建StartupWindow对象是行不通的。 - Kasun Siyambalapitiya

10

显然,你应该使用CardLayout。在这种情况下,你可以通过使用CardLayout来改变JPanels而不是打开两个JFrame。

创建和显示GUI的代码应该放在SwingUtilities.invokeLater(...);方法中以保证线程安全。如果想要了解更多信息,你可以阅读有关Swing中的并发性的内容。

但是,如果你坚持自己的方法,这里有一份示例代码供参考。

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

public class TwoFrames
{
    private JFrame frame1, frame2;
    private ActionListener action;
    private JButton showButton, hideButton;

    public void createAndDisplayGUI()
    {
        frame1 = new JFrame("FRAME 1");
        frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);      
        frame1.setLocationByPlatform(true);

        JPanel contentPane1 = new JPanel();
        contentPane1.setBackground(Color.BLUE);

        showButton = new JButton("OPEN FRAME 2");
        hideButton = new JButton("HIDE FRAME 2");

        action  = new ActionListener()
        {
            public void actionPerformed(ActionEvent ae)
            {
                JButton button = (JButton) ae.getSource();

                /*
                 * If this button is clicked, we will create a new JFrame,
                 * and hide the previous one.
                 */
                if (button == showButton)
                {
                    frame2 = new JFrame("FRAME 2");
                    frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);      
                    frame2.setLocationByPlatform(true);

                    JPanel contentPane2 = new JPanel();
                    contentPane2.setBackground(Color.DARK_GRAY);

                    contentPane2.add(hideButton);
                    frame2.getContentPane().add(contentPane2);
                    frame2.setSize(300, 300);
                    frame2.setVisible(true);
                    frame1.setVisible(false);
                }
                /*
                 * Here we will dispose the previous frame, 
                 * show the previous JFrame.
                 */
                else if (button == hideButton)
                {
                    frame1.setVisible(true);
                    frame2.setVisible(false);
                    frame2.dispose();
                }
            }
        };

        showButton.addActionListener(action);
        hideButton.addActionListener(action);

        contentPane1.add(showButton);

        frame1.getContentPane().add(contentPane1);
        frame1.setSize(300, 300);
        frame1.setVisible(true);
    }
    public static void main(String... args)
    {
        /*
         * Here we are Scheduling a JOB for Event Dispatcher
         * Thread. The code which is responsible for creating
         * and displaying our GUI or call to the method which 
         * is responsible for creating and displaying your GUI
         * goes into this SwingUtilities.invokeLater(...) thingy.
         */
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new TwoFrames().createAndDisplayGUI();
            }
        });
    }
}

输出结果为:

Frame1Frame2


1
我们又见面了...又一个很棒的例子 +1。 - JAN
1
@ron:这个例子不允许用户打开多个JFrame,它还检查条件,如果一个JFrame已经打开了,那就不要再打开新的。 - nIcE cOw

8
您可以在当前窗口上调用dispose(),并在您想要显示的窗口上调用setVisible(true)

你会将JFrame变量保留在类范围内吗?还是在第二个JFrame显示后,你会将其设置为可供垃圾回收选择? - Timoteo Ponce
dispose()会使对象成为垃圾回收的对象,只要你没有保留任何其他对它的引用。 - Garrett Hall

1
        final File open = new File("PicDic.exe");
        if (open.exists() == true) {
            if (Desktop.isDesktopSupported()) {
                javax.swing.SwingUtilities.invokeLater(new Runnable() {

                    public void run() {
                        try {
                            Desktop.getDesktop().open(open);
                        } catch (IOException ex) {
                            return;
                        }
                    }
                });

                javax.swing.SwingUtilities.invokeLater(new Runnable() {

                    public void run() {
                        //DocumentEditorView.this.getFrame().dispose();
                        System.exit(0);
                    }

                });
            } else {
                JOptionPane.showMessageDialog(this.getFrame(), "Desktop is not support to open editor\n You should try manualy");
            }
        } else {
            JOptionPane.showMessageDialog(this.getFrame(), "PicDic.exe is not found");
        }

//您可以使用它启动其他应用程序,并将整个项目分割为多个应用程序。它会发挥很大的作用


0
在调用打开新窗口的方法后立即调用下面的方法,这将关闭当前窗口。
private void close(){
    WindowEvent windowEventClosing = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
    Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(windowEventClosing);
}

同时在JFrame的属性中,确保defaultCloseOperation被设置为DISPOSE


0

您可以隐藏包含您想要在另一个JFrame上的Swing控件的JFrame的一部分。

当用户单击Jbutton时,JFrame的宽度会增加,当他单击另一个相同类型的Jbutton时,JFrame返回默认大小。

  JFrame myFrame = new JFrame("");
  JButton button1 = new JButton("Basic");
  JButton button2 = new JButton("More options");
 // actionPerformed block code for button1 (Default size)  
 myFrame.setSize(400, 400);
//  actionPerformed block code for button2 (Increase width)
 myFrame.setSize(600, 400);

0

使用 this.dispose 关闭当前窗口,使用 next_window.setVisible(true) 在按钮属性 ActionPerformed 后显示下一个窗口,以下为示例图片以供参考。

enter image description here


确保您先编写this.dispose(),然后再打开下一个JFrame - Mustajeeb ur Rehman

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