我想創建一個「選擇區域」工具。 這個工具應該允許用鼠標在屏幕上繪製一個矩形區域。SWT在外殼上繪製一個「透明」矩形
我使用全屏,半透明,變暗的swt Shell
作爲我的背景,在該背景上繪製了一個白色矩形來表示所選區域。
我的問題是,我沒有找到一個有效的方式刷新矩形區域。 到現在爲止我用過的redraw
方法,但視覺效果相當難看,甚至以爲我試圖重新繪製僅他所需要的面積:
public ManualScreenAreaSelector(final Display display) {
shell = new Shell(display, SWT.NO_TRIM | SWT.ON_TOP);
shell.setBounds(display.getClientArea());
// shell.setFullScreen(true);
shell.setAlpha(180);
shell.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
shell.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
}
@Override
public void mouseMove(final MouseEvent e) {
if (editionMode) {
// retrieve the rectangular area corresponding to mouse selection
final Rectangle r = makeRectangleFromSelection(clickCoordinates, new Point(e.x, e.y));
// make the ugly 'tint' effect
shell.redraw();
GC gc = new GC(shell);
gc.setBackground(shell.getDisplay().getSystemColor(SWT.COLOR_WHITE));
gc.setAlpha(150);
gc.fillRectangle(r.x, r.y, r.width, r.height);
gc.setBackground(shell.getDisplay().getSystemColor(SWT.COLOR_BLACK));
gc.fillRectangle(0, 0, r.x, r.y);
gc.fillRectangle(0, 1080 - r.y, r.x, 1080 - r.y);
gc.dispose();
lastX = e.x;
lastY = e.y;
}
}
@Override
public void mouseDown(final MouseEvent e) {
// Right click = reset selection
if (e.button == 3) {
shell.redraw();
selectedArea = null;
if (editionMode) {
editionMode = false;
shell.removeMouseMoveListener(ManualScreenAreaSelector.this);
}
} else if (e.button == 1) {
// left-click enter edition mode
// Reset previous selection
selectedArea = null;
editionMode = true;
clickCoordinates = new Point(e.x, e.y);
lastX = e.x;
lastY = e.y;
shell.addMouseMoveListener(ManualScreenAreaSelector.this);
}
}
@Override
public void mouseUp(final MouseEvent e) {
// left click, only if edition was set
if ((e.button == 1) && editionMode) {
editionMode = false;
shell.removeMouseMoveListener(ManualScreenAreaSelector.this);
selectedArea = makeRectangleFromSelection(clickCoordinates, new Point(e.x, e.y));
shell.dispose();
}
}
所以我想知道,如果一個更有效的解決方案,存在於SWT,而不必使用重繪方法。
EDIT 我使用3個圖像來進行選擇工作:
- 首先是畫面的圖像(屏幕截圖)
- 第二個是屏幕+ alpha混合深色矩形的圖像
- 第三個是我在其上繪製alpha混合圖像的緩衝區+從截圖圖像複製的矩形。
由於只有一個alpha混合操作(對於第二個圖像),性能是可以接受的。
只有一個問題仍然存在,當我第一次使用外殼的圖形控件繪製外殼時,第一次將alpha混合圖像用作外殼背景時,在發送鼠標事件時其他所有內容都正常工作:
public ManualScreenAreaSelector(final Display display) {
screenWidth = display.getClientArea().width;
screenHeight = display.getClientArea().height;
// create a new Image of the screen
backGround = new Image(display, display.getBounds());
GC gc = new GC(display);
gc.copyArea(backGround, 0, 0);
gc.dispose();
// Copy background image and add alpha blended effect
aplhaBackGround = new Image(backGround.getDevice(), backGround.getImageData());
GC alphaGC = new GC(aplhaBackGround);
alphaGC.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
alphaGC.setAlpha(200);
alphaGC.fillRectangle(0, 0, screenWidth, screenHeight);
alphaGC.dispose();
// create the shell
shell = new Shell(display, SWT.NO_TRIM | SWT.ON_TOP | SWT.NO_BACKGROUND);
shell.setBounds(display.getClientArea());
// get shell graphics control
shellGraphics = new GC(shell);
// set the shell image to screen image <-- does nothing
shellGraphics.drawImage(aplhaBackGround, 0, 0);
// Image for the shell
bufferImage = new Image(shell.getDisplay(), shell.getBounds());
shell.print(shellGraphics);
}
public void mouseMove(final MouseEvent e) {
if (editionMode) {
// Get selected area
final Rectangle selectedArea = makeRectangleFromSelection(clickCoordinates, new Point(
e.x, e.y));
// Copy alpha blended background into the buffer
GC gc1 = new GC(aplhaBackGround);
gc1.copyArea(bufferImage, 0, 0);
gc1.dispose();
// Paint "normal" background over selected area
GC gc2 = new GC(bufferImage);
gc2.drawImage(backGround, selectedArea.x, selectedArea.y, selectedArea.width,
selectedArea.height, selectedArea.x, selectedArea.y, selectedArea.width,
selectedArea.height);
// draw the painted image on the shell
shellGraphics.drawImage(bufferImage, 0, 0);
gc2.dispose();
}
}
我更喜歡使用print()方法,而不是OpenGl擴展或jogl。我會嘗試shell.print(gc)。 – zeropouet 2012-03-06 15:53:28
您可以嘗試使用該圖像來加速重繪,但我的直覺是SWT alpha實現對於全屏操作而言太慢。 – 2012-03-06 16:44:45