拖动事件期间GWT更改样式需要太长时间

时间:2013-08-06 13:35:38

标签: performance events gwt drag-and-drop tree

这是我的第一个问题,我不是英语母语人士,所以我提前道歉,如果这让我的解释难以理解。

CONTEXT

我负责开发一个操作词汇集的小应用程序。 该应用程序构建在GWT上,由GWT-Bootstrap和其他一些库添加,与应用程序的ui部分无关。 为了向用户公开这个词汇表的术语,我在视觉上使用树状结构。

故事

树的要求很少,它必须允许拖放项目的功能并在它们之间显示连接器。

我首先使用本机GWT组件中的Tree ui类。事实证明,即使在生产模式下,在树中加载了很多术语,性能也会下降。

我决定尝试CellTree实现,但它不适合我,因为make消失了“showmore”按钮不是一件容易的事,也是树的造型。

我终于从头开始自己实现了一棵树。 此实现主要依赖于简单的html列表结构(ul-li),并且最大限度地利用css功能。实际上,使用称为“复选框黑客”的技巧,使用css扩展树节点。

此时树的自定义实现很快(优于树或celltree),甚至填充了数千个项目,并且符合要求,但是......

问题

当项目被拖动到其他项目上时,这些项目的样式会根据丢弃的可能性而改变。

第一解决方案

第一个想法是让css受益,并使用:hover选择器来改变项目的样式,具体取决于它们的类。 但是当前浏览器(特别是Chrome)存在一个主要问题,即如果鼠标左键按下,则会导致css:hover未触发,拖动时会出现这种情况(铬问题122746)

似乎我必须忘记一个令人厌恶的CSS解决方案,直到:hover触发问题将被关闭。

第二种解决方案

我遇到的唯一其他解决方案是以编程方式更改项目的样式。

处理程序的代码

@Override
public void onDragEnter(DragEnterEvent event)
{
    if (event.getSource() instanceof Word)
    {
        event.stopPropagation();
        event.preventDefault();
        Word word = (Word) event.getSource();
        word.addStyleDependentName("over");
    }
}
@Override
public void onDragLeave(DragLeaveEvent event)
{
    if (event.getSource() instanceof Word)
    {
        event.stopPropagation();
        event.preventDefault();
        Word word = (Word) event.getSource();
        word.removeStyleDependentName("over");
    }
}

它可以正常使用一些项目,但是当处理数千个时,它会使应用程序冻结,并且渲染在某种程度上是随机的。

精度研究

在处理树中的5000个项目时会出现此问题(应用程序必须处理此类数据集)。

我知道有效的事件处理问题,因为事件冒泡,并且处理程序是唯一的,因为当潜在处理程序的数量(如果针对每个项目具体化)被推荐是因为数量不足而导致的。项目增加。

中学我使用速度追踪器分析问题的根源,,结果我不明白

事件在树的顶部元素上非常慢,特别是在样式重新计算后需要1秒钟才能触发的绘制事件 Slow events Speed Tracer Screenshot

事件速度在树的底部元素上是公平的 Fair enougth speed events Speed Tracer Screenshot

问题

我几天以来一直坚持这个问题,我想知道是否有人可以指出我错过了什么。 也许,这种行为是完全正常的,但也许有一个解决这个问题的方法? 如果有人能在这一点上帮助我,我会很高兴的。

感谢您的回复!

lilBrain

1 个答案:

答案 0 :(得分:2)

如果您使用GWT-Dnd,请查看该内容;

Slow drag performance when there are a lot of draggables on screen

提到此性能问题与在放置事件中查找窗口小部件的x,y坐标有关。

com.allen_sauer.gwt.dnd.client.DropControllerCollection.getIntersectDropController(int x, int y)

有一段代码循环通过DropController候选者,看起来它只是用于调试的目的。

for (int i = sortedCandidates.length - 1; i >= 0; i--) {
   Candidate candidate = sortedCandidates[i];
   if (DOMUtil.DEBUG) {
      DOMUtil.debugWidgetWithColor(candidate.getDropTarget(), "blue");
   }
}

之后,代码然后循环并实际尝试 确定x和y坐标是否在DropController上。

希望这会对你有所帮助。