我使用几乎相同的方法将JFrame移动为Java - Custom shaped draggable JFrame
我有一个扩展JPanel的类。在上面的类中,我将前面的x和y设置为变量,如:
private int pressX, pressY
然后,在mousePressed方法中,我有:
pressX = e.getX();
pressY = e.getY();
最后,在mouseDragged中,我有:
mainFrame.setLocation((int) Math.round(mainFrame.getLocation().getX() + e.getX() - pressX), (int) Math.round(mainFrame.getLocation().getY() + e.getY() - pressY));
然而,当拖动窗口时,存在相当多的滞后或某种问题。这是一个视频来展示视觉上发生的事情。
https://i.imgur.com/KWtbE1s.gifv
我正在使用swing库并使用大约每两毫秒滴答一次的Timer进行重新绘制。
修改
我修改了代码,使得这些点相对于JPanel,但问题仍然存在。
dragMe = new Draggable() {
private static final long serialVersionUID = 1L;
private Point press;
@Override
public void mouseClicked(MouseEvent e) {}
@Override
public void mousePressed(MouseEvent e) {
press = SwingUtilities.convertPoint(this, e.getPoint(), mainFrame);
}
@Override
public void mouseReleased(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}
@Override
public void mouseDragged(MouseEvent e) {
Point drag = SwingUtilities.convertPoint(this, e.getPoint(), mainFrame);
mainFrame.setLocation((int) Math.round(mainFrame.getLocation().getX() + drag.getX() - press.getX()), (int) Math.round(mainFrame.getLocation().getY() + drag.getY() - press.getY()));
}
@Override
public void mouseMoved(MouseEvent e) {}
};
编辑2:
不幸的是,我在这里创建的示例工作得很好,我不知道为什么它不能在真正的代码中工作。我甚至尝试将我在本例中创建的确切类复制到实际应用程序中,问题仍然出现在真正的代码中。
看起来我需要更多地了解这一点。
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.WindowConstants;
public class Test extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
private static JFrame frame;
public static void main(String[] args) {
class Draggable extends JPanel implements MouseListener, MouseMotionListener {
private static final long serialVersionUID = 1L;
private Point press;
public Draggable() {
addMouseListener(this);
addMouseMotionListener(this);
}
@Override
public void mouseClicked(MouseEvent e) {}
@Override
public void mousePressed(MouseEvent e) {
press = SwingUtilities.convertPoint(this, e.getPoint(), frame);
}
@Override
public void mouseReleased(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}
@Override
public void mouseDragged(MouseEvent e) {
Point drag = SwingUtilities.convertPoint(this, e.getPoint(), frame);
frame.setLocation((int) Math.round(frame.getLocation().getX() + drag.getX() - press.getX()), (int) Math.round(frame.getLocation().getY() + drag.getY() - press.getY()));
}
@Override
public void mouseMoved(MouseEvent e) {}
}
Test t = new Test();
t.setBounds(0, 0, 1200, 600);
t.setVisible(true);
Draggable drag = new Draggable();
drag.setBounds(24, 24, 24, 24);
drag.setVisible(true);
Timer repaintTimer = new Timer(2, t);
frame = new JFrame();
frame.setSize(1200, 600);
frame.add(t);
frame.add(drag);
Dimension dim = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLocation((dim.width - frame.getWidth()) / 2, (dim.height - frame.getHeight()) / 2);
frame.getContentPane().setLayout(null);
frame.setAlwaysOnTop(true);
frame.setResizable(false);
repaintTimer.start();
frame.setVisible(true);
frame.requestFocus();
}
@Override
public void actionPerformed(ActionEvent e) {
repaint();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(24, 24, 24, 24);
}
}
答案 0 :(得分:1)
查看Moving Windows以查找为您执行此操作的课程。
它比基本的拖动逻辑更复杂,因为它支持您可能不需要的其他功能。
在将侦听器添加到帧的一个(或多个)组件时拖动帧的基本逻辑(来自上面的类)将是:
MouseInputAdapter mia = new MouseInputAdapter()
{
Point location;
Point pressed;
public void mousePressed(MouseEvent me)
{
pressed = me.getLocationOnScreen();
Window window = SwingUtilities.windowForComponent(me.getComponent());
location = window.getLocation();
}
public void mouseDragged(MouseEvent me)
{
Point dragged = me.getLocationOnScreen();
int x = (int)(location.x + dragged.getX() - pressed.getX());
int y = (int)(location.y + dragged.getY() - pressed.getY());
Window window = SwingUtilities.windowForComponent(me.getComponent());
window.setLocation(x, y);
}
};
panel.addMouseListener(mia);
panel.addMouseMotionListener(mia);
编辑:
这是一些更通用的代码,允许您通过指定父组件来接收事件来直接或间接移动组件:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class BasicComponentMover extends MouseInputAdapter
{
/*
** A class that allows you to drag a component around a panel.
** Optionally you can specify a "parent" component, in which case
** the MouseEvents will be converted to be relative to this component
** which will then be dragged. This will allow you to drag a JFrame by
** dragging a component that has been added to the frame.
*/
private Component parent;
private Component destination;
private Point pressed;
BasicComponentMover() {}
{
}
BasicComponentMover(Component parent)
{
this.parent = parent;
}
@Override
public void mousePressed(MouseEvent me)
{
destination = (parent == null) ? me.getComponent() : parent;
pressed = SwingUtilities.convertPoint(me.getComponent(), me.getPoint(), destination);
}
@Override
public void mouseDragged(MouseEvent me)
{
Point location = destination.getLocation();
Point drag = SwingUtilities.convertPoint(me.getComponent(), me.getPoint(), destination);
int x = (int)(location.x - pressed.getX() + drag.getX());
int y = (int)(location.y - pressed.getY() + drag.getY());
destination.setLocation(x, y);
}
private static void createAndShowGUI()
{
JPanel background = new JPanel(null);
background.setPreferredSize(new Dimension(300, 300));
background.setSize(background.getPreferredSize());
background.setBackground(Color.RED);
JPanel foreground = new JPanel(null);
foreground.setPreferredSize(new Dimension(50, 50));
foreground.setSize(foreground.getPreferredSize());
foreground.setBackground(Color.BLUE);
background.add(foreground);
JFrame frame = new JFrame("BasicComponentMover");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
frame.add(background);
frame.setSize(500, 500);
frame.setLocationByPlatform( true );
frame.setVisible( true );
// Drag frame by dragging the red background panel
BasicComponentMover bcm1 = new BasicComponentMover(frame);
background.addMouseListener(bcm1);
background.addMouseMotionListener(bcm1);
// Drag the blue forground component around the red background
BasicComponentMover bcm2 = new BasicComponentMover();
foreground.addMouseListener(bcm2);
foreground.addMouseMotionListener(bcm2);
// Or, drage the background around the frame
BasicComponentMover bcm3 = new BasicComponentMover(background);
// foreground.addMouseListener(bcm3);
// foreground.addMouseMotionListener(bcm3);
}
public static void main(String[] args) throws Exception
{
EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
尝试拖动蓝色/红色组件以查看差异。