支持用户互动
为了使用户能够与您显示的图形进行交互,您需要能够确定用户何时单击其中的一个。 Graphics2D类的hit
方法提供了一种轻松确定在特定Shape对象上是否发生鼠标单击的方法。或者,您可以获取鼠标单击的位置,然后在Shape
上调用contains
以确定单击是否在Shape
的范围内。
如果您正在使用原始文本,则可以通过获取与文本对应的轮廓Shape
,然后使用Shape
调用hit
或contains
来执行简单的点击测试。支持文本编辑需要更复杂的命中测试。如果要允许用户编辑文本,通常应使用 Swing 可编辑文本组件之一。如果您正在使用原始文本并使用TextLayout类来 管理 文本的形状和位置,则还可以使用TextLayout
进行命中测试以进行文本编辑。有关更多信息,请参见Java 2D 程序员指南中的文本和字体一章,或参见下面的 HitTestSample 示例,该示例使用TextLayout
执行简单的点击测试。
Example: ShapeMover
此 Servlets 允许用户在 Servlets 窗口中拖动Shape
。在每个鼠标位置重新绘制Shape
,以在用户拖动鼠标时提供反馈。
Note:
如果看不到 Servlets 正在运行,则需要至少安装Java SE 开发套件(JDK)7版本。
ShapeMover.java包含此 Servlets 的完整代码。
调用contains
方法可确定按下鼠标时光标是否在矩形的边界内。如果是,则矩形的位置将更新。
public void mousePressed(MouseEvent e){
last_x = rect.x - e.getX();
last_y = rect.y - e.getY();
if(rect.contains(e.getX(),
e.getY())) updateLocation(e);
...
public void updateLocation(MouseEvent e){
rect.setLocation(last_x + e.getX(),
last_y + e.getY());
...
repaint();
您可能会注意到在每个鼠标位置重绘Shape
的速度很慢,因为填充的矩形每次移动都会重新渲染。使用 Double 缓冲可以消除此问题。如果使用 Swing,则图形将自动被 Double 缓冲;您根本不需要更改渲染代码。该程序的 Swing 版本的代码是SwingShapeMover.java。
Example: HitTestSample
该应用程序通过在用户单击TextLayout
的任何位置绘制默认插入记号来说明命中测试,如下图所示。
Note:
如果看不到 Servlets 正在运行,则需要至少安装Java SE 开发套件(JDK)7版本。
HitTestSample.java包含此 Servlets 的完整代码。
mouseClicked
方法使用TextLayout.hitTestChar
返回一个java.awt.font.TextHitInfo
对象,该对象包含TextLayout
对象中的鼠标单击位置(插入索引)。
TextLayout
getAscent
,getDescent
和getAdvance
方法返回的信息用于计算TextLayout
对象的原点位置,因此它在水平和垂直方向上居中。
...
private Point2D computeLayoutOrigin() {
Dimension size = getPreferredSize();
Point2D.Float origin = new Point2D.Float();
origin.x = (float) (size.width -
textLayout.getAdvance()) / 2;
origin.y =
(float) (size.height -
textLayout.getDescent() +
textLayout.getAscent())/2;
return origin;
}
...
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.white);
Graphics2D graphics2D = (Graphics2D) g;
Point2D origin = computeLayoutOrigin();
graphics2D.translate(origin.getX(),
origin.getY());
// Draw textLayout.
textLayout.draw(graphics2D, 0, 0);
// Retrieve caret Shapes for insertionIndex.
Shape[] carets =
textLayout.getCaretShapes(insertionIndex);
// Draw the carets. carets[0] is the strong
// caret and carets[1] is the weak caret.
graphics2D.setColor(STRONG_CARET_COLOR);
graphics2D.draw(carets[0]);
if (carets[1] != null) {
graphics2D.setColor(WEAK_CARET_COLOR);
graphics2D.draw(carets[1]);
}
}
...
private class HitTestMouseListener
extends MouseAdapter {
/**
* Compute the character position of the
* mouse click.
*/
public void mouseClicked(MouseEvent e) {
Point2D origin = computeLayoutOrigin();
// Compute the mouse click location
// relative to textLayout's origin.
float clickX =
(float) (e.getX() - origin.getX());
float clickY =
(float) (e.getY() - origin.getY());
// Get the character position of the
// mouse click.
TextHitInfo currentHit =
textLayout.hitTestChar(clickX, clickY);
insertionIndex =
currentHit.getInsertionIndex();
// Repaint the Component so the new
// caret(s) will be displayed.
hitPane.repaint();
}