【问题标题】:Layouting a large number of draw2d widgets in a Canvas在 Canvas 中布局大量 draw2d 小部件
【发布时间】:2013-06-13 07:14:42
【问题描述】:

我们面临一个问题,即在单个 Canvas 中处理大量 Draw2d 图形。我们正在构建一个节点树,在父节点和子节点之间建立连接。画布中的数字数量约为 10000(仅“节点”数字,还有大约 10000 个“连接”数字,我没有计算在内)。

我在图片中附上了我们其中一张图表的一部分:

问题是这样的:树中的节点可以折叠或展开。当树中的节点数量约为 1000-2000 时,会立即发生折叠/展开。但是,当节点数增加时,折叠/展开任何特定节点需要越来越多的时间,这很烦人。

我已经编写了一些示例代码来查看问题是否出在我们的代码上,或者随着小部件数量的增加,draw2d 的性能通常会下降。示例应用程序中也存在同样的问题,这表明我们可能必须在 draw2d 代码库本身内进行一些优化。我在 Eclipse 中制作了一个 View 来证明这一点。下面附上相同的代码。

import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.Cursors;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.GridData;
import org.eclipse.draw2d.GridLayout;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.MouseEvent;
import org.eclipse.draw2d.MouseListener;
import org.eclipse.draw2d.Panel;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;

public class View extends ViewPart {
    public static final String ID = "GridLayoutTest.view";

    /**
     * This is a callback that will allow us to create the viewer and initialize
     * it.
     */
    public void createPartControl(Composite parent) {
        Composite composite = new Composite(parent, SWT.NONE);
        composite.setLayout(new FillLayout());
        FigureCanvas canvas = new FigureCanvas(composite);
        Figure baseFigure = new Figure();
        baseFigure.setLayoutManager(new GridLayout(3, true));
        Panel contentPanel = new Panel();
        contentPanel.setLayoutManager(new GridLayout(1, true));
        baseFigure.add(new Figure());
        baseFigure.add(contentPanel);
        baseFigure.add(new Figure());
        fillContents(contentPanel);
        canvas.setContents(baseFigure);
    }

    private void fillContents(Panel contentPanel) {
        int margin;
        String text;
        CollapsibleFigure prevParent = null;
        for(int i = 1; i <= 2500; i++) {
            if(i%5 == 1) {
                text = "Parent " + (i/5 + 1);
                margin = 50;
                prevParent = new CollapsibleFigure(contentPanel, text, margin);
            } else {
                text = "Child " + (i%5 - 1);
                margin = 100;
                CollapsibleFigure child = new CollapsibleFigure(contentPanel, text, margin);
                prevParent.addChild(child);
            }
        }

        for(int i = 2501; i <= 7500; i++) {
            if(i == 2501) {
                text = "Parent " + (i/5 + 1);
                margin = 50;
                prevParent = new CollapsibleFigure(contentPanel, text, margin);
            } else {
                text = "Child " + (i - 2501);
                margin = 100;
                CollapsibleFigure child = new CollapsibleFigure(contentPanel, text, margin);
                prevParent.addChild(child);
            }
        }

        for(int i = 7501; i <= 10000; i++) {
            if(i%5 == 1) {
                text = "Parent " + (i/5 + 1);
                margin = 50;
                prevParent = new CollapsibleFigure(contentPanel, text, margin);
            } else {
                text = "Child " + (i%5 - 1);
                margin = 100;
                CollapsibleFigure child = new CollapsibleFigure(contentPanel, text, margin);
                prevParent.addChild(child);
            }
        }
    }

    private class CollapsibleFigure extends Panel {
        private List<CollapsibleFigure> children; 

        private int margin;

        private CollapsibleFigure(Panel contentPanel, String text, int margin) {
            children = new ArrayList<CollapsibleFigure>();
            setBorder(new LineBorder(2));
            setBackgroundColor(new Color(null, 255, 255, 255));
            this.margin = margin;
            GridLayout layout = new GridLayout(2, false);
            GridData layoutData;
            setLayoutManager(layout);
            Label label;
            label = new Label();
            label.setText("x");
            add(label);
            label.setCursor(Cursors.HAND);
            label.addMouseListener(new MouseListener.Stub() {
                public void mouseReleased(MouseEvent e) {
                    Label label = (Label) e.getSource();
                    if(label.getText().equals("x"))
                        collapseChildren();
                    else
                        showChildren();
                }
            });
            label = new Label();
            label.setText(text);
            add(label);
            layoutData = new GridData(SWT.CENTER, SWT.CENTER, true, true);
            layout.setConstraint(label, layoutData);
            label = new Label();
            label.setText("Some Content");
            add(label);
            layoutData = new GridData(SWT.CENTER, SWT.CENTER, true, true);
            layoutData.horizontalSpan = 2;
            layout.setConstraint(label, layoutData);
            contentPanel.add(this);
            layoutData = new GridData(SWT.BEGINNING, SWT.CENTER, false, true);
            layoutData.horizontalIndent = margin;
            contentPanel.getLayoutManager().setConstraint(this, layoutData);
        }

        private void addChild(CollapsibleFigure child) {
            children.add(child);
        }

        private void collapseChildren() {
            Panel contentPanel = (Panel) getParent();
            for(CollapsibleFigure child : children)
                contentPanel.remove(child);
            ((Label)(getChildren().get(0))).setText(">");
        }

        private void showChildren() {
            Panel contentPanel = (Panel) getParent();
            int index = contentPanel.getChildren().indexOf(this) + 1;
            for(CollapsibleFigure child : children) {
                contentPanel.add(child, index);
                GridData layoutData = new GridData(SWT.BEGINNING, SWT.CENTER, false, true);
                layoutData.horizontalIndent = margin + 50;
                contentPanel.getLayoutManager().setConstraint(child, layoutData);
                index++;
            }
            ((Label)(getChildren().get(0))).setText("x");
        }
    }

    @Override
    public void setFocus() {

    }
}

尝试在视图中展开/折叠图形(通过单击“x”或“>”按钮),这需要时间(不会立即发生)。谁能提供一些关于如何解决这个问题的指示?

【问题讨论】:

    标签: java layout swt paint draw2d


    【解决方案1】:

    我想通了。我将其发布在这里,以防有人遇到类似的性能问题。我在 Eclipse 论坛上获得了这方面的帮助。链接和完整代码在 eclipse 论坛上提供: http://www.eclipse.org/forums/index.php/m/1064195/

    【讨论】:

    • +1,但请在此处发布解决方案。链接往往会在一定时间后失效,这会使您的答案毫无用处。
    • 问题的解决方案是这样的:当大量的widget被添加到一个“同一个父级”时,就会出现这样的问题,因为每一次,甚至在任何一个widget中都会有轻微的修改。它的孩子,对所有兄弟姐妹执行重新验证。处理这种情况的方法是使用某种分页,即将子级划分为多个面板,然后将它们添加到父级。这将显着减少重新验证的工作量,从而显着提高整体性能。我提供的链接包含一个 ZIP 文件,它是示例代码。
    • 我无法访问 zip 文件。您可以将其发布到 Dropbox 或类似的东西上吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多