4

http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/DisplayananimatedGIF.htm描述了如何在 SWT 中显示动画 GIF - 一般。虽然代码有效且易于理解,但使用该技术在 SWT/JFace 表/树查看器单元格中显示动画 GIF 时遇到严重问题。-> 下面的所有代码

本质上,我实现了自己的 OwnerDrawLabelProvider,它在paint(Event, Object) 中创建了一个 ImageLoader 并启动了一个动画线程。问题似乎是这个动画线程不是UI 线程,我不知道在它的 run() 方法中使用哪个 GC 或 Display 实例。

我尝试在线程的构造函数中创建一个单独的 GC 实例 - 从 event.gc 派生 - 但是一旦我退出调试器,线程就无法写入该 GC ......

1 月 9 日星期六 22:11:57 192.168.1.6.local.home java[25387]:CGContextConcatCTM:无效上下文 0x0
2010-01-09 22:12:18.356 java[25387:17b03] 当 [NSGraphicsContext currentContext] 为 nil 时,绘制图像没有意义。这是一个编程错误。中断 _NSWarnForDrawingImageWithNoCurrentContext 进行调试。这将只记录一次。这可能会在未来打破。
1 月 9 日星期六 22:12:41 192.168.1.6.local.home java[25387]:CGContextConcatCTM:无效上下文 0x0

我需要如何处理这种情况?
以下是相关的代码部分:

/* 由绘画(事件,对象)调用。*/
私人无效paintAnimated(最终事件事件,最终ImageLoader imageLoader){
    if (imageLoader == null || ArrayUtils.isEmpty(imageLoader.data)) {
      返回;
    }
    最终线程 animateThread = new AnimationThread(event, imageLoader);
    animateThread.setDaemon(true);
    animateThread.start();
  }

  私有类 AnimationThread 扩展线程 {

    私人展示展示;

    私人 GC GC;

    私有 ImageLoader imageLoader;

    私人彩色背景;

    public AnimationThread(final Event event, final ImageLoader imageLoader) {
      超级(“动画”);
      this.display = event.display;
      /*
       * 如果我们只是简单地引用 event.gc,它将在使用时被重置/清空
       * 在运行()中。
       */
      this.gc = new GC(event.gc.getDevice());
      this.imageLoader = imageLoader;
      this.background = getBackground(event.item, event.index);
    }

    @覆盖
    公共无效运行(){
      /*
       * 创建一个要在其上绘制的离屏图像,并用外壳背景填充它。
       */
      最终图像 offScreenImage =
          新图像(this.display,this.imageLoader.logicalScreenWidth,
              this.imageLoader.logicalScreenHeight);
      最终 GC offScreenImageGC = new GC(offScreenImage);
      offScreenImageGC.setBackground(this.background);
      offScreenImageGC.fillRectangle(0, 0, this.imageLoader.logicalScreenWidth,
          this.imageLoader.logicalScreenHeight);
      图片 image = null;
      尝试 {
        /* 创建第一个图像并将其绘制在离屏图像上。*/
        int imageDataIndex = 0;
        ImageData imageData = this.imageLoader.data[imageDataIndex];
        图像 = 新图像(this.display,imageData);
        offScreenImageGC.drawImage(image, 0, 0, imageData.width, imageData.height, imageData.x,
            imageData.y, imageData.width, imageData.height);

        /*
         * 现在循环遍历图像,在之前的离屏图像上创建和绘制每个图像
         * 在外壳上绘制它。
         */
        int repeatCount = this.imageLoader.repeatCount;
        而(this.imageLoader.repeatCount == 0 || repeatCount > 0){
          开关(imageData.disposalMethod){
            案例 SWT.DM_FILL_BACKGROUND:
              /* 在绘制之前填充背景颜色。*/
              offScreenImageGC.setBackground(this.background);
              offScreenImageGC.fillRectangle(imageData.x, imageData.y, imageData.width,
                  图像数据.高度);
              休息;
            案例 SWT.DM_FILL_PREVIOUS:
              // 恢复之前绘制之前的图像。
              offScreenImageGC.drawImage(image, 0, 0, imageData.width, imageData.height,
                  imageData.x, imageData.y, imageData.width, imageData.height);
              休息;
          }

          imageDataIndex = (imageDataIndex + 1) % this.imageLoader.data.length;
          imageData = this.imageLoader.data[imageDataIndex];
          image.dispose();
          图像 = 新图像(this.display,imageData);
          offScreenImageGC.drawImage(image, 0, 0, imageData.width, imageData.height, imageData.x,
              imageData.y, imageData.width, imageData.height);

          // 绘制离屏图像。
          this.gc.drawImage(offScreenImage, 0, 0);

          /*
           * 休眠指定的延迟时间(添加常用的减速软糖因素)。
           */
          尝试 {
            int ms = imageData.delayTime * 10;
            如果(毫秒

我将同样的问题发布到 SWT 新闻组http://www.eclipse.org/forums/index.php?t=tree&th=160398

4

2 回答 2

2

经过数小时令人沮丧的试错后,一位同事想出了一个可行的解决方案。我最初在完全独立的 LabelProvider 中实现这一点的方法失败了。

一种不起作用的方法是覆盖 LabelProvider#update() 并从该方法中调用 timerExec(100, new Runnable() {...viewer.update()...。“生命”周期这很难控制,而且它使用了太多的 CPU 周期(在我的 MacBook 上是 10%)。

同事的一个想法是实现一个自定义的 TableEditor:一个带有图像(动画 GIF 的一帧)但没有文本的标签。每个 TableEditor 实例都会启动自己的线程,在该线程中更新标签的图像。这很好用,但是每个动画图标都有一个单独的“动画”线程。此外,这是一个性能杀手,在我的 MacBook 上消耗了 25% 的 CPU。

最终方法具有三个构建块

  • 绘制静态图像或动画 GIF 帧的 OwnerDrawLabelProvider
  • 一个动画线程(起搏器),它为包含动画 GIF 的列调用 redraw(),它还调用 update()
  • 以及控制动画线程的观众的内容提供者。

我的博客http://www.frightanic.com/2010/02/09/animated-gif-in-swt-tabletree-viewer-cell/中的详细信息。

于 2010-02-09T20:50:59.177 回答
1

您不能让 LabelProvider 返回不同的图像,然后在要设置动画的元素上调用 viewer.update(...) 。您可以使用 Display.timerExec 来获取回调,而不是使用单独的线程。

请在此处查看我的答案,了解如何更改颜色。你应该能够对图像做类似的事情。

于 2010-01-11T17:43:57.060 回答