Java Swing MapPanel更新图形
正在尝试创建具有图形地图概述的面板。地图概览显示了整个地图的10x10个分幅(因此始终只显示特定区域)。这导致有100个MapTile对象,每个对象表示MapPanel类中的一个tile。每个MapTile都包含一个当前正在显示的字段对象。field对象保存了大量数据,例如,如果它被阻止,哪个人站在field上,field是哪种类型,等等(可能的类型是草地、泥土、石头等) 每当发生变化时,我需要更新MapPanel,使其显示实际情况,而不是我实例化的情况。这就是我目前失败的地方 这就是我到目前为止所做的:Java Swing MapPanel更新图形,java,swing,animation,jpanel,Java,Swing,Animation,Jpanel,正在尝试创建具有图形地图概述的面板。地图概览显示了整个地图的10x10个分幅(因此始终只显示特定区域)。这导致有100个MapTile对象,每个对象表示MapPanel类中的一个tile。每个MapTile都包含一个当前正在显示的字段对象。field对象保存了大量数据,例如,如果它被阻止,哪个人站在field上,field是哪种类型,等等(可能的类型是草地、泥土、石头等) 每当发生变化时,我需要更新MapPanel,使其显示实际情况,而不是我实例化的情况。这就是我目前失败的地方 这就是我到目前为
public class MapTile extends JPanel {
private BufferedImage backgroundImage;
private BufferedImage fighterImage;
private Field field;
stuff...
public MapTile(Field field) throws MidWarGeneralException {
loadBackgroundImage(field.getType());
if(field.isOccupied()) {
loadFighterImage(field.getFighter().getTeam());
}
setToolTip(field);
this.field = field;
}
private void setToolTip(Field field) {
if(field.isOccupied()) {
setToolTipText(field.getX() + "/" + field.getY() + "\n"
+ "used by: " + field.getFighter().getName() + "(Team: " + field.getFighter().getTeam().getName()
+ ")\n" + "Type: " + field.getType().getName());
}
else {
setToolTipText(field.getX() + "/" + field.getY() + "\n" +
"Type: " + field.getType().getName());
}
}
private void loadBackgroundImage(TileType type) {
stuff...
}
private void loadFighterImage(Team team) {
stuff ...
}
public void update(Field field) {
this.field = field;
repaint();
}
@Override
protected void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
Graphics2D g2d = (Graphics2D) graphics;
g2d.drawImage(backgroundImage, 0, 0, getWidth(), getHeight(), this);
if(fighterImage != null) {
g2d.drawImage(fighterImage, 0, 0, getWidth(), getHeight(), this);
}
}
}
这两个load()函数都将根据当前字段对象的当前数据加载相应的图像。我想要的是:MapTile对象始终有一个背景(grass.png、stone.png等),如果字段被一个人占用,它将以团队的颜色在其上绘制person.jpg。到目前为止,这确实有效,但是我无法更新视图
在以下情况下,视图需要更新:
public class MapPanel extends JPanel {
private Map map;
private int currentX;
private int currentY;
private List<MapTile> tiles;
public MapPanel(Map map) {
this.map = map;
this.currentX = 0;
this.currentY = 0;
this.tiles = new ArrayList<>();
init();
}
private int[] calcRenderArea() {
currentX = (currentX > map.getWidth()) ? map.getWidth() : currentX;
currentY = (currentY > map.getHeight()) ? map.getHeight() : currentY;
int difX = map.getWidth() - currentX;
int difY = map.getHeight() - currentY;
currentX = (difX < 10) ? currentX - (10 - difX) : currentX;
currentX = (difY < 10) ? currentY - (10 - difY) : currentY;
return new int[]{currentX, currentY};
}
private void render() {
int[] offsets = calcRenderArea();
int tileCounter = 0;
for(int x = offsets[0]; x < 10; x++) {
for(int y = offsets[1]; y < 10; y++, tileCounter++) {
tiles.get(tileCounter).update(map.getField(x + offsets[0], y + offsets[1]));
}
}
}
private void init() {
setLayout(new GridLayout(10, 10));
for(int i = 0; i < 10; i++) {
for(int j = 0; j < 10; j++) {
MapTile tile = new MapTile(map.getField(i, j));
tile.setBorder(BorderFactory.createLineBorder(GUIConfig.BORDER_COLOR));
add(tile);
tiles.add(tile);
}
}
}
public void toLeft() {
currentX -= 1;
update();
}
public void toRight() {
currentX += 1;
update();
}
public void toTop() {
currentY -= 1;
update();
}
public void toBottom() {
currentY += 1;
update();
}
public void update() {
// Todo :fix the map panel updating
render();
}
}
公共类映射面板扩展了JPanel{
私人地图;
私有int-currentX;
私营企业;
私人名单瓷砖;
公共地图面板(地图){
this.map=map;
这个.currentX=0;
该电流y=0;
this.tiles=新的ArrayList();
init();
}
私有int[]calcRenderArea(){
currentX=(currentX>map.getWidth())?map.getWidth():currentX;
currentY=(currentY>map.getHeight())?map.getHeight():currentY;
int difX=map.getWidth()-currentX;
int difY=map.getHeight()-currentY;
currentX=(difX<10)?currentX-(10-difX):currentX;
currentX=(difY<10)?currentY-(10-difY):currentY;
返回新的int[]{currentX,currentY};
}
私有void render(){
int[]偏移量=calcRenderArea();
int tileCounter=0;
对于(int x=偏移量[0];x<10;x++){
对于(int y=偏移量[1];y<10;y++,tileCounter++){
tiles.get(tileCounter).update(map.getField(x+offset[0],y+offset[1]);
}
}
}
私有void init(){
setLayout(新网格布局(10,10));
对于(int i=0;i<10;i++){
对于(int j=0;j<10;j++){
MapTile tile=新的MapTile(map.getField(i,j));
tile.setboorder(BorderFactory.createLineBorder(GUIConfig.BORDER_COLOR));
添加(瓷砖);
瓷砖。添加(瓷砖);
}
}
}
公共收费表(){
电流x-=1;
更新();
}
公共权利{
电流x+=1;
更新();
}
公共无效toTop(){
电流y-=1;
更新();
}
托博托姆公共空间(){
电流y+=1;
更新();
}
公共无效更新(){
//Todo:修复地图面板更新
render();
}
}
所以到目前为止,我在谷歌上搜索了很多,找到了一些关于JPanel中几个图像的帖子,但没有关于如何更新它们的帖子。。。我尝试了默认重新绘制();这不管用。有人有什么想法吗?谢谢 看起来您需要改进MapTile的
update(Field)
方法,以便它从Field对象中提取所有信息,与构造函数类似
i、 e
public final void update(Field field) {
// this.field = field;
loadBackgroundImage(field.getType());
if(field.isOccupied()) {
loadFighterImage(field.getFighter().getTeam());
}
setToolTip(field);
this.field = field;
repaint();
}
及
但作为一个“侧面”建议,一个不会解决您最初的问题但可能有助于解决未来问题的建议,我建议您将程序结构更改为更多的MVC(模型-视图-控制)类型结构,并让您的视图(上面的GUI)侦听对模型的更改(程序的逻辑部分)并在发生更改时自我更新。您需要将程序结构更改为更多MVC(模型-视图-控制)类型的结构,并让您的视图(上面的GUI)侦听对模型(程序的逻辑部分)的更改并在发生更改时更新自身。在TilePanel的
render()
方法的嵌套for循环中,如果在tile上调用tiles.get(tileCounter.repaint();
之后调用update()
,会发生什么?完全不会发生任何事情。使用tiles.get(tileCounter.repaint()将只调用repaint())这是我在update()中已经做过的…事实上你是对的,对不起。
public MapTile(Field field) throws MidWarGeneralException {
updateField(field);
}