在 JScrollPane 中手动移动 JComponent

Manually movable JComponent in a JScrollPane

我正在尝试制作一个程序,允许用户在 JScrollPane 中手动放置和调整组件大小,这是一个特殊情况 UI Builder。我设法制作了一个自定义 JPanel class,允许用户手动移动它,但是当它被添加到 JScrollPane 并四处移动时,如果它超出 JScrollPane 的视觉范围,则滚动条不会出现或调整。

这是我的主要 class,其中包括 JFrame 和 JScrollPane。

package quickscrolltest;

import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class QuickScrollTest {

    JFrame wnd;
    JScrollPane scroll;
    JPanel pnl;
    MovablePanel pnl1;

    public QuickScrollTest() {
        wnd = new JFrame();
        scroll = new JScrollPane();
        pnl = new JPanel();
        pnl.setLayout(null);
        scroll.setViewportView( pnl );
        wnd.setContentPane(scroll);
        wnd.pack();
        pnl1 = new MovablePanel();
        Dimension dim1 = new Dimension( 300, 400 );
        pnl1.setSize( dim1 );        
        pnl1.setPreferredSize(dim1);
        pnl1.setBackground( Color.CYAN );
        pnl1.setLocation( 10, 10 );
        /*scroll.getViewport().add(pnl1,null);*/
        pnl.add(pnl1);
        wnd.setSize( 800, 600 );
        wnd.setLocationRelativeTo(null);
        wnd.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        wnd.setVisible(true);
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        new QuickScrollTest();
    }

}

这里是 MovablePanel class

package quickscrolltest;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JPanel;

public class MovablePanel extends JPanel implements MouseListener, MouseMotionListener {

    Color bg = Color.GRAY;
    Point clickPoint;

    public MovablePanel() {
        addMouseListener(this);
        addMouseMotionListener(this);
    }

    @Override
    public void setBackground( Color col ) {
        super.setBackground(col);
        bg = col;
    }

    @Override
    public void mouseClicked(MouseEvent e) {}

    @Override
    public void mousePressed(MouseEvent e) {
        clickPoint = e.getPoint();
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        setCursor( Cursor.getDefaultCursor() );
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        setCursor( Cursor.getPredefinedCursor(Cursor.HAND_CURSOR) );
        super.setBackground( Color.RED );
    }

    @Override
    public void mouseExited(MouseEvent e) {
        setCursor( Cursor.getDefaultCursor() );
        super.setBackground( bg );
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        setCursor( Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR) );
        int lastX = getX() - (int) clickPoint.getX();
        int lastY = getY() - (int) clickPoint.getY();
        setLocation(lastX + e.getX(), lastY + e.getY() );
    }

    @Override
    public void mouseMoved(MouseEvent e) {}  

}

如何让用户可以在 JScrollPane 中自由移动组件并根据需要更新滚动条?

我的最终代码将有一个独立的 mouselistener/mousemotionlistener class,它通常适用于给定的 JComponent,但为了简单起见,我将侦听器直接编码到 JPanel 中。

谢谢

当显示在滚动窗格视口中的组件的首选大小发生变化时,自动 appear/disappear 滚动条。

可以使用Drag Layout。 class 是一个自定义布局管理器,当组件在面板周围拖动时,它会自动重新计算面板的首选大小。

您将需要处理 mouseReleased 事件以便您可以 revalidate() 面板,并在完成拖动组件后调用 DragLayout 以便重置首选大小.或者您可以使用博客文章中引用的 ComponentMover class 为您拖动组件。它支持 auto resize 属性,它将为您执行 revalidate()。