如何在不退出应用程序的情况下处理 JFrame 并将其重新创建为新的?

How to dispose a JFrame and recreate it as new without exiting the application?

我有一个问题,我必须使用两个 JFrame,所以我们可以忘记 good/bad 练习。

既然我们已经过了这一点。

我的两个 JFrame

  1. LoginFrame
  2. MainFrame

我想从 MainFrame 注销到 LoginFrame,反之亦然。这样做时,我希望两个框架都能重新打开。 就像我们如何实例化它们一样,即

MainFrame.class

//on signout button event
new LoginFrame().setVisible(true);
dispose(); //it will dispose this frame and destroy its UI components and free resources etc etc.

同样,

LoginFrame.class

//on signin button event
new MainFrame().setVisible(true);
dispose(); //it will dispose this frame and destroy its UI components and free resources etc etc.

现在,这运行良好,但问题是我在 MainFrame 中有一个 keyDispatchEvent,它在我注销后登录(不关闭应用程序)执行了很多次。

我相信即使在处置之后,JFrame 它实际上并没有被处置。因此,当我键入任何快捷键时,先前处理的框架对象和 MainFrame 的新对象都在调度它们的事件。我怎样才能丢失(我的意思是真正处置)所有以前的对象,以便只为当前对象触发此事件?

MainFrame.class

final static KeyboardFocusManager keyManager=KeyboardFocusManager.getCurrentKeyboardFocusManager();

keyManager.addKeyEventDispatcher(new KeyEventDispatcher() 
{

        @Override
        public boolean dispatchKeyEvent(KeyEvent e) 
        {
           // if key is alt+r  
           {
               signout(); // getting called repeatedly on single key release 
           }
        }
});

我不想要的是使用相同的对象,因为它们会有以前的 state/information/changes。只想摆脱已处理的对象。

此外,在这种情况下,我必须使用 KeyboardManagerDispatchKeyEvent

我希望下面的代码能满足您的需求。因为你没有 post minimal, reproducible example I can only guess what you want from your [poor] problem description and your insistence on [your] way or the highway.

the problem is that I have a keyDispatchEvent in MainFrame which is executing a number of times I login after signout

我的猜测是,您不断将相同的 KeyEventDispatcher 添加到 KeyboardFocusManager,并且每添加一个都会执行。所以如果你把相同的KeyEventDispatcher加3次,它就会执行3次。我假设您只想添加一次,因此您需要在不再需要时将其删除。

我还假设当您启动应用程序时,您希望首先显示 LoginFrame。因此,我在下面的 class LoginFrame 中添加了一个 main 方法。

Class LoginFrame

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class LoginFrame extends JFrame implements ActionListener {

    public LoginFrame() {
        KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(MainFrame.ked);
        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
        JButton signin = new JButton("sign in");
        signin.addActionListener(this);
        JPanel panel = new JPanel();
        panel.add(signin);
        add(panel, BorderLayout.PAGE_END);
        pack();
        setLocationByPlatform(true);
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        new MainFrame().setVisible(true);
        dispose();
    }
    public static void main(String[] args) {
        EventQueue.invokeLater(() -> new LoginFrame().setVisible(true));
    }
}

Class MainFrame

import java.awt.BorderLayout;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MainFrame extends JFrame implements ActionListener {
    final static KeyboardFocusManager keyManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();

    private static boolean  done;
    static KeyEventDispatcher ked;

    public MainFrame() {
        keyManager.removeKeyEventDispatcher(ked);
        ked = new KeyEventDispatcher() {
            
            @Override
            public boolean dispatchKeyEvent(KeyEvent ke) {
                int key = ke.getKeyCode();
                int modifiers = ke.getModifiersEx();
                if (key == KeyEvent.VK_R  &&  (modifiers & KeyEvent.ALT_DOWN_MASK) == KeyEvent.ALT_DOWN_MASK) {
                    if (done) {
                        done = false;
                    }
                    else {
                        done = true;
                        actionPerformed(null);
                    }
                }
                return false;
            }
        };
        keyManager.addKeyEventDispatcher(ked);

        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
        JButton signout = new JButton("sign out");
        signout.addActionListener(this);
        JPanel panel = new JPanel();
        panel.add(signout);
        add(panel, BorderLayout.PAGE_END);
        pack();
        setLocationByPlatform(true);
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        new LoginFrame().setVisible(true);
        dispose();
    }
}

备注:

  • 我不知道为什么,但每次我在键盘上按下 Alt+R 时,事件调度程序都会触发两次。因此 done 标志。