6

同じ jlabel に保存された画像を gridlayout パネルに 2 回読み込もうとしていますが、画像の 2 つのインスタンスを作成する代わりに、画像は 1 回だけ表示されてから移動されます。

ピース配列内の同じ JLabel 位置を、boardLabels 配列内の複数の JLabel に格納するにはどうすればよいですか。

ありがとう :)

public static JPanel boardPanel = new JPanel(new GridLayout(4, 0));
public static JLabel pieces[] = new JLabel[2];
private static JLabel[] boardLabels = new JLabel[4];

public MainFrame() {
    pieces[0] = new JLabel(new ImageIcon(System.getProperty("user.dir") + "/images/piece1.png"));
    pieces[1] = new JLabel(new ImageIcon(System.getProperty("user.dir") + "/images/piece2.png"));

    this.add(boardPanel);
    displayGUIboard();
}


public static void displayGUIboard() {

    //ERROR - the label in pieces[0] is not copied into both boardLabels [0] and [1]
    boardLabels[0] = pieces[0];
    boardLabels[1] = pieces[0];

    boardPanel.add(boardLabels[0]);
    boardPanel.add(boardLabels[1]);
}

public static void main(String[] args) {
    MainFrame frame = new MainFrame();
    frame.setVisible(true);
    frame.setSize(600, 600);
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

これは機能します

    boardLabels[0] = new JLabel(pieces[1]);
    boardLabels[1] = new JLabel(pieces[1]);

ImageIconsを使用する場合、ボードを更新するにはJLabelsを削除してから再ロードする必要があるため、これを避けたいです。既に読み込まれているラベルを更新するだけです。

編集 前にこれを試しましたが、ヌルポインター例外がスローされます...

    boardLabels[0].setIcon(pieces[1]);
    boardLabels[1].setIcon(pieces[1]);

    boardPanel.add(boardLabels[0]);
    boardPanel.add(boardLabels[1]);
4

2 に答える 2

12

比較のために、@HFOE のをリファクタリングしてGround implements Icon、 によって返される配列に と のインデックスを付けましたvalues()value実装の詳細と同様に、int[][] MAP代わりにGround[][] MAP.

更新: このバリエーションは を示しGround[][] MAP、追加しますTexturePaint

ここに画像の説明を入力

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.TexturePaint;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.*;

/** @see https://stackoverflow.com/a/11556441/230513 */
public class GridExample extends JPanel {

    public static final Ground[][] MAP = {
        {Ground.GRASS, Ground.GRASS, Ground.DIRT, Ground.WATER, Ground.WATER},
        {Ground.GRASS, Ground.DIRT, Ground.CITY, Ground.WATER, Ground.WATER},
        {Ground.GRASS, Ground.DIRT, Ground.CITY, Ground.WATER, Ground.WATER},
        {Ground.GRASS, Ground.DIRT, Ground.DIRT, Ground.DIRT, Ground.WATER},
        {Ground.GRASS, Ground.GRASS, Ground.DIRT, Ground.WATER, Ground.WATER},
    };
    private JLabel[][] labelGrid = new JLabel[MAP.length][MAP[0].length];

    public GridExample() {
        setLayout(new GridLayout(MAP.length, MAP[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(MAP[r][c]);
                add(labelGrid[r][c]);
            }
        }
    }

    private static void createAndShowGui() {
        GridExample mainPanel = new GridExample();
        JFrame frame = new JFrame("GridExample");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

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

            @Override
            public void run() {
                createAndShowGui();
            }
        });
    }
}

enum Ground implements Icon {

    DIRT(new Color(205, 133, 63)), GRASS(new Color(0, 107, 60)),
    WATER(new Color(29, 172, 214)), CITY(Color.lightGray);
    private static final int SIZE = 42;
    private Random random = new Random();
    private TexturePaint paint;

    private Ground(Color color) {
        this.paint = initPaint(color);
    }

    private TexturePaint initPaint(Color color) {
        BufferedImage image = new BufferedImage(
            SIZE, SIZE, BufferedImage.TYPE_INT_ARGB);
        Rectangle2D.Double rect = new Rectangle2D.Double(0, 0, SIZE, SIZE);
        for (int row = 0; row < SIZE; row++) {
            for (int col = 0; col < SIZE; col++) {
                if (random.nextBoolean()) {
                    image.setRGB(col, row, color.getRGB());
                } else {
                    if (random.nextBoolean()) {
                        image.setRGB(col, row, color.darker().getRGB());
                    } else {
                        image.setRGB(col, row, color.brighter().getRGB());
                    }
                }
            }
        }
        return new TexturePaint(image, rect);
    }

    @Override
    public void paintIcon(Component c, Graphics g, int x, int y) {
        Graphics2D g2d = (Graphics2D) g;
        g2d.setPaint(paint);
        g.fillRect(0, 0, SIZE, SIZE);
    }

    @Override
    public int getIconWidth() {
        return SIZE;
    }

    @Override
    public int getIconHeight() {
        return SIZE;
    }
}
于 2012-07-19T08:04:38.277 に答える
9

視覚化されたコンテナーに同じコンポーネントを複数回追加することはできないため、これを行わないでください。複数の JLabel を使用することをお勧めしますが、同じImageIconを使用するようにしてください。ImageIcons は簡単に複数回使用できます。

public MainFrame() {
    pieceIcon[0] = new ImageIcon(System.getProperty("user.dir") + 
        "/images/piece1.png");
    pieceIcon[1] = new ImageIcon(System.getProperty("user.dir") + 
        "/images/piece2.png");

    this.add(boardPanel);
    displayGUIboard();
}


public void displayGUIboard() {
    boardPanel.add(new JLabel(pieceIcon[0]);
    boardPanel.add(new JLabel(pieceIcon[0]);
}

余談ですが、どの変数も静的であってはならないことに注意してください

編集:最近の編集について:

これは機能します

boardLabels[0] = new JLabel(pieces[1]);
boardLabels[1] = new JLabel(pieces[1]);

ImageIconsを使用する場合、ボードを更新するにはJLabelsを削除してから再ロードする必要があるため、これを避けたいです。すでに読み込まれているラベルを更新するだけでよろしいです。」

解決策
いいえ、JLabels をまったく変更する必要はありません。JLabel はそのままにしておきますが、JLabelsetIcon(...)メソッドを使用して保持するアイコンを交換するだけです。

編集
また、変数とオブジェクトを混同しないでください。多数の JLabel 変数を作成したとしても、それらがすべて同じ JLabel オブジェクトを参照している場合でも、コンテナにJLabel オブジェクトを複数回追加することはできません。

あなたの状態を編集 :

コードは、ゲームの表示関数の一部です。整数の配列は、解釈されるボードを表し (上記のコードではありません)、ボードの GUI を表示するために、正しい Jlabel イメージが gridlayout パネルに配置されます。表示コードが正常に動作するようになりましたが、現在のバージョンでは、ボードから jlabels を削除してから、新しい JLabels(piece...) を作成します...ただし、削除するのではなく、整数配列からそれ自体を更新することをお勧めしますラベル、配列の読み取り、ラベルの再作成。

したがって、GridLayout を使用する JPanel を作成し、変更されない JLabels で埋めます。次に、int 配列が保持する値に基づいて、JLabels が保持するアイコンを変更します。このプロセスを簡素化および自動化する方法を作成できます。

以下に関する編集:

編集以前にこれを試しましたが、ヌルポインター例外がスローされます。

次に、NPE と同じようにこれを解決します。どの行が NPE をスローしているかを調べ、その行の変数を確認し、少なくとも 1 つが null であることを確認してから、使用する前に変数を初期化するように修正します。


たとえば、次のように編集します。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.image.BufferedImage;

import javax.swing.*;

@SuppressWarnings("serial")
public class GridExample extends JPanel {
   public static final int[][] MAP = {
      {1, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2},
      {1, 1, 0, 0, 2, 2, 2, 2, 2, 2, 2},
      {1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2},
      {1, 1, 1, 0, 0, 2, 2, 2, 2, 2, 2},
      {1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2},
      {1, 1, 1, 0, 0, 0, 2, 2, 2, 2, 2},
      {1, 1, 0, 0, 0, 2, 2, 2, 2, 2, 2},
      {1, 1, 1, 0, 0, 0, 2, 2, 2, 2, 2},
      {1, 1, 1, 1, 1, 0, 0, 0, 0, 2, 2},
      {1, 1, 1, 1, 1, 0, 0, 0, 2, 2, 2},
      {1, 1, 1, 1, 1, 1, 0, 0, 0, 2, 2}
   };

   public static final Color[] COLORS = {};
   private JLabel[][] labelGrid = new JLabel[MAP.length][MAP[0].length];

   public GridExample() {
      setLayout(new GridLayout(MAP.length, MAP[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(Ground.getGround(MAP[r][c]).getIcon());
            add(labelGrid[r][c]);            
         }
      }
   }

   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 Ground(int value, Color color) {
      this.value = value;
      this.color = color;

      icon = createIcon(color);
   }

   private Icon createIcon(Color color) {
      int width = 24; // how to use const in enum? 
      BufferedImage img = new BufferedImage(width, width, BufferedImage.TYPE_INT_ARGB);
      Graphics g = img.getGraphics();
      g.setColor(color);
      g.fillRect(0, 0, width, width);
      g.dispose();
      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;
   }

}

GUIグリッドを示しています:
ここに画像の説明を入力

于 2012-07-19T03:24:54.637 に答える