如何使Jpanel的所有区域都可拖动,包括JSVGCanvas

时间:2015-03-08 01:12:46

标签: java swing svg batik

我一直在关注本指南 http://softwareisart.blogspot.co.uk/2011/11/drag-and-drop-of-complex-custom-objects.html

使我的自定义Jpanels可拖动(通过拖动手势)但是由于某种原因,只有没有组件的JPanel区域是可拖动的。我有一个JSVGCanvas(来自蜡染库)里面有一些绘画,然后我将其添加到我的自定义JPanel中。

过去,为了让JPanel上的悬停事件突出显示,我会执行以下操作,将鼠标悬停事件从画布传递到外部jpanel,以解决此问题。

@Override public void mouseClicked(MouseEvent e){outside.dispatchEvent(e);}
        @Override public void mousePressed(MouseEvent e){outside.dispatchEvent(e);}
        @Override public void mouseReleased(MouseEvent e){outside.dispatchEvent(e);}

但是我不确定如何将拖动事件从画布传递到持有画布的jpanel。

是否可以将画布绑定到JPanel,这样当我点击Jpanel中的任何地方时,它会通过画布传递到JPanel?

由于

更新

嗨理查德。使用JLayer似乎很好,因为它现在包含JSVGCanvas和持有画布的JPanel。但我怎么能在这里拖动手势处理中添加拖动手势"位。我通常会在我的JPanel中添加一个拖动事件,如下所示。

DragSource ds = new DragSource();
    ds.createDefaultDragGestureRecognizer(SecondChoice,
            DnDConstants.ACTION_COPY, new DragGestureListImp());

    DragSource ds2 = new DragSource();
    ds2.createDefaultDragGestureRecognizer(FirstChoice,
            DnDConstants.ACTION_COPY, new DragGestureListImp());


    new MyDropTargetListImp(FirstChoice);
    new MyDropTargetListImp(SecondChoice);'

我的DragGestures

class DragGestureListImp implements DragGestureListener {

    @Override
    public void dragGestureRecognized(DragGestureEvent event) {

        Cursor cursor = null;
        CustomJPanel panel= (CustomJPanel) event.getComponent();



        if (event.getDragAction() == DnDConstants.ACTION_COPY) {
            cursor = DragSource.DefaultCopyDrop;
        }
        Canvas canvas= panel.getCanvas();

        event.startDrag(cursor, new TransferableCanvas(canvas));
    }
} //DragGestureListImp

MyDropTargetListImp就像这样。     class MyDropTargetListImp扩展了DropTargetAdapter实现             DropTargetListener {

    private DropTarget dropTarget;
    private CustomJPanel panel;

    public MyDropTargetListImp(CustomJPanel panel) {
        this.panel = panel;

        dropTarget = new DropTarget(panel, DnDConstants.ACTION_COPY, this,
                true, null);
    }


    public void drop(DropTargetDropEvent event) {
        try {

            System.out.println("dropped Event");
            Transferable tr = event.getTransferable();
            CustomJPanel an = (CustomJPanel) tr.getTransferData(dataFlavor);

            if (event.isDataFlavorSupported(dataFlavor)) {
                event.acceptDrop(DnDConstants.ACTION_COPY);

                this.panel.updateMyStuff(an)

                event.dropComplete(true);
                this.panel.validate();
                return;
            }
            event.rejectDrop();
        } catch (Exception e) {
            e.printStackTrace();
            event.rejectDrop();
        }
    } //drop
} //MyDropTargetListImp

错误:(281,21)java:不兼容的类型:java.awt.AWTEvent无法转换为java.awt.dnd.MouseDragGestureRecognizer

更新最终

JLayers帮助了我一点但我终于通过以下方式实现了它。 在Richard写的JLayer类中,我只是向canvas和JLayer添加了一个gestureListener,并为每个将JLayer传递给cavas的实现创建了单独的GesturesImplementations。

DragSource ds = new DragSource();
    // create a component to be decorated with the layer
    // This would be your custom component.
    CustomPanel customPanel = new CustomPanel (index, information);
    //customPanel.add(new JButton("JButton"));

    JLayer tempLayerUI = new JLayer<JComponent>(customPanel, layerUI);

    ds.createDefaultDragGestureRecognizer(customPanel.canvas,
            DnDConstants.ACTION_COPY, new DragGestureListImp1(tempLayerUI));

    ds.createDefaultDragGestureRecognizer(tempLayerUI,
            DnDConstants.ACTION_COPY, new DragGestureListImp());

return tempLayerUI;

阿里

1 个答案:

答案 0 :(得分:0)

在Java 7或更高版本中,您应该能够将JPanel包装在一个JLayer实例中,该实例拦截当前转到JSVGCanvas的鼠标事件。这将允许您在包装器中执行拖动手势处理。

以下是https://docs.oracle.com/javase/7/docs/api/javax/swing/JLayer.html

的示例代码的改编版本
public class JLayerSample {

    private static JLayer<JComponent> createLayer() {
        // This custom layerUI will intercept all mouseMotion events generated within its borders and delegate to the wrapped JPanel
        LayerUI<JComponent> layerUI = new LayerUI<JComponent>() {

            public void installUI(JComponent c) {
                super.installUI(c);
                // enable mouse events for the layer's subcomponents
                ((JLayer) c).setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK);
            }

            public void uninstallUI(JComponent c) {
                super.uninstallUI(c);
                // reset the layer event mask
                ((JLayer) c).setLayerEventMask(0);
            }

            // overridden method which catches MouseMotion events
            public void eventDispatched(AWTEvent e, JLayer<? extends JComponent> l) {
                if (e instanceof MouseEvent) {
                    System.out.println("MouseEvent detected " + e);
                    // Do drag gesture processing here.
                    // Note, you cannot dispatch these events to the view component, since that
                    // creates an event loop.
                }
            }
        };

        // create a component to be decorated with the layer
        // This would be your custom component.
        JPanel panel = new JPanel();
        panel.add(new JButton("JButton"));

        // create the layer for the panel using our custom layerUI
        return new JLayer<JComponent>(panel, layerUI);
    }

    private static void createAndShowGUI() {
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // work with the layer as with any other Swing component
        frame.add(createLayer());

        frame.setSize(200, 200);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) throws Exception {
        SwingUtilities.invokeAndWait(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}