如何通过点击JButton来添加JPanel?

2024-04-02

我正在尝试创建一个小型 GUI,它有 2 个 JButtons 和 2 个 JPanels,每个 JPanels 上都有一些绘图动画。默认情况下,它必须显示第一个 JPanel,通过单击第二个 JButton,我想看到第二个 JPanel。所以:我创建 JFrame、Panel1 和 Panel2,在其中绘制动画,创建 Button1 和 Button2 并向它们添加 ActionListener。我还有 MainPanel,其中有一个字段变量 i。通过更改此“i”,我的构造函数将 Panel1(默认)或 Panel2 添加到 MainPanel(通过单击 JButton2,我更改 i)。然后我将此 MainPanel 添加到我的框架中。所以我的问题是:在 MainPanel 类中我有刷新方法,我应该在那里写什么以使我的 GUI 正常工作?谢谢。这是我的代码:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

public class GuiTest {

    public static void main(String[] args) {
        JFrame f = new JFrame();
        MainPanel myPanel = new MainPanel();
        f.add(myPanel);
        Button1 button1 = new Button1();
        Button2 button2 = new Button2();
        myPanel.add(button1);
        myPanel.add(button2);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.pack();
        f.setVisible(true);
    }
}

class MainPanel extends JPanel {
    Panel1 p1 = new Panel1();
    Panel2 p2 = new Panel2();
    public int i = 1;  //this is being changed later by clicking JButton
    // I use this setter later in actionPerformed in order to change i
    public void setI(int i) {
        this.i = i;
    }

    MainPanel() { 
        if (i == 1) {
            this.add(p1);
        }
        if (i == 2) {
            this.add(p2);
        }
    }

    public void refreshMe() {
        // Need some help here:
        // I don't know what should I write, how to make a repaint of myPanel?
        System.out.println("just test, if the method refreshMe working by clicking some button");
    }
}

class Panel1 extends JPanel {

    public Panel1() {
        this.setBackground(Color.BLUE);
        // a lot of drawing stuff going on here
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(200, 200);
    }
}

class Panel2 extends JPanel {

    public Panel2() {
        this.setBackground(Color.GREEN);
        // a lot of drawing stuff going on here
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(200, 200);
    }

}

class Button1 extends JButton {
    MainPanel someObj1 = new MainPanel();

    Button1() {
        setText("Show Annimation A");
        addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                someObj1.setI(1);
                System.out.println("The variable i is now: " + someObj1.i);
                someObj1.refreshMe();

            }
        });
    }

}

class Button2 extends JButton {
    MainPanel someObj2 = new MainPanel();

    Button2() {
        setText("Show Annimation B");
        addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                someObj2.setI(2);
                System.out.println("The variable i is now: " + someObj2.i);
                someObj2.refreshMe();
            }
        });

    }

}

为了反映添加/删除或调整可见容器调用上的组件大小后的更改revalidate() and repaint()添加/删除组件或调整组件大小后在容器实例上。

虽然这在您的代码中不起作用,主要原因是在 JButton 类中您重新创建了一个新实例MainPanel事实上 2JButtons应该共享正在使用的单个实例(您可以将 MainPanel 实例传递给JButtons 构造函数,但你不应该真正扩展JButton除非添加自定义功能):

class Button2 extends JButton {
    MainPanel someObj2 = new MainPanel();//you create an instance of MainPanel which isnt even showing and than do changes on that, this way you will never see any of the changes

    Button2() {
    }
}

关于您的代码的一些其他建议:

  • 不要延长JButton不需要类,只需创建一个实例JButton就像你做的那样JFrame并调用方法JButton实例。

  • 不要忘记创建/操作 Swing 组件Event Dispatch Thread, via SwingUtilities.invokeLater(..)阻止、读取here http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html了解更多。

这是您的固定代码(已实施上述建议等):

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

public class Test {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame f = new JFrame();

                final MainPanel myPanel = new MainPanel();
                f.add(myPanel);

                JButton button1 = new JButton("Show Animation A");
                JButton button2 = new JButton("Show Animation B");

                button1.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        myPanel.setI(1);
                        System.out.println("The variable i is now: " + myPanel.i);
                        myPanel.refreshMe();
                    }
                });
                button2.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        myPanel.setI(2);
                        System.out.println("The variable i is now: " + myPanel.i);
                        myPanel.refreshMe();
                    }
                });

                myPanel.add(button1);
                myPanel.add(button2);
                myPanel.checkPanel();

                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                f.pack();
                f.setVisible(true);
            }
        });
    }
}

class MainPanel extends JPanel {

    Panel1 p1 = new Panel1();
    Panel2 p2 = new Panel2();
    public int i = 1;  //this is being changed later by clicking JButton
    // I use this setter later in actionPerformed in order to change i

    public void setI(int i) {
        this.i = i;
    }

    public void refreshMe() {
        checkPanel();

        revalidate();
        repaint();
        // Need some help here:
        // I don't know what should I write, how to make a repaint of myPanel?
        System.out.println("just test, if the method refreshMe working by clicking some button");
    }

    public void checkPanel() {
        if (i == 1) {
            this.add(p1);
            this.remove(p2);//or it will remain there as this is default flowlayout
        } else if (i == 2) {
            this.add(p2);
            this.remove(p1);
        }
    }
}

class Panel1 extends JPanel {

    public Panel1() {
        this.setBackground(Color.BLUE);
        // a lot of drawing stuff going on here
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(200, 200);
    }
}

class Panel2 extends JPanel {

    public Panel2() {
        this.setBackground(Color.GREEN);
        // a lot of drawing stuff going on here
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(200, 200);
    }
}

不过我建议更简单的方法,幸运的是你有两个选择:

1) Use CardLayout http://docs.oracle.com/javase/tutorial/uiswing/layout/card.html这将允许您在单个组件上的多个组件之间切换JFrame/容器。

这是我做的一个例子:

import java.awt.BorderLayout;
import java.awt.CardLayout;
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.SwingUtilities;

public class Test {

    private final static String PANEL1 = "panel 1";
    private final static String PANEL2 = "panel 2";

    public Test() {
        initComponents();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Test();
            }
        });
    }

    private void initComponents() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel1 = new JPanel();
        panel1.add(new JLabel("Panel 1"));

        JPanel panel2 = new JPanel();
        panel2.add(new JLabel("Panel 2"));

        //Create the panel that contains the "cards".
        final JPanel cards = new JPanel(new CardLayout());
        cards.add(panel1, PANEL1);
        cards.add(panel2, PANEL2);

        //create button to allow chnage to next card
        JButton buttonNext = new JButton(">");
        buttonNext.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                CardLayout cl = (CardLayout) (cards.getLayout());//get cards
                cl.next(cards);
            }
        });

        //create button to allow chnage to previous card
        JButton buttonPrev = new JButton("<");
        buttonPrev.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                CardLayout cl = (CardLayout) (cards.getLayout());//get cards
                cl.previous(cards);
            }
        });

        //create panel to hold buttons which will allow switching between cards
        JPanel buttonPanel = new JPanel();
        buttonPanel.add(buttonPrev);
        buttonPanel.add(buttonNext);


        frame.add(cards);
        frame.add(buttonPanel, BorderLayout.SOUTH);

        frame.pack();
        frame.setVisible(true);
    }
}

2) Use removeAll()技术,即调用frame.getContentPane().removeAll()这将删除当前的所有组件JFrame然后添加新内容并调用revalidate() and repaint()(也可能想添加pack()在那里)在JFrame实例来反映变化。虽然我推荐CardLayout.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何通过点击JButton来添加JPanel? 的相关文章

随机推荐

  • pycurl 相当于“curl --data-binary”

    我想知道 pycurl 中这个curl命令的等效项 curl data binary binary data file bin http server myapp method 注意 上面的curl语句使用了POST方法 我需要使用它来与我
  • 无法加载参考程序集以供执行

    突然我的网站无法加载并给出以下错误 我在 Windows 10 Home 上运行带有 Net Framework 4 7 1 的 VS2017 BadImageFormatException Cannot load a reference
  • “docker images”显示图像,“docker rmi”表示“没有这样的图像”或“引用不存在”

    由于某些原因我无法删除 docker 镜像 这是输出 操作系统版本 Linux localhost localdomain 4 12 13 300 fc26 x86 64 1 SMP Thu Sep 14 16 00 38 UTC 2017
  • django 模型中的星期几表示

    我正在构建这个 作业服务器 模型 我想添加一个字段来保存该作业将在一周中的哪几天运行 最终在用户界面中 我希望用户能够拥有一系列可以选择的复选框 每天一个 在我的模式中表示 一周中的几天 数据的最佳方式是什么 class Job model
  • 如何设置Robots.txt或Apache仅在特定时间允许爬虫?

    由于 24 小时内流量分布不均匀 我希望在高峰时段禁止爬虫 在非繁忙时段允许爬虫 有没有一种方法可以实现这一目标 编辑 感谢所有的好建议 这是我们找到的另一个解决方案 2bits com 有一篇关于设置 IPTables 防火墙以限制来自某
  • 更新 appSettings 外部 web.config 中的变量

    我需要更新 Azure TFS 中 web config 中的值 我能够获取连接字符串替换的值 该值是 appSettings 的一部分 为此 我需要启用名为 XML 变量替换的设置 在 IIS Web 部署下 但是 web config
  • 字符显示/搜索 Unicode 字符

    在回答另一个问题时question https stackoverflow com q 18686199 418556关于这些部分 我对系统上可用字体显示的 Unicode 字符可能获得的字形感到好奇 当然 典型的机器上有 65 536 个
  • 无法通过ajax将javascript对象传递给php

    我在 javascript 中创建了一个新数组 我从一个函数向其索引添加值 然后将数组传递给 ajaxCall 函数 如果我尝试将其转换为 json 并通过 ajax 将其发送到 php 文件 但是变量 json 始终为空 我已经阅读了很多
  • 恢复小备份时磁盘空间不足

    我正在尝试从 32MB 备份恢复数据库 我的磁盘上有 6GB 可用空间 当我尝试恢复备份时 它显示磁盘空间不足错误 32MB 的备份怎么可能需要超过 6GB 的磁盘空间 可能是因为备份被压缩 或者因为有一个非常大的日志文件不需要成为备份本身
  • UIScrollView - (bounces = NO) 似乎覆盖 (pagingEnabled = YES)

    我有一个带有分页功能的 UIScrollView 因此带有 UIPageControl 并在页面之间左右拖动 轻拂的典型模型 并且我的工作正常 奇怪的是 当我想摆脱弹跳 这样就看不到左右两侧UI后面的黑色 时 突然分页不再起作用了 换句话说
  • 在 Storyboard 中实现视频视图

    我想构建简单的视频应用程序 可以查看用户添加的 YouTube 链接中的视频 我没有找到 VideoView 我的意思是如果图像视图用于图像 那么 UIView 用于视频 原库中没有执行视频观看功能的对象 但你可以导入MediaPlayer
  • 如何在 Python BaseHTTPRequestHandler 中处理分块编码?

    我有以下简单的 Web 服务器 利用 Pythonhttp module import http server import hashlib class RequestHandler http server BaseHTTPRequestH
  • 为什么选择 XML 而不是属性文件来进行 Log4J 配置?

    是否有任何理由在 Log4J 配置中使用 XML 而不是属性文件 有一个有趣的讨论这篇博客中两者的优点 http www laliluna de log4j tutorial html 以下部分摘自该博客 属性可以由属性文件或 XML 文件
  • fortran 77 到 fortran 90 的转换器软件 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有 fortran 77 编码 但我想转换为 fortran 90 在哪里可以下载转换器软件 这是我帮
  • Pandas json_normalize 因 JSON 中的空值而失败

    我有以下从外部网络服务获得的 json text id 1 name abc address flat 123 city paris street null error null 现在我想从这个 json 创建数据框 当我尝试下面时 fro
  • 无法解析模块ReactNativeEventEmitter

    将 React Native 从 0 29 升级到 0 30 后 我收到此错误消息 我多次删除了node modules 然后再次安装它们 清除了watchman缓存并npm start reset cache 我也在新项目上尝试过使用re
  • 将日期传递给 package.json 脚本

    我有一个正在尝试设置的部署脚本 我正在尝试将名为 DEPLOY DATE 的环境变量设置为等于现在 scripts deploy kubectl set env deploy api DEPLOY DATE date 问题是这只是将 DEP
  • 在linux中找不到syscall_table_32.S文件

    我正在使用linux headers 2 6 32 21虚拟机上的包 我要编写一个新的系统调用 我找到了其他文件来写入系统调用的缩写 但我找不到这个syscall table 32 S in arch x86 kernel 目录 请帮助我如
  • 将日期 yyyyMMdd 转换为 system.datetime 格式[重复]

    这个问题在这里已经有答案了 可能的重复 如何将日期从 yyyyMMdd 格式转换为 mm dd yyyy 格式 https stackoverflow com questions 4712335 how to convert date fr
  • 如何通过点击JButton来添加JPanel?

    我正在尝试创建一个小型 GUI 它有 2 个 JButtons 和 2 个 JPanels 每个 JPanels 上都有一些绘图动画 默认情况下 它必须显示第一个 JPanel 通过单击第二个 JButton 我想看到第二个 JPanel