java - 叠加的 JPanel 没有对齐
问题描述
我正在尝试制作一个可绘制的 JPanel,并带有可选的网格线显示。为此,我有一个自定义的 JPanel,它创建了另一个仅包含网格线的 JPanel。这样,我可以显示/隐藏网格线,而无需删除画布上的内容。
一切似乎都在工作,除了我似乎可以确定的一些奇怪的对齐问题。当我开始绘制一些正方形时,它们仅比网格线高几个像素。我该如何解决这个问题,以便两个面板完全重叠显示?
package com.carvethsolutions.guilib.customcomp;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
/**
* A custom component for displaying a grid
*/
public class GridCanvas extends JPanel implements MouseListener {
/**
* Width and height of the canvas, in pixels
*/
private int width, height;
/**
* How many pixels represent one square on the grid
*/
private int gridScale;
/**
* The separate panel that holds the grid lines
*/
private JPanel gridPanel;
private boolean gridLinesVisible = true;
/**
* Holds color selections
*/
private Paintbrush paintbrush;
public GridCanvas() {
super();
width = 500;
height = 500;
setupComponent();
}
public GridCanvas(int width, int height) {
super();
this.width = width;
this.height = height;
setupComponent();
}
/**
* Private function to prepare the component.
*/
private void setupComponent() {
gridScale = 50;
this.setPreferredSize(new Dimension(width,height));
this.setBackground(Color.WHITE);
this.addMouseListener(this);
gridPanel = new JPanel() {
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Vertical Lines
for (int x = gridScale; x <= width; x += gridScale) {
g.drawLine(x, 0, x, height);
}
for (int y = gridScale; y <= height; y += gridScale) {
g.drawLine(0, y, width, y);
}
}
};
gridPanel.setVisible(gridLinesVisible);
gridPanel.setPreferredSize(this.getPreferredSize());
this.add(gridPanel);
this.setSize(gridPanel.getSize());
paintbrush = new Paintbrush(Color.black);
}
/**
* Enable or disable grid lines from appearing on the Canvas
*/
public void toggleGridlines() {
gridLinesVisible = !gridLinesVisible;
gridPanel.setVisible(gridLinesVisible);
}
/**
* Invoked when the mouse button has been clicked (pressed
* and released) on a component.
*
* @param e
*/
@Override
public void mouseClicked(MouseEvent e) {
int x = e.getX() / gridScale;
int y = e.getY() / gridScale;
System.out.println("mouseClicked Event : (" + x + ", " + y + ")");
this.getGraphics().setColor(paintbrush.getColor());
this.getGraphics().fillRect(x * gridScale, y * gridScale, gridScale, gridScale);
}
/**
* Invoked when a mouse button has been pressed on a component.
*
* @param e
*/
@Override
public void mousePressed(MouseEvent e) {
}
/**
* Invoked when a mouse button has been released on a component.
*
* @param e
*/
@Override
public void mouseReleased(MouseEvent e) {
}
/**
* Invoked when the mouse enters a component.
*
* @param e
*/
@Override
public void mouseEntered(MouseEvent e) {
}
/**
* Invoked when the mouse exits a component.
*
* @param e
*/
@Override
public void mouseExited(MouseEvent e) {
}
}
解决方案
为此,我有一个自定义的 JPanel,它创建了另一个仅包含网格线的 JPanel。这样,我可以显示/隐藏网格线,而无需删除画布上的内容。
嗯,这是错误的做法。您的面板应具有以下属性:
- 是否绘制网格线
- 一个二维数组,用于控制应填充哪些方格。
你的绘画逻辑是错误的:
this.getGraphics().setColor(paintbrush.getColor());
this.getGraphics().fillRect(x * gridScale, y * gridScale, gridScale, gridScale);
您永远不应该在组件上使用 getGraphics(...) 来进行自定义绘制。Swing 第一次确定需要重新绘制组件时,您将丢失所有绘制。例如,如果您调整框架的大小。
反而。自定义绘画必须在paintComponent()
组件中完成。然后你:
- 如果需要,首先绘制网格线
- 遍历二维数组并根据需要绘制任何正方形。
阅读 Swing 教程中关于自定义绘画的部分以获取更多信息和工作示例。
或者,使用 ArrayList 代替 2D Array 来包含要绘制的对象。该对象可以简单地是Point
控制要绘制的正方形的 x/y 位置的对象,或者可以是包含有关要绘制的对象的完整信息(例如位置/颜色/形状)的对象。查看自定义绘画方法以获取此方法的工作示例。
推荐阅读
- ruby-on-rails - 多对多是 Rails
- angular - 如何使用 Angular5+ 删除或添加 Html 元素
- php - 使用类别和重量的 Magento 运输成本
- android - Firebase 配置的 Codemagic 预构建问题
- php - AJAX 实时搜索返回 HTTP 500 错误
- angular - 如何将第二个下拉框数据填充到第三个输入框?
- css - 样式化组件中的最小和最大媒体查询
- javascript - 在 docker compose 中运行 sequelize migrates
- mongodb - MongoDB:上限集合中的最大文档数
- java - 通过 Kotlin 使用 Jackson 反序列化对象列表