为什么不重新绘制 JPanel 中的按钮?

Why doesnt repaint repaint the button in the JPanel?

我不明白 repaint();有效。

我试图寻找教程,但从未找到任何东西,'similar questions' 上的回答也没有真正帮助。

这是我可以编写的最基本的代码,它应该可以工作,但不能:

static String done = "0";

    public static void main(String[] args) {
        
        JFrame frame = new JFrame();
        frame.setResizable(false);
        JPanel panel = new JPanel();
        frame.setSize(800, 500);
        frame.setLocation(500, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        
        JButton end = new JButton(done);
        end.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                done += Integer.valueOf(1);
                panel.repaint();
            }
        });
        
        panel.add(ende);
        frame.add(panel);
        frame.setVisible(true);

    }

很明显,这只是一个按钮,点击数字+1 后应该重新绘制。

后续问题: 我如何告诉面板在另一个面板内重新绘制自己? 这是应该工作的基本代码:

import java.awt.Color;
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.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;

public class Repaint
{
    static String done = "0";
    
    public static void main(String[] args)
    {
        new Repaint();
        
    }
    
    public Repaint()
    {
        createframe();
        
    }
    
    public void createframe()
    {
        JFrame frame = new JFrame();
        frame.setResizable(false);
        JPanel panel = new JPanel();
        frame.setSize(800, 500);
        frame.setLocation(500, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        Border bo = new LineBorder(Color.black);
        JMenuBar bar = new JMenuBar();
        bar.setBorder(bo);
        JMenu menu = new JMenu("Edit");
        JMenuItem stats = new JMenuItem("Edit the button");
        
        stats.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ev)
            {
                
                createbox();
                
            }
        });
        menu.add(stats);
        
        JLabel end = new JLabel(done);
        
        bar.add(menu);
        frame.setJMenuBar(bar);
        panel.add(end);
        frame.add(panel);
        frame.setVisible(true);
        
    }
    
    public void createbox()
    {
        JFrame framebox = new JFrame();
        framebox.setResizable(false);
        JPanel panelbox = new JPanel();
        framebox.setSize(800, 500);
        framebox.setLocation(500, 400);
        
        JButton end = new JButton(done);
        
        end.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                done += String.valueOf(1);
                framebox.dispose();
            }
        });
        panelbox.add(end);
        framebox.add(panelbox);
        framebox.setVisible(true);
    }
    
}

基本上按下第 2 帧中的按钮会使字符串“完成”的数量增加 1。但是它不会在原始框架中重新绘制它。

如果想把JButton上的数字加1显示出来,就不用用repaint()方法了。

无关紧要。

相反,您可以使用 setText() 方法。

代码:

JButton end = new JButton(done);
end.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        done = done + "1";
        end.setText(done);
    }
});

repaint() method is related to Graphics/Graphics2D in Java. It is called when we want to change the look of a component.

好的,尽管我不完全确定你的程序要做什么,但我已经尝试解决你的两个问题。

首先,您接受的答案实际上是错误的。我猜其他评论者忘记了变量 done 实际上是 String 类型,这意味着运算符 += 实际上不做任何数学运算,它只是附加字符串。简而言之,运算符不会将 1 添加到 done,而是将文字字符串值 1 附加到 done。因此,如果 done 的值为 0 并且您单击具有该代码的按钮,它将附加 1,并且 done 现在将具有值 01。如果您再次单击它,它将构建 String 011 等等。

要修复这个小错误,您只需将 String 解析为 Integer,然后您就可以在其上使用数学运算符。

关于你的第二个问题,我重新阅读了你的问题和你的代码,现在看来我在对另一个答案的评论中误解了。我试图不改变你的代码的底层逻辑,因此离开了你的关于 JButton 做什么的代码。在您的原始代码中,按钮递增 done 并且按钮应该显示该文本。不过,该按钮也是此框架的关闭操作,因为您在按钮的 actionPerformed() 调用中调用了 dispose()

如果这是应该发生的事情(每次按下按钮关闭框架),那么你甚至不需要 WindowListener 或覆盖任何东西,你可以简单地执行你想要的任何东西 actionPerformed()打电话。

代码:

public class Repaint
{
    String done = "0";
    
    JFrame frame;
    JPanel panel;
    Border bo;
    JMenuBar bar;
    JMenu menu;
    JMenuItem stats;
    JLabel endLabel;
    
    JFrame framebox;
    JPanel panelbox;
    JButton endButton;
    
    public static void main(String[] args)
    {
        new Repaint();
        
    }
    
    public Repaint()
    {
        createFrame();
    }
    
    public void createFrame()
    {
        frame = new JFrame();
        frame.setResizable(false);
        panel = new JPanel();
        frame.setSize(800, 500);
        frame.setLocation(500, 400);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        
        bo = new LineBorder(Color.black);
        bar = new JMenuBar();
        bar.setBorder(bo);
        menu = new JMenu("Edit");
        stats = new JMenuItem("Edit the button");
        
        stats.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent ev)
            {
                
                createBox();
                
            }
        });
        menu.add(stats);
        
        endLabel = new JLabel(done);
        
        bar.add(menu);
        frame.setJMenuBar(bar);
        panel.add(endLabel);
        frame.add(panel);
        frame.setVisible(true);
        
    }
    
    public void createBox()
    {
        framebox = new JFrame();
        framebox.setResizable(false);
        panelbox = new JPanel();
        framebox.setSize(800, 500);
        framebox.setLocation(500, 400);
        
        endButton = new JButton(done);
        
        endButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                done = Integer.toString(Integer.parseInt(done) + 1);
                endButton.setText(done);
                onDispose();
            }
        });
        panelbox.add(endButton);
        framebox.add(panelbox);
        framebox.setVisible(true);
    }
    
    private void onDispose() 
    {
        endLabel.setText(done);
        framebox.dispose();
    }
}

我最终用 class 变量替换了你所有的局部变量(也许你不需要所有它们都是非局部的,但无论如何)所以你实际上可以调用 JFramecreateFrame() 方法之外的实例 frame

您可以看到 toString()parseInt() 的调用实际让数学运算符起作用。

endButton.addActionListener(new ActionListener()
{
    @Override
    public void actionPerformed(ActionEvent e)
    {
        done = Integer.toString(Integer.parseInt(done) + 1);
        endButton.setText(done);
        onDispose();
    }
});

接下来我简单地替换了 JFrame.dispose() 的直接调用并添加了一点 onDispose() 方法,我在其中更新(通过调用 setText())标签。在此方法中,您现在基本上可以添加在调用 dispose().

之前应该发生的任何事情
private void onDispose() 
{
    endLabel.setText(done);
    framebox.dispose();
}

如果这不是您要找的,请告诉我。