【问题标题】:Superimposed JPanels not lining up叠加的 JPanel 没有对齐
【发布时间】:2018-04-28 15:46:56
【问题描述】:

我正在尝试制作一个可绘制的 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 或组件网格。
  • 重点是让网格线可以切换,Camickr 和你们似乎都忽略了这一点
  • 所以? super.paintComponent 会为您解决这些问题。根据@camickr 的回答,您根本没有正确绘画。如果您在单个 paintComponent 方法中完成所有操作,您可以使用简单的布尔字段轻松打开和关闭网格线,同时保留方块。
  • 最小化您的 GUI,然后重新显示它以查看您的绘画“正确”程度。当你这样做时,你的图像是否持久?
  • (1-) The whole point is to have the gridlines toggleable - 我的回答中提到了这一点。 Clearly I'm painting correctly since I see the squares being painted. - 显然你不是因为我给你的原因。

标签: java swing jpanel


【解决方案1】:

为此,我有一个自定义的 JPanel,它创建了另一个仅包含网格线的 JPanel。这样,我可以显示/隐藏网格线,而无需删除画布上的内容。

嗯,这是错误的方法。你的面板应该有属性:

  1. 是否绘制网格线
  2. 一个二维数组,用于控制应填充哪些方格。

你的绘画逻辑是错误的:

this.getGraphics().setColor(paintbrush.getColor());
this.getGraphics().fillRect(x * gridScale, y * gridScale, gridScale, gridScale);

永远不要在组件上使用 getGraphics(...) 来进行自定义绘制。 Swing 第一次确定需要重新绘制组件时,您将丢失所有绘制。例如,如果您调整框架的大小。

相反。自定义绘画必须在组件的paintComponent() 中完成。那么你:

  1. 如果需要,首先绘制网格线
  2. 遍历二维数组并根据需要绘制任何正方形。

阅读 Custom Painting 上的 Swing 教程部分,了解更多信息和工作示例。

或者代替二维数组,使用 ArrayList 来包含要绘制的对象。该对象可以简单地是一个Point 对象,用于控制要绘制的正方形的 x/y 位置,或者可以是包含有关要绘制的对象的完整信息(例如位置/颜色/形状)的对象。查看Custom Painting Approaches 了解此方法的工作示例。

【讨论】:

    猜你喜欢
    • 2014-09-17
    • 1970-01-01
    • 2012-03-14
    • 2014-05-06
    • 1970-01-01
    • 2014-03-25
    • 1970-01-01
    • 1970-01-01
    • 2012-07-10
    相关资源
    最近更新 更多