我正在开发一个必须绘制 map 的应用程序。
我有一个 JPanel
网格,其中包含 JPanel
单元格的二维数组。
我正在使用这个:
public class myCell extends JPanel {
...
@Override
public void paint(Graphics g){
super.paint(g);
if (imageForeground != null) {
g.drawImage(imageForeground, 0, 0, this);
}
}
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(imageBackground, 0, 0, this);
}
}
这会绘制我的背景图像,并在其上方绘制我的前景图像。
我想在一个单元格中绘制一个图像,该图像将显示在其他单元格的顶部,即从单元格中绘制一个比该单元格大的图像,如下所示:
@Override
public void paint(Graphics g){
super.paint(g);
super.drawImage(imageForeground, 0, 0, this);
or
g.drawImage(imageForeground, 0, 0, this, overflowFromPanel == true);
}
或者如果可能的话,告诉图像它可以比我的单元格更大。
了解更多信息:
背景单元格大小均为1*1。前景图像必须绘制在它所覆盖的所有背景图像之上。
例如,如果我在[1,1]方格上画一个3*3的小时,它一定在[1,1]、[1,2]、[1,3]、[2,1]上方]等...
最佳答案
自定义绘画是通过重写paintComponent()方法而不是paint()来完成的。
I'm developing an application that has to draw a map.
所以背景图像是 map 并覆盖整个面板。然后房子就会被画在 map 上。
因此,在父组件中,您重写 paintComponent()
并绘制背景图像
然后在 CellPanel
中,重写 paintComponent()
并绘制前景图像。不过,为什么不直接使用带有 ImageIcon 的 JLabel,这样就不需要进行自定义绘制了?
if I draw a 3*3 hours at the [1,1] square,
然后您需要将您的房屋图像添加到 9 个单元格中。
另一个选择是忘记将 map 定义到单元格中。相反,您创建一个具有两个属性的自定义对象:
- Point - 背景 map 上的一个点
- 图像 - 在该点绘制的图像。
然后将此自定义对象添加到 ArrayList。然后,在主面板的 PaintCompont() 方法中,您迭代此 ArrayList 并在其指定位置绘制每个图像。
@Overide
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(...); // paint the background
for (each item in the ArrayList)
{
Point p = item.getPoint();
Image image = item.getImage();
g.drawImage(...);
}
}
编辑:
On a side note: the background is a different image for every cell.
为什么要使用细胞?听起来你有一个固定大小的网格。因此,您可以将各个单元格图像绘制到更大的 BufferedImage 中,从而为所有单元格生成单个背景图像。然后你可以在背景上画房子。
另一种选择是使用OverlayLayout
。它允许您将两个面板堆叠在一起。
所以逻辑是这样的:
JPanel panel = new JPanel();
panel.setLayout( new OverlayLayout(panel) );
panel.add( foregroundPanel );
panel.add( backgroundPanel );
您需要:
- 将“foregroundPanel”设置为透明。
- 两个面板都会重写
paintComponent(...)
方法来执行自定义绘制。 - 将两个面板的大小设置为相同。
或者您可以使用JLayeredPane
。
关于java - 在父组件上绘制图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43940289/