2

在我的程序中,在尝试获取拖放对象上的拖动数据时,程序在包含所有 StepPanel 的面板中创建新的 StepPanel 时变慢。我跟踪了代码,发现使程序变慢的是方法 getTransferData(DataFlavour df)。我在 Internet 上搜索了该问题,然后找到了 Oracle 提供的解决方案。解决方案页面说:

问题:当 Java 应用程序使用 Transferable.getTransferData() 进行 DnD 操作时,拖动似乎需要很长时间。为了只在需要时初始化传输的数据,初始化代码放在 Transferable.getTransferData() 中。

可传输数据的生成成本很高,并且在 DnD 操作期间,Transferable.getTransferData() 被多次调用,导致速度变慢。

解决方案:缓存Transferable数据,使其只生成一次。

但我找不到如何缓存可传输数据。有谁曾经为这个问题而苦苦挣扎过?我真的需要防止程序在这个问题上变慢。如果除了缓存可传输数据之外还有其他解决方案,我将不胜感激。谢谢你。

还有 StepPanel 代码:

public class StepPanel extends JPanel implements Transferable, DragSourceListener, DragGestureListener, DropTargetListener{

private DragSource      source;
private TransferHandler transfer;
private DropTarget      dropTarget;

StepContainer       statementStep;
StepContainerPanel  mainPanel;
JButton             add;
JButton             maximize;
JButton             remove;
JTextArea           stepCommand;
ImageIcon           removeIcon;
ImageIcon           maximizeIcon;
ImageIcon           addIcon;
JPanel              eastPanel;

public StepPanel( StepContainer step) /*throws MalformedURLException*/ {

    setLayout( new BorderLayout());
    setBackground(Color.WHITE);

    statementStep = step;

    removeIcon = new ImageIcon( "src/jlfgr-1_0/toolbarButtonGraphics/general/Delete24.gif");
    maximizeIcon = new ImageIcon( "src/jlfgr-1_0/toolbarButtonGraphics/general/ZoomIn24.gif");
    addIcon = new ImageIcon( "src/jlfgr-1_0/toolbarButtonGraphics/general/Add24.gif");

    eastPanel = new JPanel();
    add = new JButton( addIcon);
    maximize = new JButton( maximizeIcon);
    remove = new JButton( removeIcon);
    stepCommand = new JTextArea();

    stepCommand.setPreferredSize( new Dimension( StepContainer.WIDHT, StepContainer.HEIGHT));
    stepCommand.setBorder( BorderFactory.createLineBorder( Color.BLACK));

    add.addActionListener( new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {

            statementStep.addSubStep();
            ((StepContainerPanel)getParent().getParent().getParent().getParent().getParent()).updateView();
        }  
    });

    maximize.addActionListener( new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {

            ((StepContainerPanel)getParent().getParent().getParent().getParent().getParent()).setStepContainer( statementStep);
            ((StepContainerPanel)getParent().getParent().getParent().getParent().getParent()).updateView();

        }
    });

    remove.addActionListener( new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {

            statementStep.removeMe();
            ((StepContainerPanel)getParent().getParent().getParent().getParent().getParent()).updateView();
        }
    });

    //Setting tool tips to the buttons
    maximize.setToolTipText( "Click this button to maximize");
    remove.setToolTipText( "Remove this step");
    add.setToolTipText( "Add a sub-step");

    //East Panel
    eastPanel.setLayout( new GridLayout());
    eastPanel.add( add);     
    eastPanel.add( remove);
    eastPanel.setBackground( getBackground());

    //StepPanel
    add( maximize, BorderLayout.WEST);
    add( eastPanel, BorderLayout.EAST);
    add( stepCommand, BorderLayout.CENTER);

    //The Properties for Drag and Drop

    //setting transferhandler to the panel
    transfer = new TransferHandler() {

        @Override
        public Transferable createTransferable( JComponent c) {

            return new StepPanel( statementStep);
        }
    };
    setTransferHandler( transfer);

    source = new DragSource();
    source.createDefaultDragGestureRecognizer( this, DnDConstants.ACTION_COPY_OR_MOVE, this);

    //setting drop data
    dropTarget = new DropTarget( this, this);
}

@Override
public void paintComponent( Graphics g) {

    super.paintComponent( g);

    setBorder( BorderFactory.createTitledBorder(statementStep.getBorderText()));
    setToolTipText( statementStep.getBorderText());
}

public JButton getRemove() {

    return remove;
}

public StepContainer getStep() {

    return statementStep;
}

@Override
public DataFlavor[] getTransferDataFlavors() {

    return new DataFlavor[]{ new DataFlavor( StepPanel.class, "Step")};
}

@Override
public boolean isDataFlavorSupported( DataFlavor df) {

    return true;
}

//when this method is called it returns this object
@Override
public Object getTransferData( DataFlavor df) throws UnsupportedFlavorException, IOException {

    return this;
}

@Override
public void dragEnter(DragSourceDragEvent dsde) {}
@Override
public void dragOver(DragSourceDragEvent dsde) {}
@Override
public void dropActionChanged(DragSourceDragEvent dsde) {}
@Override
public void dragExit(DragSourceEvent dse) {}
@Override
public void dragDropEnd(DragSourceDropEvent dsde) {}

@Override
public void dragGestureRecognized(DragGestureEvent dge) {

    source.startDrag( dge, DragSource.DefaultMoveDrop, this, this);
}

@Override
public void dragEnter(DropTargetDragEvent dtde) {}
@Override
public void dragOver(DropTargetDragEvent dtde) {}
@Override
public void dropActionChanged(DropTargetDragEvent dtde) {}
@Override
public void dragExit(DropTargetEvent dte) {}

@Override
public void drop(DropTargetDropEvent dtde) {

    //getting the dragged step from dataFlavor and synchroning it if this
    //step has same parent with dropped step then change their order

    //getting and initalizing dragged step
    Transferable transferedPanel = dtde.getTransferable();
    DataFlavor[] datas = transferedPanel.getTransferDataFlavors();

    try {
        //its dragged panel, which is in the 0th index of DataFlavor array
        StepPanel draggedPanel = ((StepPanel)transferedPanel.getTransferData( datas[0]));

        //since the dragged step will come as if it is different object
        //we cannot compare their parents directly since it will give
        //wrong comparison. So we look order of parent step of both dragged 
        //and dropped step
        if( statementStep.getParent().getBorderText().equals( draggedPanel.getStep().getParent().getBorderText())) {

            StepContainer sameParent = statementStep.getParent();

            int indexOfFirstSubStep = statementStep.getParent().getSubSteps().indexOf( statementStep);
            int indexOfSecondSubStep = draggedPanel.getStep().getParent().getSubSteps().indexOf( draggedPanel.getStep());
            System.out.println( "We ");
            sameParent.changeOrders( indexOfFirstSubStep, indexOfSecondSubStep);
        }
        else {

            System.out.println( "We cannot change those steps' orders since their parents are different");
        }
    } catch (UnsupportedFlavorException ex) {

        Logger.getLogger(StepPanel.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {

        Logger.getLogger(StepPanel.class.getName()).log(Level.SEVERE, null, ex);
    }
}

}

4

0 回答 0