【问题标题】:JPanel not updating when using invalidate, validate and repaint使用无效、验证和重绘时 JPanel 不更新
【发布时间】:2026-01-01 03:45:02
【问题描述】:

我有一个问题,我的JPanels 之一在它应该也没有根据窗口更新自己。我将尝试简要解释发生了什么。一个字符列表被输入到另一个类的arraylist(名为lookReply)中(这在我已经测试过的情况下有效),然后它使用2 iterations将每个字符分配给由JLabels制成的方表中的坐标.这些JLabels 在lookReplyGUIPanel JPanel 中。按下按钮后,新字符会加载到arraylist 中并重复。但是,该窗口不显示此更新。我知道他们正在通过一些测试进入JLabels,但它只是窗口的更新似乎不起作用。我正在使用invalidate, validate and repaint,但它仍然不起作用。请参阅下面的代码了解所需的部分。

调用的第一个方法 - 处理数组列表,然后调用另一个方法。

private void look()
{
    //clear arrayList then add new lookReply to it
    lookReply.clear();
    while (HumanUser.lookReply==null)
    {
    }
    for(int n = 0; n<HumanUser.lookReply.length(); n++)
    {
        lookReply.add(HumanUser.lookReply.charAt(n));                   
    }
    lookReply();
//UP TO HERE WORKS FINE

    screen.invalidate();
    screen.validate();
    screen.repaint();
}

处理问题JPanel的方法。

/**
 * Made up of several smaller JPanels each relate to 1 map position from the lookReply command.
 */
private JPanel lookReply()
{
    JPanel lookReplyGUIPanel = new JPanel(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    Border blackline = BorderFactory.createLineBorder(Color.black);


    //Create a square table dependent on the radius of view.
    //Then fill each cell with the block retrieved from the lookReply arrayList.
    for(int y = lookReplyY; y>0; y--)
    {
        for(int x = lookReplyX; x>0; x--)
        {wall...
            //Then assign it to a variable which is used in the JLabel.
            String item = null;
            if (lookReply.size()!=0)
            {
                item = lookReply.get(x*y-1) + "";
            }
            //ADD TO CHECK WHAT EACH ITEM IS AND USE THE RELEVENT PICTURE
            JLabel lookx = new JLabel(item);
            int width = (2*screenHeight/(5*lookReplyX)-10);
            lookx.setPreferredSize(new Dimension(width, width));
            lookx.setBorder(blackline);
            c.gridx = x;
            c.gridy = y;
            lookReplyGUIPanel.add(lookx, c);
        }
    }
    return lookReplyGUIPanel;
}

如果有帮助,请提供有关所有内容的更多详细信息。调用的第一个方法使用gridBagConstraints 将所有JPanels 添加到JFrame 的正确位置。 JFrame 是在方法之外创建的,因此所有其他方法都可以看到它。非常感谢所有帮助,如果需要,我们很乐意提供更多详细信息!谢谢

这里有一段简单的可编译代码演示了同样的问题。忽略窗口必须调整大小的事实 - 每个按钮单击button 都会使 m 增加 1,并且应该更新以显示 5X5 表的 lookReply 方法。然而事实并非如此。

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
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;

public class temp
{
JFrame screen = new JFrame("temp");
int m = 1;


public static void main(String[] args)
{
    temp g = new temp();
    g.create();
}

private void create()
{       
    screen.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    screen.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();

    c.gridy = 0;
    screen.add(lookReply(), c);


    c.gridy = 1;
    screen.add(button(), c);

    screen.setVisible(true);
}

private JPanel lookReply()
{
    JPanel lookReplyGUIPanel = new JPanel(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();

    for(int y = 5; y>0; y--)
    {
        for(int x = 5; x>0; x--)
        {
            JLabel lookx = new JLabel((m + ""));
            c.gridx = x;
            c.gridy = y;
            lookReplyGUIPanel.add(lookx, c);
        }
    }

    screen.invalidate();
    screen.validate();
    screen.repaint();
    return lookReplyGUIPanel;
}

private JPanel button()
{
    JPanel button = new JPanel(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();

    JButton b = new JButton("button");
    b.setBorder(null);
    c.gridx = 2;
    c.gridy = 2;
    button.add(b, c);
    b.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            m++;
            lookReply();                
        }
    });

    return button;
}

}

【问题讨论】:

  • 如果没有完全可运行的示例,就无法确定发生了什么,但是,while (HumanUser.lookReply==null) 非常可怕,这要么意味着您正在运行这段代码单独的线程,这很糟糕,因为您在同一段代码中更新 UI,或者您在 EDT 中运行它,这很糟糕,因为这会导致您的程序看起来像是“挂起”(因为它有) .您是否将lookReplyGUIPanel 添加到任何内容?
  • 你的SSCCE在哪里?为什么每次都需要要求您发布您的 SSCCE? MadProgrammer 和我都要求您在最后一个问题中发布 SSCCE/MCVE:*.com/q/22849557/131872。为什么我们每次都要重复自己???
  • @MadProgrammer 我已经将该 while 语句用作“暂停”,而另一个线程更新了用于将字符添加到数组列表的变量。是的,我正在使用多个线程。 lookReplyGUIPanel 最初在程序首次运行时添加,但不是在每次更新后添加。在阅读其他问题后,我认为这就是 invalidate、validate 和 repaint 所做的。
  • @camickr 我问过很多次了,怎么办,没人回复
  • @pokeairguy 一个简单、可编译、可运行的示例,证明您的问题就是我们所要求的一切......

标签: java swing jframe jpanel updates


【解决方案1】:

因此,根据您的示例,lookReply 创建了一个新的JPanel,但您不使用它做任何事情。所以组件永远不会添加到屏幕上,所以所有让它刷新的尝试都没有效果......

【讨论】:

  • +1,并在将组件添加到使用screen.revalidate()screen.repaint()的屏幕后刷新“屏幕”。
  • 谢谢,经过一些调整,这很有效。 @camickr 当我编译 screen.revalidate() 时它说“找不到符号符号:方法 revalidate()”。在查看了人们建议使用invalidatevalidate 的其他帖子后,您可以看到我已经使用过它并且可以正常工作
  • @pokeairguy, After looking on other posts people suggested... 这是旧建议,在使用 AWT 时使用。使用 Swing 时,您应该使用 revalidate()。 revalidate() 方法已添加到 JDK7 的 JFrame 中,因此您使用的是旧版本。但是,revalidate() 可用于所有 Swing 组件,例如 JPanel。通常人们将包含其组件的 JPanel 添加到框架中,而不是直接将组件添加到框架中。这样您就可以轻松访问面板并使用 revalidate()。
  • @camickr revalidate 当我通过eclipse编译和运行我的程序时工作,当我在LCPU中这样做时它不起作用,(Uni的linux命令行)我认为他们有一个旧版本,因此它不工作。所以我对此无能为力,无论如何都干杯
  • @pokeairguy, So theres not much I can do about that - 我已经建议了你可以做些什么。您应该更好地构建程序以将组件添加到框架的内容窗格中,而不是直接添加到框架中。阅读 Swing 教程并创建具有更好结构的程序。您做错的另一件事是您没有在事件调度线程上创建组件。
【解决方案2】:

使用javax.swing.Timer 更新您的GUI 元素,如herehere 所示。

【讨论】: