PaintComponent 破坏网格绘图

Posted

技术标签:

【中文标题】PaintComponent 破坏网格绘图【英文标题】:PaintComponent disrupting grid drawing 【发布时间】:2022-01-03 22:12:25 【问题描述】:

我是 Java 和用户界面的新手,但我对 Java 图形有疑问。我想要实现的是在 JPanel 上绘制网格,然后将自定义组件绘制到网格中。

这是我要在其上绘制网格的类(其基础扩展 JPanel)。

public class RectGridPanel extends GridPanel


    List<Rectangle> rects;  
    
    public RectGridPanel(Simulator sim)
    
        super(sim);
        
        this.rects = new ArrayList<Rectangle>();        
        
        this.setLayout(new GridLayout(20,20));
        
        for(int x = 1; x < 801; x += 40)
        
            for(int y = 2; y < 801; y += 40)
            
                Cell newCell = new RectCell(x, y, sim);
                this.add(newCell);
            
        
        
    
    
    @Override
    public void paintComponent(Graphics g)
    
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setPaint(Color.BLACK);
        for(int x = 1; x < 801; x += 40)
        
            for(int y = 2; y < 801; y += 40)
            
                Rectangle rect = new Rectangle(x, y, 40, 40);
                g2.draw(rect);
                rects.add(rect);
            
        
    

这是我想在网格内绘制的单元格:

public class RectCell extends Cell

    Rectangle shape;
    
    public RectCell(int x, int y, Simulator sim)
    
        super(x, y, sim);
        shape = new Rectangle(x, y, CELL_SIZE, CELL_SIZE);
    
    
    @Override
    public void paintComponent(Graphics g)
    
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setPaint(Color.BLACK);
        g2.fill(shape);
    

所以网格本身绘制得很好,但是一旦我尝试在其中创建单元格,它就会像这样被打乱:

【问题讨论】:

如需更好的帮助,请edit添加minimal reproducible example。 CellGridPanel 是什么? rects.add(rect); 这将在每次调用paintComponent() 时将所有矩形添加到列表中。您应该只在创建时初始化列表一次。 您应该有一张图纸JPanel 负责所有图纸。您使用由一个或多个 Java getter/setter 类组成的逻辑模型来维护板的状态。绘图JPanel 从逻辑模型中读取游戏状态并相应地绘制游戏板。您必须在游戏的每一帧中绘制所有内容。 【参考方案1】:
public class RectCell extends Cell

    Rectangle shape;
    
    public RectCell(int x, int y, Simulator sim)
    
        super(x, y, sim);
        shape = new Rectangle(x, y, CELL_SIZE, CELL_SIZE);
    
    
    @Override
    public void paintComponent(Graphics g)
    
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setPaint(Color.BLACK);
        g2.fill(shape);
    

传递给此paintComponent() 函数的Graphics 对象定义了当前RectCell 可以绘制的屏幕空间。坐标系相对于RectCell 的左上角,因此绘制背景应始终从x = 0y = 0 或其他有意义的值开始。这里的坐标并不像你想象的那样相对于父组件。

更好的是,设置背景颜色并让 Swing 负责绘制它,而不是自己绘制一个矩形。

【讨论】:

我现在尝试使用背景颜色,使用 JPanel 绘制网格并给它们一个边框,然后将它们添加到我在 RectGridPanel 中创建的网格布局中。网格再次工作得很好,但是在我将单元格放在新创建的 JPanel 上之后它变得很奇怪,单元格的大小越小,它们离左上角越远(尽管我猜这只是它们的背景,因为鼠标侦听器附加到它们上可以正常工作)。 @HairyGnome 自从您第一次发布此问题以来,您似乎已经对代码进行了重大更改。如果您仍然需要帮助,我建议发布一个新问题。请务必包含足够的代码,以便我们自己编译和运行它,但不要包含任何与您的问题无关的代码。【参考方案2】:

目前尚不清楚您要达到什么目标。 RectCell的原因是什么?为什么不直接在 RectGridPanel 中绘制形状? paintComponent 中的嵌套循环不是一个好主意。请注意,每次使用新对象增加 rects 列表时都会经常调用paintComponent。以前绘制的矩形会丢失(画质),而具有相同参数的新矩形则超出了列表。

【讨论】:

代表每个单元格的组件就可以了。您的建议与为什么不在一个paintComponet() 中绘制所有按钮和标签相同。我们创建类来表示程序中的对象。 是的,你的组件是对的,你可以让 super.paintC... 渲染它们。但是你必须使用 Layout 并定义组件的不同宽度和高度属性,以便 LayoutManager 知道如何渲染。 这可能是问题所在:Cell 不能很好地与 LayoutManager API 配合使用。 我看到使用了 GridLayout。但是 RectCell 中形状的 x/y 定位没有任何意义。每个 RectCell 的定位由 GridLayout 管理,如果 RectCell 中的形状是必需的,它的 x 和 y 应该是静态的。随着每个实例化值的增加,您可以使形状移出组件的绘制区域。 是的,我刚刚注意到同样的事情,并开始按照这些思路写一个答案。一个问题是传递给RectCell.paintComponent()Graphics 对象的坐标系定义了对象可以绘制的区域。这不是父 RectGridPanel 的区域。

以上是关于PaintComponent 破坏网格绘图的主要内容,如果未能解决你的问题,请参考以下文章

剑道网格破坏命令不刷新网格

MATLAB绘图—三维网格绘图(mesh)

seaborn多绘图网格---小平面网格FaceGrid配对网格PairGrid联合网格JointGrid

如何在绘图中修改网格尺寸?

使用网格来注释绘图区域之外的格子图

使用 geom_sf 绘图时无法删除网格线