【问题标题】:How to update components listening a button in java如何更新在java中监听按钮的组件
【发布时间】:2020-05-07 16:04:16
【问题描述】:

有点不好意思问这个问题,因为好像有点明显,但是我一个人找不到解决办法。

我正在用 Java 编写一个小应用程序,但在“重绘”我的挥杆组件时遇到了一些问题。基本上,我希望我的JFrame 在事件发生时更新。我设法在下面的代码中重现了这个问题。这段代码应该显示两个按钮(它确实如此),并在您单击第一个按钮时将它们替换为第三个按钮(它没有)。

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

public class Example extends JFrame implements ActionListener {

    private JButton button = new JButton("Button 1");
    private JButton button2 = new JButton("Button 2");
    private JButton button3 = new JButton("Button 3");
    private JPanel buttons = new JPanel();

    public void init() {
        this.setVisible(true);
        this.setSize(500,500);
        buttons.add(button);
        buttons.add(button2);
        this.add(buttons);
        this.button.addActionListener(this);
    }

    public void update() {
        this.removeAll();
        buttons.add(button3);
        this.revalidate();
    }

    public static void main(String[] args) {
        Example ex = new Example();
        ex.init();
    }

    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == button) {
            update();
        }
    }
}

我很确定我在 update() 方法中做错了什么。实际上,我很难理解removeAll()revalidate()repaint() 等的工作原理,我想这就是问题所在。我尝试在buttons 面板上调用相同的方法,它几乎可以工作,但我仍然有一个图形错误,我想对所有容器都这样做。我也尝试在this.getContentPane() 上调用这些方法,但它不起作用。

有人可以帮我解决吗?

【问题讨论】:

    标签: java swing jbutton actionlistener repaint


    【解决方案1】:

    您正在从 this 中删除所有组件(在这种情况下是 JFrame (因为您正在扩展它,这不是必需的,而是您应该从它创建一个实例而不是从它继承它,因为您没有更改 JFrame 的行为,所以最好只创建它的实例)。请参阅:Extends JFrame vs. creating it inside the program

    在这种情况下,您以这种方式添加组件:

    JFrame > buttons (JPanel) > JButtons
    

    你正在尝试删除

    JFrame > everything
    

    这包括 contentPane,而不是你应该调用。

    buttons.removeAll()
    

    update() 方法内部。

    并且还调用this.repaint() 所以你的update() 方法应该变成:

    public void update() {
        buttons.removeAll();
        buttons.add(button3);
        this.revalidate();
        this.repaint();
    }
    

    或者最好的方法是使用@AndrewThompson 在下面的评论中推荐的CardLayout。这样您就不必为每个组件处理删除/重新绘制,因为 CardLayout 会为您完成。对于example

    【讨论】:

    • ".. 而你应该.." 使用CardLayout,因为它是为这种情况设计的。
    • 你说得对@AndrewThompson 我忘了提到卡片布局,在我的脑海中我正在考虑它,然后忘了提到它。
    • “我在想,后来忘了说” 嗯,有道理。老实说,我非常重视你的经历,以至于没有提到它,但“忘记”完美地解释了它。我经常这样做,只有在几小时后(长达数年)回到答案时,我才发现遗漏。或者当有人用类似 “What about..?” ;) 的字眼提示我们时
    • 我没有你,MadProgrammer,Hovercraft 或许多其他 Swing 方面的经验丰富,我的大部分知识来自于在 Swing 中回答问题,但被像你这样的人认可让我流下了喜悦的泪水:') 再次感谢您指出
    • 非常感谢您的回答。我实际上简化了一点我的问题,所以我不确定 CardLayout 是否会成为我的解决方案,但我认为我现在应该可以了。尽管如此,我还是不太明白:如果我在“按钮”面板上调用 removeAll,为什么我不能也调用 revalidate 呢?另外,我不明白为什么我们需要重新验证和重新绘制,但这是很多问题,也许下次......
    【解决方案2】:

    这行得通,

    public void update() {
        buttons.remove(button);
        buttons.remove(button2);
        buttons.add(button3);
        this.revalidate();
        this.repaint();
    }
    

    【讨论】:

      猜你喜欢
      • 2021-04-19
      • 1970-01-01
      • 2015-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多