英文:
JFrame adding two mouselisteners causing glitchy drag effect
问题
以下是翻译好的部分:
所以我有一个未装饰的JFrame,我尝试将这个FrameDragListener添加到JFrame上,以某种方式成功了。
但是,如果我的鼠标位于Frame内的文本窗格内,我无法拖动该窗格。
所以我尝试将其添加到文本窗格上,这在某种程度上起作用,但会引起一些闪烁效果,因为我添加了两个不同的鼠标监听器。
在这里,您可以看到鼠标监听器引起的闪烁效果。https://streamable.com/3yijqq
那么,当在文本窗格内单击时,我该如何取消其中一个鼠标监听器,或者将这两个鼠标监听器变成一个既适用于JFrame又适用于文本窗格内部的监听器,以避免引起那种闪烁效果?
这是FrameDragListener的代码:
FrameDragListener frameDragListener = new FrameDragListener(this);
jTextPane1.addMouseListener(frameDragListener);
jTextPane1.addMouseMotionListener(frameDragListener);
public static class FrameDragListener extends MouseAdapter {
private final JFrame frame;
private Point mouseDownCompCoords = null;
public FrameDragListener(JFrame frame) {
this.frame = frame;
}
public void mouseReleased(MouseEvent e) {
mouseDownCompCoords = null;
}
public void mousePressed(MouseEvent e) {
mouseDownCompCoords = e.getPoint();
}
public void mouseDragged(MouseEvent e) {
Point currCoords = e.getLocationOnScreen();
frame.setLocation(currCoords.x - mouseDownCompCoords.x, currCoords.y - mouseDownCompCoords.y);
}
}
英文:
So I have an undecorated JFrame I tried to add this framedraglistener to the JFrame and that worked in a way.
But I can't drag the frame if my mouse is inside the text pane inside the Frame.
So I tried to also add it to text pane and that kinda worked but is causing a glitchy effect because I am adding two different mouse listeners.
Here you can see the glitchy effect the mouse listeners are causing. https://streamable.com/3yijqq
So how can I either cancel one of the mouse listeners when clicking inside the text pane or turn the two mouse listeners into one that works both on the JFrame and inside the text pane so it won't be causing that glitchy effect
Here is the FrameDragListener
FrameDragListener frameDragListener = new FrameDragListener(this);
jTextPane1.addMouseListener(frameDragListener);
jTextPane1.addMouseMotionListener(frameDragListener);
public static class FrameDragListener extends MouseAdapter {
private final JFrame frame;
private Point mouseDownCompCoords = null;
public FrameDragListener(JFrame frame) {
this.frame = frame;
}
public void mouseReleased(MouseEvent e) {
mouseDownCompCoords = null;
}
public void mousePressed(MouseEvent e) {
mouseDownCompCoords = e.getPoint();
}
public void mouseDragged(MouseEvent e) {
Point currCoords = e.getLocationOnScreen();
frame.setLocation(currCoords.x - mouseDownCompCoords.x, currCoords.y - mouseDownCompCoords.y);
}
}
答案1
得分: 1
Here is the translated code you requested:
你尝试过了吗:
```java
public void mouseDragged(MouseEvent e) {
Point currCoords = frame.getLocation();
Point newMouseDownCompCoords = e.getPoint();
frame.setLocation(currCoords.x + newMouseDownCompCoords.x - mouseDownCompCoords.x, currCoords.y + newMouseDownCompCoords.y - mouseDownCompCoords.y);
}
它对我有用:
import java.awt.Color;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
public class Main {
public static class FrameDragListener extends MouseAdapter {
private final JFrame frame;
private Point mouseDownCompCoords = null;
public FrameDragListener(final JFrame frame) {
this.frame = frame;
}
@Override
public void mouseReleased(final MouseEvent e) {
mouseDownCompCoords = null;
}
@Override
public void mousePressed(final MouseEvent e) {
mouseDownCompCoords = e.getPoint();
}
@Override
public void mouseDragged(final MouseEvent e) {
Point currCoords = frame.getLocation();
Point newMouseDownCompCoords = e.getPoint();
frame.setLocation(currCoords.x + newMouseDownCompCoords.x - mouseDownCompCoords.x, currCoords.y + newMouseDownCompCoords.y - mouseDownCompCoords.y);
}
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(() -> {
final JTextPane jTextPane1 = new JTextPane();
jTextPane1.setBorder(BorderFactory.createLineBorder(Color.CYAN.darker(), 5));
jTextPane1.setText("Some text...");
final JFrame frame = new JFrame("Drag the text pane");
final FrameDragListener frameDragListener = new FrameDragListener(frame);
jTextPane1.addMouseListener(frameDragListener);
jTextPane1.addMouseMotionListener(frameDragListener);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(jTextPane1);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
这段代码的唯一问题是,如果你紧贴某个边缘(例如左边缘)抓住 JTextPane
并将其拖到框架边界之外(例如左侧),则会出现问题。但如果你在所有边缘离开几个像素的地方抓住 JTextPane
,那么你应该看到与我看到的一样的正常拖动。要解决这个边缘问题,你可能想要使用 java.awt.MouseInfo
类,以始终获取用户鼠标指针的位置,即使超出框架的边界。我将很快测试 MouseInfo
的想法并告诉你。
请发布一个 MRE 以便获得更好的答案。
编辑 1:
以下是使用 MouseInfo
类的代码:
import java.awt.Color;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
public class Main {
public static class FrameDragListener extends MouseAdapter {
private final JFrame frame;
private Point mouseDownCoords = null;
public FrameDragListener(final JFrame frame) {
this.frame = frame;
}
@Override
public void mouseReleased(final MouseEvent e) {
mouseDownCoords = null;
}
@Override
public void mousePressed(final MouseEvent e) {
mouseDownCoords = MouseInfo.getPointerInfo().getLocation();
}
@Override
public void mouseDragged(final MouseEvent e) {
Point currCoords = frame.getLocation();
Point newMouseDownCoords = MouseInfo.getPointerInfo().getLocation();
frame.setLocation(currCoords.x + newMouseDownCoords.x - mouseDownCoords.x, currCoords.y + newMouseDownCoords.y - mouseDownCoords.y);
mouseDownCoords = newMouseDownCoords;
}
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(() -> {
final JFrame frame = new JFrame("Drag the text pane");
final FrameDragListener frameDragListener = new FrameDragListener(frame);
final JTextPane jTextPane1 = new JTextPane();
jTextPane1.setBorder(BorderFactory.createLineBorder(Color.CYAN.darker(), 5));
jTextPane1.setText("Some text...");
jTextPane1.addMouseListener(frameDragListener);
jTextPane1.addMouseMotionListener(frameDragListener);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(jTextPane1);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
它可以工作,但问题仍然存在。这可能是由于 JTextPane
的文本被选择和取消选择导致的问题。我将尝试修复它,然后再次通知你。
编辑 2:
似乎确实是 JTextPane
的文本选择/取消选择引起的问题。因为当我将 JTextPane
替换为 JLabel
时,它正常工作。所以现在的问题是:当用户在 JTextPane
内拖动时,你希望发生什么?你希望选择文本,还是拖动框架?这两种选项之间存在冲突。
我建议你在顶部添加一个空白区域(例如一个空的 JPanel
),用户可以在那里抓住(没有装饰的)框架,并将 FrameDragListener
实例添加到该区域,而不是添加到 JTextPane
或用户界面的任何内容中。
英文:
Have you tried:
public void mouseDragged(MouseEvent e) {
Point currCoords = frame.getLocation();
Point newMouseDownCompCoords = e.getPoint();
frame.setLocation(currCoords.x + newMouseDownCompCoords.x - mouseDownCompCoords.x, currCoords.y + newMouseDownCompCoords.y - mouseDownCompCoords.y);
}
It worked for me:
import java.awt.Color;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
public class Main {
public static class FrameDragListener extends MouseAdapter {
private final JFrame frame;
private Point mouseDownCompCoords = null;
public FrameDragListener(final JFrame frame) {
this.frame = frame;
}
@Override
public void mouseReleased(final MouseEvent e) {
mouseDownCompCoords = null;
}
@Override
public void mousePressed(final MouseEvent e) {
mouseDownCompCoords = e.getPoint();
}
@Override
public void mouseDragged(final MouseEvent e) {
Point currCoords = frame.getLocation();
Point newMouseDownCompCoords = e.getPoint();
frame.setLocation(currCoords.x + newMouseDownCompCoords.x - mouseDownCompCoords.x, currCoords.y + newMouseDownCompCoords.y - mouseDownCompCoords.y);
}
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(() -> {
final JTextPane jTextPane1 = new JTextPane();
jTextPane1.setBorder(BorderFactory.createLineBorder(Color.CYAN.darker(), 5));
jTextPane1.setText("Some text...");
final JFrame frame = new JFrame("Drag the text pane");
final FrameDragListener frameDragListener = new FrameDragListener(frame);
jTextPane1.addMouseListener(frameDragListener);
jTextPane1.addMouseMotionListener(frameDragListener);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(jTextPane1);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
The only problem with this code, is if you grab the JTextPane
really close to some edge (eg the left edge) and drag outside the frame bounds (eg at the left side). But if you grab the JTextPane
a couple of pixels away from all edges, then you should see a normal drag as I saw. To solve this at-the-edge problem you may want to use the java.awt.MouseInfo
class to always get the location of the user's mouse pointer even when outside the frame's bounds. I will test the idea of the MouseInfo
shortly and let you know.
Please post an MRE so you can get better answers.
Edit 1:
Here follows the code which utilizes the MouseInfo
class...
import java.awt.Color;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
public class Main {
public static class FrameDragListener extends MouseAdapter {
private final JFrame frame;
private Point mouseDownCoords = null;
public FrameDragListener(final JFrame frame) {
this.frame = frame;
}
@Override
public void mouseReleased(final MouseEvent e) {
mouseDownCoords = null;
}
@Override
public void mousePressed(final MouseEvent e) {
mouseDownCoords = MouseInfo.getPointerInfo().getLocation();
}
@Override
public void mouseDragged(final MouseEvent e) {
Point currCoords = frame.getLocation();
Point newMouseDownCoords = MouseInfo.getPointerInfo().getLocation();
frame.setLocation(currCoords.x + newMouseDownCoords.x - mouseDownCoords.x, currCoords.y + newMouseDownCoords.y - mouseDownCoords.y);
mouseDownCoords = newMouseDownCoords;
}
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(() -> {
final JFrame frame = new JFrame("Drag the text pane");
final FrameDragListener frameDragListener = new FrameDragListener(frame);
final JTextPane jTextPane1 = new JTextPane();
jTextPane1.setBorder(BorderFactory.createLineBorder(Color.CYAN.darker(), 5));
jTextPane1.setText("Some text...");
jTextPane1.addMouseListener(frameDragListener);
jTextPane1.addMouseMotionListener(frameDragListener);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(jTextPane1);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
It works, but the problem persists. It may be due to the text of the JTextPane
being selected and unselected. I will try to fix it and then let you know again.
Edit 2:
Seems like indeed the selection/unselection of text of the JTextPane
is causing the problem. Because when I substituted the JTextPane
with a JLabel
it worked fine. So the question now is: What do you want to happen when the user drags inside the JTextPane
? Do you want the text to be selected, or the frame being dragged? There is a conflict between those options.
I would suggest you to just add an empty space (eg an empty JPanel
) at the top, where the user is supposed to grab the (undecorated) frame and add the FrameDragListener
instance to that, instead of the JTextPane
or any contents of the user's interface.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论