2013-12-21 7 views
3

это мой первый вопрос, поэтому, пожалуйста, будьте терпеливы, если я делаю что-то не так.Перекрашивание JPanel слегка перемещает изображение на нем

Я пытаюсь создать какой-то редактор карт. В основном у меня есть 2D-массив плиток, у плиток есть тип ландшафта, а JPanel рисует изображения для каждой плитки. Теперь, когда я нажимаю на плитку, тип ландшафта изменяется, и JPanel перерисовывает все измененные плитки.

Проблема в том, что изображение на JPanel каким-то образом немного перемещается, когда я нажимаю плитку. Когда я изменяю размер окна так, чтобы каждая плитка была перекрашена, все снова выглядит нормально. Но я не могу перекрасить все, когда я только что сменил одну плитку, которая будет работать очень медленно.

Я не знаю, какие образцы кода имеют отношение к этой проблеме, но вот мой переопределяется метод paintComponent:

@Override 
protected void paintComponent(Graphics g) 
{ 
    super.paintComponents(g); 
    Tile[][] tiles = field.getTiles(); 

    for(int i = 0; i < field.getRows(); i++) 
     for(int j = 0; j < field.getColumns(); j++) 
     { 
      if(field.tileHasChanges(i, j)) 
      { 
       GroundType gt = tiles[i][j].getGround(); 
       g.drawImage(getGroundImage(gt), j*20, i*20, null); 
       field.handledTileChange(i, j); 
      } 
     } 
} 
+0

Итак, вы вызываете 'repaint()' который имеет параметры? – Justin

+0

Вы уверены, что они верны: 'j * 20, i * 20' в вызове' g.drawImage (...) '? Пиксель, так или иначе, будет иметь огромное значение. Также как в стороне, 'getGroundImage (gt)' не читает в файле или ресурсе? Это только изображение, которое вы сохранили в памяти в своей программе, не так ли? –

+0

Нет, не так ли? Я использую параметры метода drawImage. Перекраска JPanel сейчас просто перерисовывается(). – slowdive

ответ

3

Вместо нанесение изображений, рекомендуется использовать сетку JLabels, проведенный в GridLayout для вашей собственной карты сетку, а затем просто заменять ImageIcons, если вы хотите изменить изображение ячейки сетки.

Например, чтобы объединить код из предыдущего ответа of mine и из TrashGod's, проверить эту реализацию:

import java.awt.Color; 
import java.awt.Component; 
import java.awt.GridLayout; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.image.BufferedImage; 
import java.util.Random; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class GridExample extends JPanel { 
    private Ground[][] groundMap = { 
     { Ground.GRASS, Ground.DIRT, Ground.DIRT, Ground.WATER, Ground.WATER, 
       Ground.WATER, Ground.WATER, Ground.WATER, Ground.WATER, 
       Ground.WATER, Ground.WATER }, 
     { Ground.GRASS, Ground.GRASS, Ground.DIRT, Ground.DIRT, Ground.WATER, 
       Ground.WATER, Ground.WATER, Ground.WATER, Ground.WATER, 
       Ground.WATER, Ground.WATER }, 
     { Ground.GRASS, Ground.GRASS, Ground.GRASS, Ground.DIRT, Ground.WATER, 
       Ground.WATER, Ground.WATER, Ground.WATER, Ground.WATER, 
       Ground.WATER, Ground.WATER }, 
     { Ground.GRASS, Ground.GRASS, Ground.GRASS, Ground.DIRT, Ground.DIRT, 
       Ground.WATER, Ground.WATER, Ground.WATER, Ground.WATER, 
       Ground.WATER, Ground.WATER }, 
     { Ground.GRASS, Ground.GRASS, Ground.GRASS, Ground.GRASS, Ground.DIRT, 
       Ground.WATER, Ground.WATER, Ground.WATER, Ground.WATER, 
       Ground.WATER, Ground.WATER }, 
     { Ground.GRASS, Ground.GRASS, Ground.GRASS, Ground.DIRT, Ground.DIRT, 
       Ground.DIRT, Ground.WATER, Ground.WATER, Ground.WATER, 
       Ground.WATER, Ground.WATER }, 
     { Ground.GRASS, Ground.GRASS, Ground.DIRT, Ground.DIRT, Ground.DIRT, 
       Ground.WATER, Ground.WATER, Ground.WATER, Ground.WATER, 
       Ground.WATER, Ground.WATER }, 
     { Ground.GRASS, Ground.GRASS, Ground.GRASS, Ground.DIRT, Ground.DIRT, 
       Ground.DIRT, Ground.WATER, Ground.WATER, Ground.WATER, 
       Ground.WATER, Ground.WATER }, 
     { Ground.GRASS, Ground.GRASS, Ground.GRASS, Ground.GRASS, 
       Ground.GRASS, Ground.DIRT, Ground.DIRT, Ground.DIRT, 
       Ground.DIRT, Ground.WATER, Ground.WATER }, 
     { Ground.GRASS, Ground.GRASS, Ground.GRASS, Ground.GRASS, 
       Ground.GRASS, Ground.DIRT, Ground.DIRT, Ground.DIRT, 
       Ground.WATER, Ground.WATER, Ground.WATER }, 
     { Ground.GRASS, Ground.GRASS, Ground.GRASS, Ground.GRASS, 
       Ground.GRASS, Ground.GRASS, Ground.DIRT, Ground.DIRT, 
       Ground.DIRT, Ground.WATER, Ground.WATER }, }; 

    private JLabel[][] labelGrid = new JLabel[groundMap.length][groundMap[0].length]; 

    public GridExample() { 
     setLayout(new GridLayout(groundMap.length, groundMap[0].length)); 
     for (int r = 0; r < labelGrid.length; r++) { 
     for (int c = 0; c < labelGrid[r].length; c++) { 
      labelGrid[r][c] = new JLabel(); 
      labelGrid[r][c].setIcon(groundMap[r][c].getIcon()); 
      add(labelGrid[r][c]); 
     } 
     } 

     addMouseListener(new MyMouseListener()); 
    } 

    private class MyMouseListener extends MouseAdapter { 
     @Override 
     public void mousePressed(MouseEvent mEvt) { 
     Component comp = getComponentAt(mEvt.getPoint()); 
     for (int row = 0; row < labelGrid.length; row++) { 
      for (int col = 0; col < labelGrid[row].length; col++) { 
       if (labelGrid[row][col] == comp) { 
        Ground ground = groundMap[row][col]; 
        int mapCode = ground.getValue(); 
        mapCode++; 
        mapCode %= Ground.values().length; 
        groundMap[row][col] = Ground.values()[mapCode]; 
        labelGrid[row][col].setIcon(groundMap[row][col].getIcon()); 
       } 
      } 
     } 
     } 
    } 

    private static void createAndShowGui() { 
     GridExample mainPanel = new GridExample(); 

     JFrame frame = new JFrame("GridExample"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

enum Ground { 
    DIRT(0, new Color(205, 133, 63)), GRASS(1, new Color(0, 107, 60)), WATER(2, 
     new Color(29, 172, 214)); 
    private int value; 
    private Color color; 
    private Icon icon; 
    private Random random = new Random(); 

    private Ground(int value, Color color) { 
     this.value = value; 
     this.color = color; 

     icon = createIcon(); 
    } 

    private Icon createIcon() { 
     int width = 24; 
     BufferedImage img = new BufferedImage(width, width, 
      BufferedImage.TYPE_INT_ARGB); 
     for (int row = 0; row < width; row++) { 
     for (int col = 0; col < width; col++) { 
      if (random.nextBoolean()) { 
       img.setRGB(col, row, color.getRGB()); 
      } else { 
       if (random.nextBoolean()) { 
        img.setRGB(col, row, color.darker().getRGB()); 
       } else { 
        img.setRGB(col, row, color.brighter().getRGB()); 
       } 
      } 
     } 
     } 
     return new ImageIcon(img); 
    } 

    public int getValue() { 
     return value; 
    } 

    public Color getColor() { 
     return color; 
    } 

    public Icon getIcon() { 
     return icon; 
    } 

    public static Ground getGround(int value) { 
     for (Ground ground : Ground.values()) { 
     if (ground.getValue() == value) { 
      return ground; 
     } 
     } 
     return null; 
    } 

} 
+0

Я тоже думал об этом, но не нашел умного способа написать MouseListener – slowdive

+0

+1 классный код, мне нравится, как создаются значки травы, грязи и воды. – camickr

+1

@camickr: Я не могу претендовать на кредит для этой части - это код trashgod. Пожалуйста, нажмите на ссылку на нее в моем ответе и проголосуйте за его ответ. –

2
super.paintComponent's'(g); 

Может опечатка вызывает проблему. Вы должны вызывать super.paintComponent(g), без «s».

+0

Я играл с этим, прежде чем спрашивать, но оба метода сделали то же самое – slowdive

+2

@slowdive, ну, разместите правильный код, чтобы вы не вводили людей в заблуждение! – camickr

Смежные вопросы