当我释放鼠标按钮时,MouseEvent未注册发布 [英] MouseEvent is not registering a release when I release the mouse button
问题描述
public void mousePressed(MouseEvent e){//在组件上按下鼠标按钮时调用.如果(e.getButton()== MouseEvent.BUTTON1){isDown = true;System.out.println("isDown现在为true");}如果(e.getButton()== MouseEvent.BUTTON3){isDown2 = true;System.out.println("isDown2现在为真");}做 {点位置= MouseInfo.getPointerInfo().getLocation();int x = location.x-(drawingPanel.getLocationOnScreen()).x;int y = location.y-(drawingPanel.getLocationOnScreen()).y;drawingPanel.paint(drawingPanel.getGraphics(),(x-(x%20)-1),(y-(y%20)-1),19,19);} while(isDown);System.out.println(鼠标已被按下.");}public void mouseReleased(MouseEvent e){//在组件上释放鼠标按钮时调用.如果(e.getButton()== MouseEvent.BUTTON1){isDown = false;System.out.println("isDown现在为false");}如果(e.getButton()== MouseEvent.BUTTON3){isDown2 = false;System.out.println("isDown2现在为false");}System.out.println(鼠标已被释放.");}
这是我到目前为止所拥有的.我的初衷是设计代码,以便在按下鼠标时将布尔值 isDown
设置为true,然后在时运行
为true.如果释放鼠标按钮,我将 while
循环> isDown isDown
设置为false,以终止 while
循环.
我在这里弄乱了什么?两个MouseEvent方法不能同时运行吗? isDown
布尔变量中的更改未注册,并且我的手上有一个无限的while循环.
这是对事件调度线程的经典违反.
所有UI代码都在单个线程中运行.所有事件都是从同一线程分派UI的,这意味着如果您阻塞此线程(使用循环或其他阻塞操作),则不会分派任何事件.这将使您的程序看起来像已被挂起.
有关更多信息,请参见 Swing并发详细信息.
您真正应该做的是使用如何使用鼠标侦听器./p>
此 drawingPanel.paint(drawingPanel.getGraphics(),(x-(x%20)-1),(y-(y%20)-1),19,19);
也让我无休止.
您永远不应使用 getGraphics
进行自定义绘制. getGraphics
可以返回null,并且仅是上一次绘制周期的快照.使用此方法完成的任何绘画都将在发生另一次重新绘画时被删除/清除.
您应该创建一个自定义组件(例如 JPanel
)并覆盖它的 paintComponent
方法,并在其中执行所需的绘画.有关详细信息,请查看执行自定义绘画
示例
公共类MouseDraggedTest {公共静态void main(String [] args){新的MouseDraggedTest();}公共MouseDraggedTest(){EventQueue.invokeLater(new Runnable(){@Override公共无效run(){尝试 {UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());} catch(ex Exception){}JFrame frame = new JFrame("Test");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.add(new TestPane());frame.pack();frame.setLocationRelativeTo(null);frame.setVisible(true);}});}公共类TestPane扩展了JPanel {私有Map< Point,List< Point>>mapPoints;私有Point currentPoint;公共TestPane(){mapPoints = new HashMap<>(25);MouseAdapter mouseListener = new MouseAdapter(){@Overridepublic void mousePressed(MouseEvent e){currentPoint = e.getPoint();mapPoints.put(currentPoint,new ArrayList< Point>(25));}@Overridepublic void mouseReleased(MouseEvent e){List< Point>points = mapPoints.get(currentPoint);如果(points.isEmpty()){mapPoints.remove(currentPoint);}currentPoint = null;}@Override公共无效mouseDragged(MouseEvent me){List< Point>points = mapPoints.get(currentPoint);points.add(me.getPoint());repaint();}};addMouseListener(mouseListener);addMouseMotionListener(mouseListener);}@Override公共维度getPreferredSize(){返回新的Dimension(200,200);}@Override受保护的void paintComponent(Graphics g){super.paintComponent(g);对于(Point startPoint:mapPoints.keySet()){List< Point>points = mapPoints.get(startPoint);对于(点p:点){如果(startPoint!= null){g.drawLine(startPoint.x,startPoint.y,p.x,p.y);}startPoint = p;}}}}}
public void mousePressed(MouseEvent e) {
//Invoked when a mouse button has been pressed on a component.
if (e.getButton() == MouseEvent.BUTTON1) {
isDown = true;
System.out.println("isDown is now true");
}
if (e.getButton() == MouseEvent.BUTTON3) {
isDown2 = true;
System.out.println("isDown2 is now true");
}
do {
Point location = MouseInfo.getPointerInfo().getLocation();
int x = location.x - (drawingPanel.getLocationOnScreen()).x;
int y = location.y - (drawingPanel.getLocationOnScreen()).y;
drawingPanel.paint(drawingPanel.getGraphics(), (x - (x % 20) - 1), (y - (y % 20) - 1), 19, 19);
} while (isDown);
System.out.println("Mouse has been pressed down.");
}
public void mouseReleased(MouseEvent e) {
//Invoked when a mouse button has been released on a component.
if (e.getButton() == MouseEvent.BUTTON1) {
isDown = false;
System.out.println("isDown is now false");
}
if (e.getButton() == MouseEvent.BUTTON3) {
isDown2 = false;
System.out.println("isDown2 is now false");
}
System.out.println("Mouse has been released.");
}
This is what I have so far. My original intentions were to design the code so that the boolean isDown
would be set to true when the mouse was pressed down and then I would have the while
loop run while isDown
is true. If the mouse button is released, I would set isDown
to false in order to terminate the while
loop.
What I am messing up here? Is it not possible for two MouseEvent methods to be running at the same time? The change in the isDown
boolean variable is not being registered and I have an infinite while loop on my hands.
This is a classic violation of the Event Dispatching Thread.
All UI code is run from within a single thread. All events are dispatched the UI from this same thread, meaning that should you block this thread (using a loop or other blocking operation), no events will be dispatched. This will make your program look like it's hung.
Take a look at Concurrency in Swing for more details.
What you really should be doing is using a MouseMoitionListener
to track drag events instead. Check out How to use Mouse Listeners for more details.
This drawingPanel.paint(drawingPanel.getGraphics(), (x - (x % 20) - 1), (y - (y % 20) - 1), 19, 19);
also worries me to no end.
You should never be using getGraphics
to perform custom painting. getGraphics
can return null and is only a snap shot of the last paint cycle. Any painting done using this method will be removed/cleaned when another repaint occurs.
You should be creating a custom component (such as a JPanel
) and overriding it's paintComponent
method and performing any painting you need in it. Check out Performing Custom Painting for more details
Example
public class MouseDraggedTest {
public static void main(String[] args) {
new MouseDraggedTest();
}
public MouseDraggedTest() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Map<Point, List<Point>> mapPoints;
private Point currentPoint;
public TestPane() {
mapPoints = new HashMap<>(25);
MouseAdapter mouseListener = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
currentPoint = e.getPoint();
mapPoints.put(currentPoint, new ArrayList<Point>(25));
}
@Override
public void mouseReleased(MouseEvent e) {
List<Point> points = mapPoints.get(currentPoint);
if (points.isEmpty()) {
mapPoints.remove(currentPoint);
}
currentPoint = null;
}
@Override
public void mouseDragged(MouseEvent me) {
List<Point> points = mapPoints.get(currentPoint);
points.add(me.getPoint());
repaint();
}
};
addMouseListener(mouseListener);
addMouseMotionListener(mouseListener);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Point startPoint : mapPoints.keySet()) {
List<Point> points = mapPoints.get(startPoint);
for (Point p : points) {
if (startPoint != null) {
g.drawLine(startPoint.x, startPoint.y, p.x, p.y);
}
startPoint = p;
}
}
}
}
}
这篇关于当我释放鼠标按钮时,MouseEvent未注册发布的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!