4

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

语境

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

故事

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

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

我决定尝试 CellTree 实现,但它不适合我,因为让“showmore”按钮消失并不是一件容易的事,而且树的样式也是如此。

我终于从头开始实现了我自己的树实现。这个实现本质上依赖于一个简单的 html 列表结构 (ul-li),并且最大程度地受益于 css 功能。实际上,扩展树节点是使用 css 完成的,使用了一种称为“checkbox hack”的技巧。

在这一点上,树的自定义实现很快(比树或单元树更好),甚至填充了数千个项目,并且满足了要求,但是......

问题

当一个项目被拖到其他项目上时,这些项目的样式会根据放置的可能性而改变。

第一种解决方案

第一个想法是利用 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 秒触发的绘制事件 慢速事件 速度跟踪器截图

事件速度在树的底部元素上是公平的 公平的速度事件速度跟踪器屏幕截图

问题

几天以来我一直被这个问题困扰,我想知道是否有人能指出我所缺少的。也许,这种行为是完全正常的,但也许有解决此类问题的方法?如果有人能在这一点上帮助我,我会很高兴。

感谢您的回复!

小脑

4

1 回答 1

2

如果您使用的是GWT-Dnd,请看一下;

当屏幕上有很多可拖动对象时,拖动性能变慢

提到此性能问题与在放置事件上查找小部件的 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 上。

希望这会帮助你。

于 2013-12-20T22:58:20.200 回答