在 Nattable OverlayPainter 中绘制动画
Drawing animation in a Nattable OverlayPainter
我正在尝试在 nattable 上渲染加载动画。我使用 OverLayPainter 机制在 table 上绘制 "glasspane" 和一些文本,这很完美:
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
方法不会定期调用,而是在每次 table 更改时调用。
为了能够显示流畅的动画,我添加了一个新线程
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.) 以替代方式解决这个问题?
感谢您的帮助。
您可以尝试使用当前的 NatTable 实例创建一个新的 GC,如果需要,从传入的 GC 实例传递配置。然后你负责处理 GC 实例,不应该有在线程外处理 GC 的风险。
一个简单的示例可能类似于以下代码段,它只显示窗格 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();
}
});
我正在尝试在 nattable 上渲染加载动画。我使用 OverLayPainter 机制在 table 上绘制 "glasspane" 和一些文本,这很完美:
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
方法不会定期调用,而是在每次 table 更改时调用。
为了能够显示流畅的动画,我添加了一个新线程
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.) 以替代方式解决这个问题?
感谢您的帮助。
您可以尝试使用当前的 NatTable 实例创建一个新的 GC,如果需要,从传入的 GC 实例传递配置。然后你负责处理 GC 实例,不应该有在线程外处理 GC 的风险。
一个简单的示例可能类似于以下代码段,它只显示窗格 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();
}
});