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


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

/ *由paint(Event,Object)调用。 * /
private void paintAnimated(最终事件事件,最终ImageLoader imageLoader){
如果(imageLoader == null || ArrayUtils.isEmpty(imageLoader.data)){
返回;
}
最终线程animateThread = new AnimationThread(event,imageLoader);
animateThread.setDaemon(true);
animateThread.start();
}

私有类AnimationThread扩展了Thread {

私人展示架;

私人GC gc;

私有ImageLoader imageLoader;

私人色彩背景;

public AnimationThread(最终事件事件,最终ImageLoader imageLoader){
super(“ Animation”);
this.display = event.display;
/ *
*如果我们只是引用event.gc,它将在使用时重置/为空
*在run()中。
* /
this.gc =新的GC(event.gc.getDevice());
this.imageLoader = imageLoader;
this.background = getBackground(event.item,event.index);
}

@Override
公共无效run(){
/ *
*创建一个要绘制的屏幕外图像,并用外壳背景填充它。
* /
最终图片offScreenImage =
新图片(this.display,this.imageLoader.logicalScreenWidth,
this.imageLoader.logicalScreenHeight);
最终GC offScreenImageGC =新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;
while(this.imageLoader.repeatCount == 0 || repeatCount> 0){
开关(imageData.disposalMethod){
情况SWT.DM_FILL_BACKGROUND:
/ *在绘制之前填充背景色。 * /
offScreenImageGC.setBackground(this.background);
offScreenImageGC.fillRectangle(imageData.x,imageData.y,imageData.width,
imageData.height);
打破;
情况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);

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

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

最佳答案

经过数小时的反复试验,一个同事提出了一个可行的解决方案。我最初在完全独立的LabelProvider中实现此目标的方法失败了。

一种无效的方法是重写LabelProvider#update()并从该方法中调用timerExec(100,new Runnable(){... viewer.update()...)。很难控制,它使用了太多的CPU周期(在我的MacBook上为10%)。

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

最终方法有三个构建基块


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


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

关于eclipse - SWT表/树查看器单元中的GIF动画,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2037353/

10-15 16:02