拖放以在 JPanel 上移动 JTextArea

我希望能够单击 JTextArea 并将其拖动到我的 JPanel 周围.我不确定这样做的方法.我想要做的是更改 JTextArea 的 x,y 坐标,因为它被拖动,我没有将 JTextArea 拖动到另一个上方或下方.就在屏幕上,类似于在 Microsoft PowerPoint 等程序中移动文本框

I want to be able to click on a JTextArea and drag it around my JPanel. I'm not sure the method on doing so. What I'm trying to do is change the x,y coordinates of the JTextArea as it is dragged, I'm not dragging a JTextArea above or below another. Just around on the screen, similar to moving Text Boxes in a program like Microsoft PowerPoint

我能想到的唯一方法是使用 MouseListener 但我想知道除了检测 JTextArea 上的悬停/按下/拖动之外,是否有更简单的方法来实现它.关于如何开始的任何想法?

The only method I can think of is using a MouseListener but I'm wondering if there is an easier way to implement it other than detecting a hover/press/drag on the JTextArea. Any ideas on how I can start?

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextArea;

public class UMLEditor {

    public static void main(String[] args) {
        JFrame frame = new UMLWindow();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBounds(30, 30, 1000, 700);
        frame.getContentPane().setBackground(Color.white);
        frame.setVisible(true);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

class UMLWindow extends JFrame {
    Canvas canvas = new Canvas();

    private static final long serialVersionUID = 1L;

    public UMLWindow() {
        addMenus();
    }

    public void addMenus() {

        getContentPane().add(canvas);

        JMenuBar menubar = new JMenuBar();

        JMenuItem newTextBox = new JMenuItem("New Text Box");
        newTextBox.setMnemonic(KeyEvent.VK_E);
        newTextBox.setToolTipText("Exit application");
        newTextBox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                canvas.addTextBox();
            }
        });

        menubar.add(newTextBox);

        setJMenuBar(menubar);

        setSize(300, 200);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
}

class Canvas extends JPanel {

    JTextArea commentTextArea = new JTextArea(10, 10);

    public Canvas() {
        this.setOpaque(true);
        MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
        addMouseListener(myMouseAdapter);
        addMouseMotionListener(myMouseAdapter);
    }

    public void addTextBox() {

        commentTextArea.setLineWrap(true);
        commentTextArea.setWrapStyleWord(true);
        commentTextArea.setVisible(true);
        commentTextArea.setLocation(0, 0);
        this.add(commentTextArea);
        commentTextArea.setBounds(0, 0, 100, 100);

        revalidate();
        repaint();
    }

    class MyMouseAdapter extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent e) {

        }

        @Override
        public void mouseDragged(MouseEvent e) {

        }

        @Override
        public void mouseMoved(MouseEvent e) {

        }
    }
}

推荐答案

你并不想尝试在 JTextComponent 上拖动",它们已经启用了允许用户单击并拖动以突出显示文本,您真的不想在其中竞争.

You don't really want to try and "drag" on JTextComponents, they already have functionality enabled which allows the user to click and drag to highlight text, you really don't want to be competing within this.

相反,您想在组件周围定义一个热区"区域,这将允许您突出显示"某些组件并允许用户通过它拖动组件.

Instead, you want to define a "hot zone" area around the component which would allow you "highlight" the component in some and allow the user to drag the component via it.

例如...

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;

public class DragMe {

    public static void main(String[] args) {
        new DragMe();
    }

    public DragMe() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JTextArea ta = new JTextArea(10, 20);
                ta.setText("Bananas in pajamas");
                JScrollPane sp = new JScrollPane(ta);

                DragProxyPane proxy = new DragProxyPane(sp);
                proxy.setSize(proxy.getPreferredSize());
                proxy.setLocation(100 - proxy.getWidth() / 2, 100 - proxy.getHeight()/ 2);

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setContentPane(new JPanel() {
                    @Override
                    public Dimension getPreferredSize() {
                        return new Dimension(300, 300);
                    }
                });
                frame.add(proxy);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class DragProxyPane extends JPanel {

        public static final int BUFFER_ZONE = 10;

        private boolean mouseInHouse;
        private JComponent component;

        private List<HotZone> hotZones;

        public DragProxyPane(JComponent comp) {
            MouseAdapter ma = new MouseAdapter() {

                @Override
                public void mouseEntered(MouseEvent e) {
                    mouseInHouse = true;
                    repaint();
                }

                @Override
                public void mouseExited(MouseEvent e) {
                    mouseInHouse = false;
                    repaint();
                }

                @Override
                public void mouseMoved(MouseEvent e) {
                    Cursor cursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
                    for (HotZone hz : hotZones) {
                        if (hz.getBounds(getSize()).contains(e.getPoint())) {
                            cursor = hz.getCursor();
                            break;
                        }
                    }
                    setCursor(cursor);
                }

            };

            addMouseListener(ma);
            addMouseMotionListener(ma);

            setOpaque(false);
            setLayout(new BorderLayout());
            add(comp);

            setBorder(new EmptyBorder(BUFFER_ZONE, BUFFER_ZONE, BUFFER_ZONE, BUFFER_ZONE));

            hotZones = new ArrayList<>(8);
            // Top left, middle, right
            hotZones.add(new HotZone(0f, 0f, Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR)));
            hotZones.add(new HotZone(0.5f, 0f, Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)));
            hotZones.add(new HotZone(1f, 0f, Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR)));
            // Left, right
            hotZones.add(new HotZone(0f, 0.5f, Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR)));
            hotZones.add(new HotZone(1f, 0.5f, Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)));
            // Bottom left, middle, right
            hotZones.add(new HotZone(0f, 1f, Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR)));
            hotZones.add(new HotZone(0.5f, 1f, Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR)));
            hotZones.add(new HotZone(1f, 1f, Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR)));

        }


        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            if (mouseInHouse) {
                g2d.setColor(Color.BLACK);
                for (HotZone hotZone : hotZones) {
                    g2d.draw(hotZone.getBounds(getSize()));
                }
            }
            g2d.dispose();
        }

        public class HotZone {

            private float x, y;
            private Cursor cursor;

            public HotZone(float x, float y, Cursor cursor) {
                this.x = x;
                this.y = y;
                this.cursor = cursor;
            }

            public Cursor getCursor() {
                return cursor;
            }

            public Rectangle getBounds(Dimension size) {

                return getBounds(size.width - 1, size.height - 1);

            }

            public Rectangle getBounds(int width, int height) {

                int halfBuffer = BUFFER_ZONE / 2;

                float xPos = (width * x) - halfBuffer;
                float yPos = (height * y) - halfBuffer;

                xPos = Math.min(Math.max(0, xPos), width - BUFFER_ZONE);
                yPos = Math.min(Math.max(0, yPos), height - BUFFER_ZONE);

                return new Rectangle(Math.round(xPos), Math.round(yPos), BUFFER_ZONE, BUFFER_ZONE);

            }

        }

    }

}

这设置了一个简单的代理组件,它充当热区管理器,检测鼠标进出它并根据光标在其中的位置更新光标,但不会破坏组件的正常操作.

This sets up a simple proxy component which acts as the hot zone manager, detecting the mouse coming into or out of it and updating the cursor based on its location within in it, but it does not disrupt the normal operations of the component.

现在,这个例子没有拖拽,抱歉,你有很多其他的例子可以让你越界,但是,你可以简单地添加一个 MouseListener/MouseMoitionListener 到代理以检测用户何时拖动,但您需要向其添加更多功能以确定拖动的实际含义(调整大小或移动);)

Now, this example doesn't drag, sorry, you have plenty of other examples which should be able to get you over the line, but, you could simply add a MouseListener/MouseMoitionListener to the proxy to detect when the user drags, but you will need to add some more functionality to it to determine what that drag actually means (resize or move) ;)

相关文章