垂直视图中的可拖动组件 (Java Swing)

Posted

技术标签:

【中文标题】垂直视图中的可拖动组件 (Java Swing)【英文标题】:DraggableComponents in vertical view (Java Swing) 【发布时间】:2020-04-05 17:02:18 【问题描述】:

这是我在这个平台上的第一个问题,请耐心等待:

我正在使用 Java Swing 制作一个 LayerPanel,就像在 Photoshop 中一样,LayerPanel 的每个子项也是一个代表一个图层的面板。就像在 Photoshop 中一样,我使用鼠标移动 LayerPanel 的这些子项,使用 DraggableComponent 类的灵感来自:输入图像描述 heregable-component>。

问题在于重新排列 UI 中的图层。我无法在 UI 中切换面板。

这是我目前的代码:

可拖动组件:

class DraggableComponent extends JPanel implements MouseListener, MouseMotionListener 

    private LayerPanel panel;

    private volatile int screenY = 0;
    private volatile int myY = 0;

    private String name;

    public DraggableComponent(LayerPanel panel, String name) 
        setPreferredSize(new Dimension(300, 80));
        this.name = name;
        this.panel = panel;
        updateBorder(name);
        setVisible(true);

        setLayout(null);

        addMouseListener(this);
        addMouseMotionListener(this);
    

    private void updateBorder(String name) 
        setBorder(new TitledBorder(new DropShadowBorder(), name, TitledBorder.LEADING, TitledBorder.BELOW_TOP, null, null));
    

    private void handleLocation(int y) 
        if (y >= getParent().getHeight() - this.getHeight()) 
            setLocation(getLocation().x, getParent().getHeight() - this.getHeight());
         else setLocation(getLocation().x, Math.max(y, 0));
    

    @Override
    public void mousePressed(MouseEvent e) 
        screenY = e.getYOnScreen();
        myY = getY();
    

    @Override
    public void mouseReleased(MouseEvent e) 
        panel.handleReleased(this);
    

    @Override
    public void mouseDragged(MouseEvent e) 
        int deltaY = e.getYOnScreen() - screenY;

        handleLocation(myY + deltaY);
        panel.handleLocation(this);
    

    public void rename(String name) 
        this.name = name;
        updateBorder(name);
    

LayerPanel 类:

public class LayerPanel extends JPanel 

    private ArrayList<DraggableComponent> components = new ArrayList<>();
    protected int HEIGHT_PER_COMPONENT;

    public LayerPanel(int height, int amountOfComponents) 
        setPreferredSize(new Dimension(200, height));
        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

        for (int i = 0; i < 10; i++) 
            components.add(new DraggableComponent(this, Integer.toString(i)));
        

        updateComponents();
    

    public void addComponent(String name) 
        components.add(new DraggableComponent(this, name));
        updateComponents();
    

    private void updateComponents() 
        HEIGHT_PER_COMPONENT = getHeight() / (components.size() + 1);
        removeAll();

        for (DraggableComponent c : components) 
            //c.rename(Integer.toString(components.indexOf(c)));
            add(c);
            c.setLocation(0, HEIGHT_PER_COMPONENT * components.indexOf(c));
        
    

    public void handleReleased(DraggableComponent component) 
        updateComponents();
    

    public void handleLocation(DraggableComponent component) 
        final int index = components.indexOf(component);

        for (DraggableComponent nextComponent : components) 
            final int indexNext = components.indexOf(nextComponent);
            if (component.getY() >= nextComponent.getY() - HEIGHT_PER_COMPONENT / 2 && !component.equals(nextComponent)) 
                Collections.swap(components, indexNext, indexNext - 1);
                updateComponents();
            
        
    

    public static void main(String[] args) 
        JFrame f = new JFrame("Layers test");

        LayerPanel panel = new LayerPanel(800, 10);

        f.add(panel);
        f.setSize(300, 800);
        f.setLocationRelativeTo(null);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    

【问题讨论】:

【参考方案1】:

问题在于重新排列图层。

无需自己管理。

这由面板中组件的ZOrder 控制。

在您的mousePressed 事件中,您可以将组件的ZOrder 设置为0,以确保该组件最后绘制,这意味着它现在将绘制面板上所有其他组件的顶部。

类似:

Container container = e.getComponent().getParent();
container.setComponentZOrder(e.getComponent(), 0);

【讨论】:

这实际上有助于解决我将要遇到的第二个问题,但我的问题在于 UI 而不是实际绘图。我的意思是用鼠标重新排列 UI 元素。它们仍然符合布局。修复后,我必须实现这一点。感谢您回复@camickr(编辑:我会在此页面的问题部分更好地指定)

以上是关于垂直视图中的可拖动组件 (Java Swing)的主要内容,如果未能解决你的问题,请参考以下文章

Java Swing:具有固定宽度和可变高度的垂直布局

用于在 Java 中拖动组件的 Swing 库

使组件对 Swing 中的拖动不那么敏感

使用 UIPanGestureRecognizer 的可拖动视图中的操作元素导致视图移动

java swing JPanel添加在JScrollPane上,有垂直的滚动条,可是滚动条拉到底,只显示了JPanel的一部分。

jQuery-ui 可拖动滚动仅垂直