2017-12-15 11 views
0

マップエディタを作成しようとしていますが、Graphics2dで描画したグリッドの位置を取得したいと考えています。しかし、私は解決策を見つけることができませんでしたので、各矩形の内側にMouseListenersで目に見えないJLabelを描画するというアイデアを思いつきました。しかし、私はJLabelsを描画された長方形に合わせることはできません。Javaはスイングコンポーネントとグラフィックス描画を結合します

私は描画する複数のコンポーネントがあり、それらを重ね合わせて重ねる必要があるので、これをやっています。したがって、一度に1つの画像しか保持できないため、コンポーネントを使用することはできません。

public class MainGui extends JFrame { 

    public MainGui(int width, int height) { 
     this.setTitle("Map Editor"); 
     this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 

     GuiGridPanel guiGridPanel = new GuiGridPanel(width, height); 
     add(guiGridPanel.buildGuiGrid(), BorderLayout.CENTER); 

     setSize(new Dimension(780,480)); 
     setLocationRelativeTo(null); 
     setVisible(true); 
    } 
} 

public class GuiGridPanel extends JPanel { 
    private Graphics2D render; 
    private int width; 
    private int height; 
    private JPanel gridPanel; 
    private final int gridSize = 32; 

    public GuiGridPanel(int width, int height){ 
     this.width = (width); 
     this.height = (height); 
     gridPanel = new JPanel(new GridLayout(height, width)); 
     buildLabels(); 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     render = (Graphics2D) g; 
     drawMap(); 
    } 

    public JScrollPane buildGuiGrid() { 
     add(gridPanel); 
     JScrollPane jScrollPane = new JScrollPane(this); 
     jScrollPane.getVerticalScrollBar().setUnitIncrement(16); 
     return jScrollPane; 
    } 

    private void buildLabels() { 
     for(int x = 0; x < height; x++) { 
      for (int y = 0; y < width; y++) { 
       JLabel label = new JLabel("HERE"); 
       label.setBounds(x*gridSize, y*gridSize, gridSize, gridSize); 
       gridPanel.add(label); 
      } 
     } 
    } 

    private void drawMap() { 
     for(int x = 0; x < height; x++) { 
      for(int y = 0; y < width; y++) { 

       render.drawRect(x*gridSize, y*gridSize, gridSize, gridSize); 
      } 
     } 
    } 
} 

テスト目的のために:ここで

は、現在私が使用している最低限の実施例です。私はJLabelsの名前として "Here"を入れて、各矩形の内側に入っていることを確認します。しかし、現在彼らはそれをやっていません。私はJLabelの境界を修正しようとしましたが、レイアウトマネージャをnullに設定して自由に配置できるようにしましたが、動作させることができませんでした。

おかげ

+0

「私はグリッドの位置を取得したい」 - あなたが何を意味するかわからない。パネルに幅100ピクセル、グリッド10個のパネルがある場合は、マウスポイントを特定のグリッドに簡単に変換できます。つまり、マウスポイントのx値を10で割り、整数値をとって "X"グリッドを与えます。 "Y"グリッドについても同じ操作を行います。 – camickr

答えて

1

次の例では、GridPainterは、選択状態に基づいて各セルが青色で塗りつぶされた、指定されたサイズのグリッドをレンダリングします(addMouseListener参照)。

public class MainFrame extends JFrame { 
    public MainFrame() { 
     GridPainter gp = new GridPainter(5,5); 
     gp.addMouseListener(new MouseAdapter() { 
      @Override 
      public void mouseClicked(MouseEvent e) { 
       if (e.getButton() == MouseEvent.BUTTON1) { 
        // onLeftButtonClick 
        gp.selectCell(e.getX(), e.getY()); 
       } else { 
        // onWheelButton/RightButtonClick 
        gp.unselectCell(e.getX(), e.getY()); 
       } 
      } 
     }); 
     add(gp); 
     setSize(new Dimension(500,500)); 
     setVisible(true); 
    } 
} 

public class GridPainter extends JComponent { 
    private final int rows; 
    private final int columns; 
    private boolean[][] isSelected; // selection state of cells 

    public GridPainter(int rows, int columns) { 
     this.rows = rows; 
     this.columns = columns; 
     isSelected = new boolean[rows][columns]; 
    } 

    private int getRowSize() {return getHeight()/rows;} 
    private int getColSize() {return getWidth()/columns;} 

    private int[] resolveIndices(int x, int y) { 
     int i = y/getRowSize(); 
     int j = x/getColSize(); 
     return new int[] {i, j}; 
    } 

    public void selectCell(int x, int y) { 
     int[] indices = resolveIndices(x, y); 
     int i = indices[0]; 
     int j = indices[1]; 
     isSelected[i][j] = true; 
     repaint(); 
    } 
    public void unselectCell(int x, int y) { 
     int[] indices = resolveIndices(x, y); 
     int i = indices[0]; 
     int j = indices[1]; 
     isSelected[i][j] = false; 
     repaint(); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     Graphics2D g2 = (Graphics2D) g; 
     int width = this.getWidth(); 
     int height = this.getHeight(); 

     // draw rows 
     int rowSize = getRowSize(); 
     for (int i = 0; i < columns; i++) { 
      int yOffset = i * rowSize; 
      g2.drawLine(0, yOffset, width, yOffset); 
     } 

     // draw lines 
     int colSize = getColSize(); 
     for (int j = 0; j < rows; j++) { 
      int xOffset = j * colSize; 
      g2.drawLine(xOffset, 0, xOffset, height); 
     } 

     // fill selected cells 
     for (int i = 0; i < rows; i++) { 
      for (int j = 0; j < columns; j++) { 
       if (isSelected[i][j]) { 
        Color oldColor = g2.getColor(); 
        g2.setColor(Color.BLUE); 
        int x = j * colSize; 
        int y = i * rowSize; 
        int w = colSize; 
        int h = rowSize; 
        g2.fillRect(x, y, w, h); 
        g2.setColor(oldColor); 
       } 
      } 
     } 
    } 
} 
+0

これは私が探しているスタイルの詳細です。しかし、描画をBufferedImageのダイナミックにすることは可能ですか?だから私は1つまたは複数のBufferedImagesを送ることができ、それらを互いに重ねる必要がありますか?私はGraphics2DオブジェクトがpaintComponentの中になければならないことを理解していますので、そのようなメソッドの作り方がわかりません。 – Cows42

+0

@ Cows42 'Graphics2D'コンテキストには' drawImage'メソッドが含まれていますので、あなたが望む何でもできることを確信しています。 – matoni

+0

申し訳ありませんが、私はそれを打つつもりです。ありがとう – Cows42

3

はあなたの問題を解決することはできませんが、変数は、変数がインスタンス変数として定義すべきではありません「レンダリング」。

Graphicsオブジェクトは、paintComponent()メソッドまたはpaintComponent(...)メソッドから呼び出されたメソッドでのみ使用できます。

ので、変数をローカルに定義する必要があります。

//render = (Graphics2D) g; 
    //drawMap(); 
    Graphics2D render = (Graphics2D) g; 
    drawMap(render); 

そしてあなたはdrawMap(...)メソッドに変更:

//private void drawMap() 
private void drawMap(Graphics2d render) 

を編集:

私はそれらをしたいです互いの上に積み重ねる。したがって、一度に1つの画像しか保持できないため、コンポーネントを使用することはできません。

あなたは別のコンポーネントにコンポーネントを追加することができます

JLabel background = new JLabel(...); 
background.setLayout(new BorderLayout()); 
JLabel foreground = new Jlabel(...); 
background.add(foreground); 

次に、上記繰り返し、「フォアグラウンド」に別のコンポーネントを追加することができます。

別のオプションは、複数のアイコンを含むアイコンを作成することです。このアプローチの例については、Compound Iconをご覧ください。

もう1つのアプローチは、BufferedImageを作成し、すべての画像をBufferedImage上に重ねてペイントすることです。

本当に不明な点はありますか?これらの画像が動的に変化するか固定されているかどうかはわかりませんので、アプローチを提案するのは難しいです。

+0

申し訳ありませんが、これらの編集を追加します。可能な解決策が見つかりました。 Graphicsを使用してカスタムJComponentを作成し、それにMouseListenerを設定します。しかし、私はそのオブジェクトをどのように描くことができるのかは分かりません。/ – Cows42

+0

あなたの問題や何をしようとしているのか分かりませんが、現在のクラスにMouseListenerを追加できない理由はありません。また、カスタムJComponentを作成したとしても、paintComponent()をオーバーライドすることで、ここでやったやり方でカスタムペインティングを行うことができます。 – camickr

+0

私がしたいのは、Gridlayoutで整列された矩形を作成することです。各矩形にはMouseListenerが必要です。 JComponentを拡張すると、そのクラスに矩形を描き、その上にMouseListenerを作成できることが分かりました。しかし、私は図面を見栄え良くすることはできません:/ – Cows42

関連する問題