knu*_*nub 7 java swing scala transform graphics2d
我使用Java的Graphics2D在一个组件上使用AffineTransform来操作我的绘图.Graphics2D为此提供了一个方法转换,它采用了AffineTransform.
有时我需要手动操作一个点而不使用内置转换.但是当我尝试使用相同的变换转换一个点时,我给了Graphics2D.transform有时结果点不一样.
下面的代码重现了这个问题(它是Scala代码,但我认为你可以想象Java代码.):
var transformationMatrix = new AffineTransform()
/*
* transformationMatrix is modified throughout the program
* ...
*/
override def paintComponent(g: Graphics2D) = {
super.paintComponent(g)
/* 1. transform using graphics transform */
g.transform(transformationMatrix)
g.setColor(Color.RED)
g.fill(new Rectangle(0, 0, 1, 1))
/* 2. transform point manually */
g.setTransform(new AffineTransform) // reset transformation to standard
val p0 = new Point(0, 0)
val pDest = new Point()
transformationMatrix.transform(p0, pDest)
g.setColor(Color.BLUE)
g.fill(new Rectangle(pDest.x, pDest.y, 1, 1)
}
Run Code Online (Sandbox Code Playgroud)
预期的行为
蓝色矩形(手动计算)透过红色矩形(通过变换计算).
经验丰富的行为

我承认我的transformationMatrix并不是真正的整数,但那应该不是问题,不是吗?
affineTransform = 1.1, 0.0, 520.55
0.0, 1.1, 182.54999999999995
0.0, 0.0, 1.0
Run Code Online (Sandbox Code Playgroud)
这是一个错误还是我错过了一些深刻的见解?
编辑:如果将transformationMatrix设置为,则可以重现该错误
transformationMatrix = new AffineTransform(1.1, 0.0, 0.0, 1.1, 521.55, 183.54999999999995)
Run Code Online (Sandbox Code Playgroud)
在paintComponent的开头.请注意,g是Graphics2D类型.
你的变换基本上只是一个翻译(520.55, 182.55).并且因为它具有小数像素值,所以实际上对于舍入选择很敏感.如果你有抗锯齿功能,你实际上会得到一个4像素的红色斑点,覆盖重叠的像素.否则,考虑到舍入到整数和截断为整数之间的模糊性,您看到的行为(不一致)是合理的.
好吧,您正在做两种不同的事情。
在(1)中,您要对形状(和它无关,Rectangle而与否无关Rectangle2D.Double)进行转换,以产生分数坐标。它仅被绘制为别名,因为您尚未设置特定的渲染提示(RenderingHints.KEY_ANTIALIASING-> RenderingHints.VALUE_ANTIALIAS_ON和RenderingHints.KEY_STROKE_CONTROL-> RenderingHints.VALUE_STROKE_PURE)。
在(2)中,您要对转换点进行点化,并将其强制转换为别名坐标(Point而不是Point2D.Double)。然后从该点开始依次构造一个矩形。
显然,引擎盖下可能会发生非常不同的事情,并且我完全不希望在别名图形上下文中转换为整数点与绘制浮点形状会产生相同的结果。
(未经测试)我猜想对于(1)的有效等效语句为
g.fill(transformationMatrix.createTransformedShape(new Rectangle(0, 0, 1, 1)))
Run Code Online (Sandbox Code Playgroud)