gpt4 book ai didi

Java HitTest 行为异常

转载 作者:行者123 更新时间:2023-12-01 23:44:06 28 4
gpt4 key购买 nike

我试图扩展 java ScrollDemo2 来报告 Canvas 上的形状是否被单击。我从一个简单的矩形开始,相信简单地循环 Canvas 中的矩形检查点击点是否包含在其中应该没有问题。但随后发生了一些奇怪的事情, contains 方法似乎只关心该点是否位于锚定于 (0,0) 的矩形中,并且似乎并不关心我的组件位于 y=20 处。因此,如果我在 x:[0,20] y:[0,20] 中单击 Jpanel,我就会受到打击,而只有在单击 x:[0,20] y[20,40] 时才应该受到打击。 。这是一个错误,还是我做错了什么?

public class CachedDrawableComponent extends JComponent
{
//this will do more later
CachedDrawableComponent(Rectangle bounds)
{
this.setBounds(bounds);
}
protected void paintComponent(Graphics g)
{
g.setColor(Color.magenta);
Rectangle r = this.getBounds();
g.fillRect(r.x, r.y, r.width, r.height);
}

}

public class ScrollDemo2 extends JPanel
implements MouseListener {
private Dimension area; //indicates area taken up by graphics
private Vector<Rectangle> circles; //coordinates used to draw graphics
private Vector<CachedDrawableComponent> otherDrawables;
private JPanel drawingPane;

private final Color colors[] = {
Color.red, Color.blue, Color.green, Color.orange,
Color.cyan, Color.magenta, Color.darkGray, Color.yellow};
private final int color_n = colors.length;

public ScrollDemo2() {
super(new BorderLayout());

area = new Dimension(0,0);
circles = new Vector<Rectangle>();
this.otherDrawables = new Vector<CachedDrawableComponent>();

//Set up the instructions.
JLabel instructionsLeft = new JLabel(
"Click left mouse button to place a circle.");
JLabel instructionsRight = new JLabel(
"Click right mouse button to clear drawing area.");
JPanel instructionPanel = new JPanel(new GridLayout(0,1));
instructionPanel.setFocusable(true);
instructionPanel.add(instructionsLeft);
instructionPanel.add(instructionsRight);

//Set up the drawing area.
drawingPane = new DrawingPane();
drawingPane.setBackground(Color.white);
drawingPane.addMouseListener(this);
TestRect t = new TestRect(new Rectangle(0,20,20,20));
this.otherDrawables.add(t);


//Put the drawing area in a scroll pane.
JScrollPane scroller = new JScrollPane(drawingPane);
scroller.setPreferredSize(new Dimension(200,200));

//Lay out this demo.
add(instructionPanel, BorderLayout.PAGE_START);
add(scroller, BorderLayout.CENTER);
}

/** The component inside the scroll pane. */
public class DrawingPane extends JPanel {
protected void paintComponent(Graphics g) {
super.paintComponent(g);

Rectangle rect;
for (int i = 0; i < circles.size(); i++) {
rect = circles.elementAt(i);
g.setColor(colors[(i % color_n)]);
g.fillOval(rect.x, rect.y, rect.width, rect.height);

}

for (int i = 0; i < otherDrawables.size(); i++) {
CachedDrawableComponent drawMe = otherDrawables.elementAt(i);;
g.setColor(colors[(i % color_n)]);
drawMe.paint(g);

}
}
}

//Handle mouse events.
public void mouseReleased(MouseEvent e) {
final int W = 100;
final int H = 100;
boolean changed = false;
if (SwingUtilities.isRightMouseButton(e)) {
//This will clear the graphic objects.
circles.removeAllElements();
area.width=0;
area.height=0;
changed = true;
} else {
int x = e.getX() - W/2;
int y = e.getY() - H/2;
if (x < 0) x = 0;
if (y < 0) y = 0;
Rectangle rect = new Rectangle(x, y, W, H);
circles.addElement(rect);
drawingPane.scrollRectToVisible(rect);

int this_width = (x + W + 2);
if (this_width > area.width) {
area.width = this_width; changed=true;
}

int this_height = (y + H + 2);
if (this_height > area.height) {
area.height = this_height; changed=true;
}
}
if (changed) {
//Update client's preferred size because
//the area taken up by the graphics has
//gotten larger or smaller (if cleared).
drawingPane.setPreferredSize(area);

//Let the scroll pane know to update itself
//and its scrollbars.
drawingPane.revalidate();
}
drawingPane.repaint();
}
public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mousePressed(MouseEvent e)
{
System.out.println("Did press:"+e.getPoint());
System.out.println(otherDrawables.get(0).getBounds());
if(otherDrawables.get(0).contains(e.getPoint()))
{
System.out.println("Did Hit");
}

}

/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("ScrollDemo2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Create and set up the content pane.
JComponent newContentPane = new ScrollDemo2();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);

//Display the window.
frame.pack();
frame.setVisible(true);
}

public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}



Output:

Did press:java.awt.Point[x=8,y=7]
java.awt.Rectangle[x=0,y=20,width=20,height=20]
Did Hit
Did press:java.awt.Point[x=14,y=89]
java.awt.Rectangle[x=0,y=20,width=20,height=20]

enter image description here

最佳答案

面临的问题是您正在混合坐标系:

  • mouseListener中的坐标是drawingPane的坐标
  • somecomponent.contains 中预期的坐标是组件的坐标

来自 contains 的 api 文档:

Checks whether this component "contains" the specified point, where x and y are defined to be relative to the coordinate system of this component.

拥有这些组件而不将它们实际添加到绘图 Pane 中是不寻常的(没有充分的理由就不要这样做:-)。

关于Java HitTest 行为异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17419238/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com