【问题标题】:How to use an ActionListener to make a JPanel Visible如何使用 ActionListener 使 JPanel 可见
【发布时间】:2021-05-03 14:56:08
【问题描述】:

我试图通过单击 JButton 使第一个 JPanel 消失而使第二个 JPanel 可见。 到目前为止,我只显示了第一个 JPanel,单击 JButton 后,框架为空。 我也尝试用作文来做,所以我不必扩展课程。所以我对如何 作曲作品可能是问题所在。我研究了很多,但找不到适合我的问题的解决方案。

第一个 JPanel 类:

import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;

public class Panel1 {

JPanel firstscreenpanel = new JPanel();
JButton jButton1 = new JButton();
    
Panel1() {
    
    jButton1.setBounds(300,300,400,200);
    jButton1.setBackground(Color.BLACK);
    jButton1.setVisible(true);
    jButton1.addActionListener(new ActionListener() {

    Panel2 test = new Panel2();
            
    public void actionPerformed(ActionEvent e) {
            
        
            firstscreenpanel.setVisible(false); 
            test.secondscreenpanel.setVisible(true);
            
            
            }
    });
    
    
}

public Component panelone() {
    
    firstscreenpanel.setSize(1280, 1024);
    firstscreenpanel.setLayout(null);
    firstscreenpanel.setBackground(Color.BLUE);
    firstscreenpanel.add(jButton1);
    firstscreenpanel.setVisible(true);
    return firstscreenpanel;
            
    }

}

第二个 JPanel 类:

import java.awt.Color;
import java.awt.Component;
import javax.swing.JButton;
import javax.swing.JPanel;

public class Panel2 {

public JPanel secondscreenpanel = new JPanel();
public JButton jButton2 = new JButton();



Panel2() {
    
    jButton2.setBounds(100,100,400,200);
    jButton2.setBackground(Color.BLACK);
    jButton2.setVisible(true);
            
}
    
public Component paneltwo() {
    
    secondscreenpanel.setSize(1280, 1024);
    secondscreenpanel.setLayout(null);
    secondscreenpanel.add(jButton2);
    secondscreenpanel.setBackground(Color.RED);
    secondscreenpanel.setVisible(false);
    return secondscreenpanel;
            
    }
    }

JFrame 类:

import javax.swing.JFrame;

public class Frame1 {


public JFrame frame1 = new JFrame();
Panel1 panel1 = new Panel1();
Panel2 panel2 = new Panel2();

Frame1() {
    
    frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame1.setState(JFrame.MAXIMIZED_BOTH);
    frame1.setSize(1280, 1024);
    frame1.setLayout(null);
    frame1.add(panel1.panelone());
    frame1.add(panel2.paneltwo());
    frame1.setVisible(true);
    
            
    }
    }

主类:

    public class MainClass {

        
    private void showGUI() {

    Frame1 jframe = new Frame1();
                        
    }
    
    public static void main(String[] args) {
        
        final MainClass main = new MainClass();
        
        javax.swing.SwingUtilities.invokeLater(new Runnable()

          {
            public void run() {
                main.showGUI();

            }
        
         });
        
      }

        }

【问题讨论】:

  • 我认为问题在于您正在创建一个新的 Panel2 对象并且您没有使用原始 JFrame 中的对象。您可能应该将 JFrame 的引用传递给您的 panel1,以便您可以使用引用的 Jframe 中的 jpanel2
  • 我真的不明白如何传递我的 JFrame hm 的引用。
  • 您的 JPanel 中应该有一个 JFrame,然后您可以在创建 JPanel 时将 JFrame 传递给您的 JPanel 的构造函数。
  • 使用CardLayout,如this answer所示。

标签: java swing jpanel jbutton actionlistener


【解决方案1】:

我没有检查整个代码(bug 太多,empty 行太多)但停在Panel2 test = new Panel2();

这个实例是否被添加到某个可见组件中?如果不是,它将永远不会显示。

注意:通常不建议使用null 布局管理器,使用CardLayout 甚至JTabbedPane 来切换组件 - 参见教程A Visual Guide to Layout Managers

【讨论】:

  • 你也许就是问题所在。我这样做是因为我认为我需要这样做才能访问 actionlistener 中的第二个面板。
  • new .... 正在创建一个新实例,无助于访问另一个实例。或者在构造函数中传递实例(不太好),或者使用监听器(更好?),或者正确的组件(参见答案中的注释)
  • 好吧,我会研究 CardLayout 并希望我能解决我的问题。谢谢你的帮助:)
【解决方案2】:

这不是最好的实现,但它足够简单,您可以遵循。我修改了您的代码以创建一个包含原始两个面板的框架(尽管这些面板类不是必需的 - 正如我在您发布的解决方案的评论中所解释的那样),以及一个用于切换面板可见性的按钮。我使用的是普通的 JButton 而不是 JToggleButton 也不是该类的最佳用途,只是为了让您理解。

动作监听器被添加到框架上的按钮中。请注意,我的动作侦听器不会创建任何新实例。那是原始问题的一部分。由于按钮与面板 1 和 2 一样是框架类的成员,因此它可以直接访问它们。所以,在监听器中,我需要做的就是“切换”每个面板的可见性。

public class Frame1 extends JFrame {
    private Panel1 panel1 = new Panel1();
    private Panel2 panel2 = new Panel2();
    private JPanel btnPanel = new JPanel();
    private JButton button = new JButton("Toggle");

    public Frame1() {
    
        button.addActionListener(new ActionListener() {
        
            @Override
            public void actionPerformed(ActionEvent arg0) {
                boolean visible = panel1.isVisible();
                panel1.setVisible(!visible);
                panel2.setVisible(visible);
            
            }
        });

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setState(JFrame.MAXIMIZED_BOTH);
        setSize(1280, 1024);
        btnPanel.setSize(400, 100);
        btnPanel.add(button);
        setLayout(null);
        add(panel1);
        add(panel2);
        add(btnPanel);
    }
}

public class Panel1 extends JPanel {

    public Panel1() {
        setBounds(100,100,400,200);
        setBackground(Color.RED);
        setVisible(true);
    }
}

public class Panel2 extends JPanel {

    public Panel2() {
        setBounds(100,100,400,200);
        setBackground(Color.BLACK);
        setVisible(false);
    }
}

public class MainClass {

    private void showGUI() {

        Frame1 jframe = new Frame1();
        jframe.setVisible(true);
    }

    public static void main(String[] args) {

        final MainClass main = new MainClass();
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                main.showGUI();

            }

        });
    }
}

【讨论】:

  • 感谢您的解决方案,它绝对有帮助。我想我只是有点困惑,因为我在这里读到的大多数关于如何组织 GUI 项目的建议都说我不应该扩展类。他们说主要使用组合并且仅在罕见的覆盖情况下使用扩展类(继承)。他们还建议为每个 JPanel 创建一个类,并将该 JPanel 的所有组件放入其中。另外我的项目有很多 JButtons 和 ActionListener 所以我想把它们放到 JFrame 类中会让这个类变得非常大,我想避免,因为我以前做过。
  • 对...在此示例中,您不需要Panel1Panel2。您可以简单地使用JPanel 的两个实例来做同样的事情,就像我在按钮面板中使用JPanel 一样。不需要类的一个指标是在我发布的示例中查看这两个类的“空”程度。层次结构中的一个新类应该实现新的行为。相反,这些面板类没有添加任何内容(没有新方法)。子类应该是其父类的更特殊形式。例如,JPanelJComponent 的更特殊形式。你现在明白了吗?
  • 作为一个java初学者来表达自己太粗糙了。我很抱歉。但我明白你所说的这些 JPanel 类是不需要的,因为它们可以像你对​​ btnpanel 所做的那样处理。我只是担心,因为如果我不明白如何不将我的大部分组件放在 JFrame 类中并且仍然连接它们,那么我最终会再次得到一个巨大的类。我想我很讨厌解释我的问题我很抱歉
  • 这是来自 Java Oracle 的教程,我认为您应该阅读 docs.oracle.com/javase/tutorial/uiswing。它将涵盖使用 Java Swing 构建简单 GUI 所需了解的基础知识。
  • 另外,如果我的答案是您想要的,如果您将其标记为这样,我将不胜感激。
【解决方案3】:

您可以通过将框架的引用传递给您的 panel1 来修复您的程序。请参阅下面的示例。

框架类

import javax.swing.*;

public class Frame1 {

    private JFrame frame = new JFrame();
    private Panel1 panel1;
    private Panel2 panel2;

    Frame1() {
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.setState(JFrame.MAXIMIZED_BOTH);
         frame.setSize(1280, 1024);
         frame.setLayout(null);
         panel1 = new Panel1(this);
         frame.add(panel1.getPanel());
         panel2 = new Panel2();
         frame.add(panel2.getPanel());
         frame.setVisible(true);
    }

    public Panel2 getPanel2() {
        return panel2;
    }

}

Panel1 类

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

public class Panel1 {
    private JPanel panel = new JPanel();
    private Frame1 frame1;
    private JButton jButton1 = new JButton();

    public Panel1(Frame1 frame1) {
        this.frame1 = frame1;
        panel.setSize(1280, 1024);
        panel.setLayout(null);
        panel.setBackground(Color.BLUE);
        panel.add(jButton1);
        panel.setVisible(true);
        jButton1.setBounds(300,300,400,200);
        jButton1.setBackground(Color.BLACK);
        jButton1.setVisible(true);
        jButton1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                panel.setVisible(false);
                frame1.getPanel2().getPanel().setVisible(true);
            }
        });
    }

    public JPanel getPanel() {
         return panel;
    }
}

Panel2 类

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

public class Panel2 {
     private JButton jButton2 = new JButton();
     private JPanel panel = new JPanel();

    public Panel2() {
        panel.setSize(1280, 1024);
        panel.setLayout(null);
        panel.add(jButton2);
        panel.setBackground(Color.RED);
        panel.setVisible(false);

        jButton2.setBounds(100,100,400,200);
        jButton2.setBackground(Color.BLACK);
        jButton2.setVisible(true);
    }

    public JPanel getPanel() {
        return panel;
    }
}

【讨论】:

  • 更改了我的答案以删除任何扩展类
  • 非常感谢,这正是我正在寻找的!
【解决方案4】:

我通过将“public static”添加到“Panel2 panel2 = new Panel2();”解决了我的问题

然后我就用了:

"Frame1.panel2.secondscreenpanel.setVisible(true);"

在 JButton ActionListener 内部。

它现在可以工作,但我想那是一种不好的做法。因为我听说使用过多的静电并不是那么好。但我现在还不知道为什么。

【讨论】:

  • 你知道static 会员是什么吗?这意味着该成员在给定类的所有实例之间共享。这既不好也不坏。它的好坏在于它的适用性。考虑一个Car 类,它具有Engine 作为该类的成员。让所有汽车共享一个引擎 (static) 和只拥有相同的引擎(具有相同值的非静态)之间是有区别的。只有您可以确定具有 static 的字段对于您的特定要求是好是坏。
  • 对于您的具体问题,将panel2 设为static 成员似乎是个坏主意。
  • 为什么这是个坏主意?如果我坚持下去,以后会遇到什么问题?
  • 由于我在第一条评论中提到的原因,这是一个坏主意。我确定您不希望完全相同的“静态”面板出现在框架的所有不同实例中。此外,Panel1 和 Panel2 基本上是同一个类,但内部值不同。转到我的Car 示例,如果我需要一辆蓝色汽车和一辆红色汽车,我不需要创建两个类(即BlueCarRedCar)。我只是创建一个类并提供一种机制来创建不同颜色的实例。
  • 好吧,我明白了,那么我只需要学习如何正确地做到这一点。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-06
  • 1970-01-01
  • 2019-08-06
  • 1970-01-01
  • 2016-12-05
  • 1970-01-01
相关资源
最近更新 更多