java.awt drawRect()错误地解释了;宽度“;及;高度“;(左右各产生一个像素) 我开始使用Swing编程,发现了一个非常奇怪的东西,我认为它是基本的错误。
下面的示例显示,创建矩形和显示矩形时,“宽度”和“高度”值的处理方式不同java.awt drawRect()错误地解释了;宽度“;及;高度“;(左右各产生一个像素) 我开始使用Swing编程,发现了一个非常奇怪的东西,我认为它是基本的错误。,swing,awt,drawrect,Swing,Awt,Drawrect,下面的示例显示,创建矩形和显示矩形时,“宽度”和“高度”值的处理方式不同 import java.awt.*; // I create a rectangle 2 x 2 with height=2, width=2 Rectangle rec = new Rectangle(1, 1, 2, 2); // I make sure that it contains only 4 points: (1,1), (1,2), (2,1), (2,2) println("- " + rec.con
import java.awt.*;
// I create a rectangle 2 x 2 with height=2, width=2
Rectangle rec = new Rectangle(1, 1, 2, 2);
// I make sure that it contains only 4 points: (1,1), (1,2), (2,1), (2,2)
println("- " + rec.contains(1, 1) + ", " + rec.contains(1, 2) + ", " + rec.contains(1, 3));
println("- " + rec.contains(2, 1) + ", " + rec.contains(2, 2) + ", " + rec.contains(2, 3));
println("- " + rec.contains(3, 1) + ", " + rec.contains(3, 2) + ", " + rec.contains(3, 3));
输出:
- 真,真,假
- 真,真,假
- 假,假,假
- 相交(2,2):真
- 相交(3,3):false
// Let's check what is get drawn
g.drawRect(1, 1, 2, 2); // displays 3 x 3 (as if width=3, height=3) !!
// Try it different way
((Graphics2D)g).draw(rec); // displays 3 x 3 again (as if width=3, height=3) !!
黄色小矩形显示为3 x 3:
结论:矩形()类构造函数将宽度/高度视为像素的实际宽度/高度,而绘制方法绘制矩形()将宽度/高度考虑为相对于左上像素的偏移。
因此java.awt在计算时表示与nxm相同的矩形,但在使用drawRect()渲染时表示为(N+1)x(M+1)
我发现这是完全错误的,因为人类的默认逻辑是假设我们画的正是我们所拥有的
我想知道是否有其他人知道这个问题,并且可以给bug追踪器提供一些参考或/和对这种行为的一些逻辑解释。只是谷歌搜索没有告诉我什么
我还想知道其他程序员是如何解决这个问题的。使用包装器拖动直线推送(x、y、宽度-1、高度-1)?我真不敢相信它如此怪异的工作对每个人来说都是好的
更新1:发布复制问题的“最小”代码段:
import javax.swing.*;
import java.awt.*;
public class Main {
public static void main(String args[]) {
JFrame jFrame = new JFrame("Bug of drawRect() demo");
JPanel jPanel = new JPanel() {
@Override
public void paintComponent(Graphics g) {
g.drawRect(1,1,2,2);
}
};
jFrame.add(jPanel);
jFrame.setSize(400, 100);
jFrame.setLocationRelativeTo(null);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setVisible(true);
}
}
更新2:我正在使用来自的OpenJDK 8。如果我在IDE中使用“Go To->Implementation(s)”,我会在这里看到drawRect()实现:C:\Program Files\ojdkbuild\java-1.8.0-openjdk-1.8.0.181-1\src.zip\java\awt\Graphics.java
public void drawRect(int x, int y, int width, int height) {
if ((width < 0) || (height < 0)) {
return;
}
if (height == 0 || width == 0) {
drawLine(x, y, x + width, y + height);
} else {
drawLine(x, y, x + width - 1, y);
drawLine(x + width, y, x + width, y + height - 1);
drawLine(x + width, y + height, x + 1, y + height);
drawLine(x, y + height, x, y + 1);
}
}
public void drawRect(整数x、整数y、整数宽度、整数高度){
如果((宽度<0)| |(高度<0)){
回来
}
如果(高度=0 | |宽度=0){
抽绳(x,y,x+宽度,y+高度);
}否则{
抽绳(x,y,x+宽度-1,y);
抽绳(x+宽度,y,x+宽度,y+高度-1);
抽绳(x+宽度,y+高度,x+1,y+高度);
抽绳(x,y+高度,x,y+1);
}
}
在这个实现中,我看到它在“x+width”处绘制了第二行和第三行,而不是导致错误的“x+width-1”。当我遇到同样的问题时,下面的代码(比这更复杂),我花了一些时间来理解我做错了什么(我在这里强调,就像你一样,我认为API是错误的:你画的是100x100的矩形,它应该是100x100,而不是101x101。): 在示例窗口中,我们可以看到绘制的矩形在宽度/高度上增加了一个像素 在我的例子中,这是有问题的,因为我正在使用绘制矩形的区域调用repaint。因此:
- 我正在调用重新绘制(0,0,100,100)
- Swing重新粉刷100x100正方形
- 白线仍然存在,因为它没有重新喷漆
Graphic
类在如何使用宽度和高度方面并不一致,正如下面的Javadoc摘录所示:
- 从javadoc: 绘制指定矩形的轮廓。左右边缘 矩形的宽度为x和x+宽度。上边缘和下边缘为 在y和y+高度。使用图形绘制矩形 上下文的当前颜色
- 从javadoc: 填充指定的矩形。矩形的左边缘和右边缘 矩形位于x和x+宽度-1。上边缘和下边缘位于 y和y+高度-1。生成的矩形覆盖一个区域宽度 宽像素高像素。矩形用 图形上下文的当前颜色
Graphics2D
)
TL;DR:您可能应该创建一个与fillRect
相同的静态方法drawRect
,如下所示:
public static void drawRect(Graphics g, int x, int y, int w, int h) {
g.drawRect(x, y, w - 1, h - 1);
}
g.fillRect(1,1,2,2);
-对我来说只是一个2x2的正方形。在我看来,它就像API中描述的那样绘制。我在Windows 7上使用JDK 8。发布一篇正确的演示问题的文章,而不仅仅是几行代码。对不起,关于fillRect,你是对的。但是drawRect()仍然有一个问题。我已经相应地更新了我的问题,并将对我正在使用的JDK的引用和drawRect()的实现放在那里,这证明它是错误的。您能确认drawRect()也有问题吗?但是drawRect()有问题仍然有一个问题。
-不,没有。它按照API中的描述进行绘制。阅读这两种方法的API,您将看到它们的区别。我在处阅读了它。我看到当前的行为是“矩形的左边缘和右边缘在x和x+宽度处”这句话所期望的。但是参数描述我认为下面的“宽度-要绘制的矩形的宽度”是错误的,因为它实际上不是一个宽度。宽度是实际显示的边缘的像素数,严格来说。你同意吗?我想人们一般都理解“宽度”这个词“意思是从一个起点向右。如果你不这样做,你还会用什么术语?”
public class MyComponent extends JComponent {
@Override
public void paintComponent(final Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.RED);
g.fillRect(0, 0, 100, getHeight());
g.setColor(Color.WHITE);
g.drawRect(0, 0, 100, 100);
}
public static void main(final String[] args) {
final JFrame frame = new JFrame("Test");
frame.setSize(150, +156);
frame.getContentPane().add(new MyComponent());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
public static void drawRect(Graphics g, int x, int y, int w, int h) {
g.drawRect(x, y, w - 1, h - 1);
}