我一直试图"透支"我的Eclipse RCP应用程序的主窗口,以显示红色"录制"应用程序启用了屏幕录制功能时的边框。
private boolean isActive;
private final ProgressMonitorDialog monitor;
private PaintListener paintListener;
private final int recordingFrameThickness = 5;
public boolean toggle() {
isActive = !isActive;
try {
// New state
if (isActive) {
monitor.run(true, false, new BackupExecutionBeginRecording(Display.getCurrent()));
addRecordingFrame(Display.getCurrent().getActiveShell());
}
else {
monitor.run(true, false, new BackupExecutionAfterRecording());
removeRecoringFrame(Display.getCurrent().getActiveShell());
}
}
catch (InvocationTargetException e) {
System.err.println("Couldn't start backup task. Error: " + e.getMessage());
}
catch (InterruptedException e) {
System.err.println("Backup thread was interrupted. Error: " + e.getMessage());
}
return isActive;
}
private void addRecordingFrame(Shell shell) {
paintListener = new PaintListener() {
@Override
public void paintControl(PaintEvent e) {
Rectangle clientArea = shell.getClientArea();
e.gc.setLineWidth(recordingFrameThickness);
e.gc.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
e.gc.drawRectangle(clientArea);
}
};
shell.addPaintListener(paintListener);
}
private void removeRecoringFrame(Shell shell) {
shell.removePaintListener(paintListener);
}
正如您所看到的,我遵循的方法是等待应用程序主窗口被绘制并随后添加一个矩形。理论上,在每次改变窗口大小或位置后,应重新渲染重叠的红框。但似乎应用程序的主shell不会调用PaintEvent。
是否有其他方法可以将某些内容绘制到应用程序的现有布局上,而不会阻止与下面控件的交互?
答案 0 :(得分:1)
Eclipse Platform通过在 overlay shell上创建和绘制来实现这一点,该shell小心地位于基本shell的顶部。叠加层是使用SWT.NO_TRIM | SWT.ON_TOP
创建的,其位置跟踪底层基础shell。有关示例,请参阅e4 Overlay。
答案 1 :(得分:0)
通过下面的解决方案,我能够在我的主壳周围绘制一个红色边框,"跟随" shell的任何重新定位和调整大小的活动。一个很大的缺点仍然存在:红色边框似乎有一个外边框(由区域创建?),它与用于调整外壳大小的手柄重叠。因此,只有在没有显示红色边框时才能调整外壳的大小(等于外壳没有焦点)。
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.ShellListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.Region;
import org.eclipse.swt.widgets.Shell;
public class RecordingFrame {
private Shell baseShell;
private Shell overlayShell;
private ControlListener controlListener;
private ShellListener shellListener;
private PaintListener paintListener;
private Rectangle outerRect;
private Rectangle innerRect;
private Region region;
private int lineWidth = 10;
private Color color;
public RecordingFrame(Shell baseShell) {
this.baseShell = baseShell;
// Set up new shell
overlayShell = new Shell(baseShell, SWT.BORDER | SWT.NO_TRIM | SWT.ON_TOP);
overlayShell.setVisible(true);
// Initialize objects
outerRect = new Rectangle(0, 0, 0, 0);
innerRect = new Rectangle(0, 0, 0, 0);
region = new Region();
color = new Color(baseShell.getDisplay(), 255, 0, 0);
// First drawing of frame
redraw();
// Configure listeners
initListeners();
// Add listeners to shells
baseShell.addControlListener(controlListener);
baseShell.addShellListener(shellListener);
overlayShell.addPaintListener(paintListener);
}
public void dispose() {
// Remove all listeners
overlayShell.removePaintListener(paintListener);
baseShell.removeControlListener(controlListener);
baseShell.removeShellListener(shellListener);
if (!overlayShell.isDisposed())
overlayShell.dispose();
}
private void redraw() {
// Get bounds of base shell
overlayShell.setBounds(baseShell.getBounds());
// Calculate outer rectangle
outerRect.height = overlayShell.getBounds().height;
outerRect.width = overlayShell.getBounds().width;
outerRect.x = 0;
outerRect.y = 0;
// Calculate inner rectangle
innerRect.height = outerRect.height - 2 * lineWidth;
innerRect.width = outerRect.width - 2 * lineWidth;
innerRect.x = 0 + lineWidth;
innerRect.y = 0 + lineWidth;
// Create a new region which is the outer shell minus the inner shell
region = new Region();
region.add(outerRect);
region.subtract(innerRect);
overlayShell.setRegion(region);
region.dispose();
// Draw rectangle with new GC
GC gc = new GC(overlayShell);
gc.setLineWidth(lineWidth);
gc.setForeground(color);
gc.drawRectangle(innerRect);
gc.dispose();
}
private void initListeners() {
controlListener = new ControlListener() {
@Override
public void controlResized(ControlEvent e) {
redraw();
}
@Override
public void controlMoved(ControlEvent e) {
redraw();
}
};
shellListener = new ShellListener() {
@Override
public void shellIconified(ShellEvent e) {
overlayShell.setVisible(false);
}
@Override
public void shellDeiconified(ShellEvent e) {
overlayShell.setVisible(true);
}
@Override
public void shellDeactivated(ShellEvent e) {
overlayShell.setVisible(false);
}
@Override
public void shellClosed(ShellEvent e) {
dispose();
}
@Override
public void shellActivated(ShellEvent e) {
overlayShell.setVisible(true);
}
};
paintListener = new PaintListener() {
@Override
public void paintControl(PaintEvent e) {
redraw();
}
};
}
}