【问题标题】:Drawing animation in a Nattable OverlayPainter在 Nattable OverlayPainter 中绘制动画
【发布时间】:2019-05-17 13:49:15
【问题描述】:

我正在尝试在 nattable 上渲染加载动画。我使用 OverLayPainter 机制在表格顶部绘制了一个“玻璃窗格”和一些文本,这非常有效:

public class MessageOverlay
implements IOverlayPainter {
....
@Override
public void paintOverlay(final GC gc, final ILayer layer) {
  this.currentGC = gc;
  this.currentLayer = layer;
  if (visible) {
    currentGC.setAlpha(200);
    currentGC.fillRectangle(0, 0, currentLayer.getWidth(), currentLayer
      .getHeight());
     drawMessage();

    if (withLoadingAnimation) {
      showAnimation = true;
    }
   } else {
     showAnimation = false;
   }
  }
}

但是,paintOverlay 方法不会定期调用,而是在每次表更改时调用。

为了能够显示平滑动画,我添加了一个新线程

final Thread animatorThread = new Thread(new Runnable() {

  @Override
  public void run() {

    while (!Thread.interrupted()) {
      try {
        Thread.sleep(1000 / fps);
      } catch (final InterruptedException e) {
        break;
      }

       display.asyncExec(new Runnable() {
        @Override
        public void run() {
          if (showAnimation && !currentGC.isDisposed()) {
            final Image currentImage = getNextImage();
            final int posX = currentGC.getClipping().width / 2
                - currentImage.getBounds().width;
            final int posY = currentGC.getClipping().height / 2
                - currentImage.getBounds().height;
            currentGC.drawImage(currentImage, posX, posY);
          }
        }
      });
    }
  }
});

animatorThread.start();

如您所见,它尝试访问在paintOverlay 方法中设置的图形上下文this.currentGC。我的问题是,animatorThread 中的currentGC 始终是disposed

我怎样才能 a.) 确保上下文不在线程中或 b.) 以替代方式解决这个问题?

感谢您的帮助。

【问题讨论】:

  • 即使没有处理 GC,这仍然会因“无效线程访问”而失败,因为所有 UI 操作(例如 drawImage)都必须在 UI 线程中完成。
  • 啊,你说得对,我已经改变了问题以反映在 ui 线程中运行。

标签: java swt nattable


【解决方案1】:

您可以尝试使用当前的 NatTable 实例创建一个新的 GC,并在需要时从传入的 GC 实例中传递配置。然后你负责处置 GC 实例,不应该有在你的线程之外处置 GC 的风险。

一个简单的示例可能类似于以下 sn-p,它仅显示窗格 1000 毫秒,然后再次将其删除。您当然需要更改逻辑,使其在加载操作方面更具动态性:

AtomicBoolean paneThreadStarted = new AtomicBoolean(false);

...

natTable.addOverlayPainter(new IOverlayPainter() {

    @Override
    public void paintOverlay(GC gc, ILayer layer) {
        if (this.paneThreadStarted.compareAndSet(false, true)) {
            Display.getDefault().asyncExec(new Runnable() {

                @Override
                public void run() {
                    GC currentGC = new GC(natTable);
                    currentGC.setForeground(GUIHelper.COLOR_WHITE);
                    currentGC.setBackground(GUIHelper.COLOR_BLACK);
                    currentGC.setAlpha(200);
                    currentGC.fillRectangle(0, 0, layer.getWidth(), layer.getHeight());

                    String load = "Loading data ...";
                    Point textExtent = currentGC.textExtent(load);
                    currentGC.drawText(load,
                            layer.getWidth() / 2 - textExtent.x / 2,
                            layer.getHeight() / 2 - textExtent.y / 2,
                            true);

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    currentGC.dispose();
                    natTable.redraw();
                }
            });
        }
    }
});

这样您就可以通过从外部更改AtomicBoolean 再次显示窗格:

    Button showPaneButton = new Button(buttonPanel, SWT.PUSH);
    showPaneButton.setText("Show Pane");
    showPaneButton.addSelectionListener(new SelectionAdapter() {
        @Override
        public void widgetSelected(SelectionEvent e) {
            this.paneThreadStarted.set(false);
            natTable.redraw();
        }
    });

【讨论】:

  • 这似乎让我更接近结果,但是,图层现在不是在表格上而是在窗口上绘制。我能够正确设置剪辑(因此叠加层具有正确的大小)。我用new GC(table.getShell) 创建了新的gc。如果我使用new GC(table.getDisplay),我看不到任何覆盖,可能是因为它被绘制在桌子下面?
  • 你试过new GC(natTable);吗?因为 NatTable 作为 Canvas 也是 Drawable
  • 这听起来像是放置它的正确位置,但是,似乎覆盖层是在实际表格下方绘制的,因此隐藏了覆盖层的内容。
  • 可能是一个并发问题,因为您在第二个线程中异步渲染。我对您的代码进行了简单的修改进行了测试,它对我有用。如果您仍然有问题,您可以尝试使用 PaintListener 而不是 IOverlayPainter。
  • 您介意分享您的示例吗?我可以分析差异,如果有的话,看看我是否犯了一个微妙的错误。
猜你喜欢
  • 1970-01-01
  • 2015-08-09
  • 2018-03-28
  • 1970-01-01
  • 2011-07-28
  • 2013-10-20
  • 1970-01-01
  • 2021-07-24
  • 2019-04-19
相关资源
最近更新 更多