Java 无法更新Swing中的显示

Java 无法更新Swing中的显示,java,swing,user-interface,paint,Java,Swing,User Interface,Paint,我肯定我做得不对,但是 我有一个扩展JComponent的定制平铺对象的2D数组。它们包含模型信息,以及对paintComponent()方法的重写。平铺实际上只包含一个图像、一个表示其类型的字符串和两个布尔值,这两个布尔值指示它们是否包含播放器以及它们是否能够被移动。此平铺类是所有我的平铺对象的超类,当前包括NormalTile、ActionTile和EmptyTitle 2D数组本身包含在一个扩展JPanel的TilePanel类中,这个类有几个方法来修改这个Tile数组 在这个链的顶部是M

我肯定我做得不对,但是

我有一个扩展JComponent的定制平铺对象的2D数组。它们包含模型信息,以及对paintComponent()方法的重写。平铺实际上只包含一个图像、一个表示其类型的字符串和两个布尔值,这两个布尔值指示它们是否包含播放器以及它们是否能够被移动。此平铺类是所有我的平铺对象的超类,当前包括NormalTile、ActionTile和EmptyTitle

2D数组本身包含在一个扩展JPanel的TilePanel类中,这个类有几个方法来修改这个Tile数组

在这个链的顶部是MapManager,它没有显式扩展任何内容,而是包含TilePanel和JScrollPane的实例,TilePanel被添加到JScrollPane中

第一次创建my TilePanel时,它使用一系列NormalTile初始化2D数组,这些NormalTile可以轻松地用它们使用的测试图像显示它们自己。这一切都表现得恰到好处

但是,在创建TilePanel之后,我立即调用其addTileBlock(int-width、int-height、int-x、int-y、String-type)方法来更改2D数组中特定点处的平铺。这就是更新显示的问题所在

根据我通过打印出来收集的数据,指定位置的瓷砖确实会发生变化,并且当玩家踩在瓷砖上时,瓷砖的行为确实会根据其变化类型的指示发生变化,但显示的变化从未反映出来。新的平铺(在本例中,我使用了EmptyTiles)只显示与以前使用的NormalTiles相同的图像,尽管它们的底层对象已更改

现在,“更新”平铺实际上会使旧的平铺引用指向新的平铺实例,因为我的平铺对象本身是不可变的。每当更新完成时,TilePanel类只需将抽象类TileFactory分类,以使用其GenerateFile(字符串类型)方法创建正确的Tile实例。它只是使用开关/盒块返回瓷砖

有人建议我尝试在tile对象上使用
revalidate()
方法来解决这个问题,您可以看到我在tile类的构造函数中实现它的地方。我以前也曾尝试在其paintComponent方法中使用它,但也没有效果

下面是addTileBlock方法和Tile类的完整内容:

addTileBlock:

有人能告诉我我可能做错了什么吗

有人建议我尝试在tile对象上使用revalidate()方法来解决问题

从面板添加/删除组件时,将完成重新验证()。因此,基本准则是:

panel.add(...);
panel.revalidate();
panel.repaint();
这假定您使用的是正确的布局管理器。在你的情况下,我会猜一个网格布局

现在,“更新”磁贴实际上会使旧磁贴引用指向新的磁贴实例

您不能仅仅更改变量的引用以指向新的Swing组件。您需要实际将组件添加到面板中。因此,在您的情况下,因为您使用的是网格,我猜您需要删除网格上当前点的组件,然后在该点添加另一个组件


这是一个很大的工作。既然您说您的组件基本上只包含一个图像,那么更简单的方法可能是创建一个
changeImage(…)
image,然后调用repaint()从该方法中,组件将重新绘制自身,您无需担心创建新组件并将其添加到面板。

@peeskillet所有更改GUI的代码都在Tile类的paintComponent()方法中。发布一条消息以获得更好的帮助。嗯。。。然后我对ActionTiles之类的东西有问题。扩展Tile的每个类都有自己的applyEffect()方法实现,因此我在更改类型时用新实例替换了引用。啊,但我想这只是我必须想办法解决的问题。。。非常感谢。@Aargonian,也许您的组件有一个类似'updateAction()的属性。然后,该操作将包含该操作的映像和applyEffect()方法的实现。因此,与其更新实际的磁贴,不如更新磁贴的操作,这样就不用担心布局管理了。
package games.tile.tiles;

import games.tile.Player;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;

import javax.swing.JComponent;

abstract public class Tile extends JComponent implements TileConstants
{
    private String type;
    private Image tileImage;

    private boolean containsPlayer = false;
    private boolean walkable;

    public Tile(String type, int size, boolean walkable)
    {
        this.setSize(size, size);
        this.type = type;
        this.walkable = walkable;
        this.setPreferredSize(new Dimension(this.getHeight(), this.getWidth()));
        tileImage = null;
        revalidate();
    }

    public Tile(String type, int size, boolean walkable, Image image)
    {
        this.setSize(size, size);
        this.type = type;
        this.walkable = walkable;
        tileImage = image;
        this.setPreferredSize(new Dimension(this.getHeight(), this.getWidth()));
        this.revalidate();
    }

    public boolean getWalkable() { return walkable; }
    public void setWalkable(boolean val) { walkable = val; }
    public boolean containsPlayer() { return containsPlayer; }
    public void setContainsPlayer(boolean val) { containsPlayer = val;}
    public Image getImage() { return tileImage; }
    public void setImage(Image image) { tileImage = image; }
    public String getType() { return type; }

    abstract public void applyEffect(Player player);

    @Override
    public void paintComponent(Graphics g)
    {
        if(type.equals(EMPTY) || tileImage == null)
        {
           g.setColor(Color.black);
           g.fillRect(0, 0, 32, 32);
        }
        else
        {
            g.drawImage(tileImage, 0, 0, null);
        }
        if(containsPlayer)
        {
            g.drawImage(Player.PLAYER_IMAGE, 0, 0, null);
        }
    }
}
panel.add(...);
panel.revalidate();
panel.repaint();