Перетаскивание JFrame из пользовательской кнопки не плавно - PullRequest
0 голосов
/ 20 мая 2018

Я использую практически тот же метод перемещения JFrame, что и Java - перетаскиваемый 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

Я использую библиотеку свинга и перерисовываю с использованием таймера, который тикает примерно каждые две миллисекунды.

Редактировать:

Я изменил код так, чтобы точки были относительно 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);
    }

}

1 Ответ

0 голосов
/ 20 мая 2018

Проверьте Перемещение 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();
            }
        });
*/
    }
}

Попробуйте перетащить синий / красный компоненты, чтобы увидеть разницу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...