使用 ActionListener 按钮单击以隐藏一个 JFrame 并显示另一个时出错

Error when using ActionListener button click to hide a JFrame and reveal another

我正在尝试在单击按钮(在本例中为尺寸按钮)时“打开”另一个 JFrame window,就像浏览菜单时一样。我的 2 windows、Main 函数和 ActionListener 是分开的 类。当我单击应该将我重定向到另一个 window 的按钮时,它只是显示一个错误,并没有隐藏第一个 window 并显示第二个。错误是:

"Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: class javax.swing.JButton cannot be cast to class javax.swing.JFrame (javax.swing.JButton and javax.swing.JFrame are in module java.desktop of loader 'bootstrap') at ActionDimensions.actionPerformed(ActionDimensions.java:8) at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972) at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2313) at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405) at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262) at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279) at java.desktop/java.awt.Component.processMouseEvent(Component.java:6626) at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3389) at java.desktop/java.awt.Component.processEvent(Component.java:6391) at java.desktop/java.awt.Container.processEvent(Container.java:2266) at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5001) at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324) at java.desktop/java.awt.Component.dispatchEvent(Component.java:4833) at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948) at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4575) at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516) at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310) at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780) at java.desktop/java.awt.Component.dispatchEvent(Component.java:4833) at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:773) at java.desktop/java.awt.EventQueue.run(EventQueue.java:722) at java.desktop/java.awt.EventQueue.run(EventQueue.java:716) at java.base/java.security.AccessController.doPrivileged(AccessController.java:399) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97) at java.desktop/java.awt.EventQueue.run(EventQueue.java:746) at java.desktop/java.awt.EventQueue.run(EventQueue.java:744) at java.base/java.security.AccessController.doPrivileged(AccessController.java:399) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:743) at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203) at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124) at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90) "

第一个window:

public class MainMenu extends JFrame {
   public MainMenu(){
       setSize(300,600);
       JPanel center = new JPanel();
       center.setLayout(new GridLayout(3,1));
       JButton MainMenuButtonStart = new JButton("Start");
       JButton MainMenuButtonContinue = new JButton("Continue");
       JButton MainMenuButtonDimensions = new JButton("Dimensions");
       center.add(MainMenuButtonStart);
       center.add(MainMenuButtonContinue);
       center.add(MainMenuButtonDimensions);
       ActionDimensions actionDimensions = new ActionDimensions();
       MainMenuButtonDimensions.addActionListener(actionDimensions);
       add(center, BorderLayout.CENTER);

   }
}

第二个window:

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

public class Dimensions extends JFrame {
   public Dimensions(){
       setSize(600,500);
       JPanel north = new JPanel();
       JLabel labelnorth = new JLabel("Enter Dimensions! Rows and Columns");
       north.add(labelnorth);
       JPanel center = new JPanel();
       JPanel south = new JPanel();
       JButton buttonsouth = new JButton("Return to Main Menu");
       south.add(buttonsouth);
       center.setLayout(new GridLayout(1,2));
       TextField rowtextfield = new TextField();
       TextField columntextfield = new TextField();
       center.add(rowtextfield);
       center.add(columntextfield);
       add(north,BorderLayout.NORTH);
       add(center,BorderLayout.CENTER);
       add(south,BorderLayout.SOUTH);

主要功能:

public class Main {
   public static void main(String[] args) {
       MainMenu mainMenu = new MainMenu();
       Dimensions dimensions = new Dimensions();
       dimensions.setVisible(false);
       mainMenu.setVisible(true);
       mainMenu.setDefaultCloseOperation(3);

   }
}

动作侦听器:

public class ActionDimensions implements ActionListener {
   @Override
   public void actionPerformed(ActionEvent e) {
   JFrame mainMenu = (JFrame) e.getSource();
   JFrame dimensions = (JFrame) e.getSource();
   mainMenu.setVisible(false);
   dimensions.setVisible(true);
   }
}

我认为问题是我试图通过框架使用 getsource() 方法,但如果我不指定该方法,我将无法访问实例(主菜单和维度)。如果是这样,还有什么其他方法可以将 setVisible 方法连接到 ActionListener 内的实例?

这可能是您的问题:

JFrame mainMenu = (JFrame) e.getSource();
JFrame dimensions = (JFrame) e.getSource();

ActionEvent#getSource() 方法 return 是触发操作的 来源 ,这里是一个 JButton,您正在尝试投射 相同 JButton 对象 return 从这个方法中作为两个不同的 JFrames 编辑,这真的没有多大意义,因为,再一次,这个方法没有't return 一个 JFrame,其次,转换不会将一个对象转换为两个不同的对象。如果您需要对 JFrame 的引用,请将其传递到需要的位置,例如为您的 ActionListener class 提供一个采用 JFrame 参数的构造函数:

ActionDimensions actionDimensions = new ActionDimensions(this);

public class ActionDimensions implements ActionListener {
    private  MainMenu mainMenu;
    
    public ActionDimensions(MainMenu mainMenu) {
        this.mainMenu = mainMenu;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // JFrame mainMenu = (JFrame) e.getSource();
        // JFrame dimensions = (JFrame) e.getSource();
        mainMenu.setVisible(false);
        
        // create a new Dimensions JFrame here?
        Dimensions dimensions = new Dimensions();
        // .... other code
        
        dimensions.setVisible(true);
    }
}

或者,您可以通过调用 SwingUtilities.getWindowAncestor(yourJButton).

获取按钮所在的 JFrame

话虽如此,但要明白没有用户会喜欢有多个 windows 推向他们,这就是交换 JFrames 所做的,并且有更好的方法来干净地交换视图,例如使用CardLayout tutorial. Please read The Use of Multiple JFrames, Good/Bad Practice?.