3

我目前正在编写我的一个小型“绘画”程序;到目前为止,你可以用笔在上面画画,放大到 100 倍,然后选择一种颜色。接下来我想添加的是(或者是)拖动 JPanel 子类的可能性,在该子类上绘制选择要编辑的图像。基本上,通过按住鼠标右键,您可以更改位于 JInternalFrame 上的 JPanel 子类的位置。我有一个应该可以自己正常工作的代码示例;至少它对我有用。要重现该问题,只需启动DragPanelTest类并在带有红色边框的组件上拖动鼠标 - 面板不会平滑拖动,而是一直来回跳跃。

代码:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.BorderFactory;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class DragPanelTest extends JPanel implements MouseMotionListener, MouseListener {
    Point oldDragPt;
    boolean dragEnabled;
    int newX;
    int newY;

    public static void main(String[] args) {
        System.out.println("Launching Test.java ...");

        JFrame frame = new JFrame("Title");
        JInternalFrame intFrame = new JInternalFrame("title", true, true, true, true);
        JDesktopPane deskPane = new JDesktopPane();
        DragPanelTest dragPanel = new DragPanelTest();

        frame.setSize(300, 300);;
        frame.setLayout(null);
        frame.setVisible(true);
        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
        int x = (d.width - frame.getWidth()) / 2;
        int y = (d.height - frame.getHeight()) / 2;
        frame.setLocation(x, y);

        deskPane.setBounds(50, 50, 200, 200);
        deskPane.setBorder(BorderFactory.createLineBorder(Color.BLACK));
        frame.add(deskPane);


        deskPane.add(intFrame);
        intFrame.setSize(150, 150);
        intFrame.add(dragPanel);
        intFrame.setVisible(true);
    }

    public DragPanelTest() {
        this.setSize(100,100);
        this.setBorder(BorderFactory.createLineBorder(Color.RED));
        this.addMouseListener(this);
        this.addMouseMotionListener(this);
    }

    public void mousePressed(MouseEvent e) {
        if (e.isMetaDown()) {
            dragEnabled = true;
            oldDragPt = new Point((int) this.getMousePosition().getX(), (int) this.getMousePosition().getY());
        }
        repaint();
    }

    public void mouseReleased(MouseEvent e) {
        dragEnabled = false;
        oldDragPt = null;
    }

    public void mouseDragged(MouseEvent e) {
        if (e.isMetaDown() && this.getMousePosition() != null) {
            if (oldDragPt != null) {
                if (dragEnabled) {
                    int mouseX = (int) this.getMousePosition().getX();
                    int mouseY = (int) this.getMousePosition().getY();
                    int x = this.getX();
                    int y = this.getY();
                    int diffX = (mouseX - (int) oldDragPt.getX());
                    int diffY = (mouseY - (int) oldDragPt.getY());
                    newX = getX() + diffX;
                    newY = getY() + diffY;
                    this.setLocation(newX, newY);
                    this.repaint();
                    oldDragPt = new Point(mouseX, mouseY);
                }
            } else {
                oldDragPt = new Point((int) this.getMousePosition().getX(), (int) this.getMousePosition().getY());
            }
        }
    }

    public void mouseClicked(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
    public void mouseMoved(MouseEvent e) {} 
}

请注意,我省略了一些System.out.println()@Override命令以稍微缩短代码。

无论如何,如果有人知道我做错了什么/需要改进的地方,我将非常感激!

4

2 回答 2

5

面板拖动不顺畅,而是一直来回跳跃。

当您因为鼠标和组件与父面板之间的相对移动关闭而跳转时。您的代码太复杂,无法指出导致问题的确切行。

在面板周围拖动组件的基本代码是:

public class DragListener extends MouseInputAdapter
{
    Point location;
    MouseEvent pressed;

    public void mousePressed(MouseEvent me)
    {
        pressed = me;
    }

    public void mouseDragged(MouseEvent me)
    {
        Component component = me.getComponent();
        location = component.getLocation(location);
        int x = location.x - pressed.getX() + me.getX();
        int y = location.y - pressed.getY() + me.getY();
        component.setLocation(x, y);
     }
}

对于具有更多功能的更高级代码,您还可以查看Moving WindowsComponent Mover中的类。

于 2016-04-04T18:56:47.653 回答
0

我在移动滚动窗格的视口时遇到了类似的问题。我认为当重新定位组件时,保存点的值是相对于原始位置的,相对于新位置是不正确的。我的解决方案对我来说似乎不合逻辑,使拖动操作顺利进行。我所做的是将点增量添加回保存的位置。

这是拖动视口的基本代码:

Point priorPanPoint;

public void mouseDragged(MouseEvent e) {
    Point newPt = subtractPoints(priorPanPoint, e.getPoint());
    priorPanPoint = addPoints(e.getPoint(), newPt);
    newPt = addPoints(getVisibleRect().getLocation(), newPt);
    viewport.setViewPosition(newPt);
}

public void mousePressed(MouseEvent e) {
    priorPanPoint = e.getPoint();
}

private Point addPoints(Point p1, Point p2) {
    return  new Point(p1.x + p2.x, p1.y + p2.y); }

private Point subtractPoints(Point p1, Point p2) {
    return new Point(p1.x - p2.x, p1.y - p2.y);
}
于 2017-05-11T04:45:51.537 回答