Java将图形绘制与swing组件相结合

时间:2017-12-15 01:41:54

标签: java swing rendering

我正在尝试创建一个地图编辑器,我希望能够获得我使用Graphics2d绘制的网格位置。但是,我没有找到任何解决方案,因此我提出了在每个矩形内部使用MouseListener绘制隐形JLabel的想法。但是,我无法使JLabel适合绘制的矩形。

我这样做是因为我有多个要绘制的组件,我希望它们相互堆叠。因此,我不能使用任何组件,因为它们一次只能容纳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);
            }
        }
    }
}

用于测试目的。我把&#34;在这里&#34;作为JLabels的名称,以确保它们进入每个矩形。但目前他们并没有这样做。我尝试修改JLabel的边界,甚至将其布局管理器设置为null,这样我就可以自由放置它们了,但是我无法让它工作。

由于

2 个答案:

答案 0 :(得分:3)

不能解决你的问题,但变量&#34;渲染&#34;变量不应该被定义为实例变量。

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 );

然后,您可以重复上面的内容并将另一个组件添加到&#34;前景&#34;。

另一种选择是创建一个包含多个图标的图标。查看Compound Icon以获取此方法的示例。

另一种方法可能是创建一个BufferedImage并在BufferedImage上将所有图像绘制在一起。

你的问题真的不清楚。我不知道这些图像是动态更改还是修复,所以很难建议一种方法。

答案 1 :(得分: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);
                }
            }
        }
    }
}