私のアプリケーションでは、いくつかのコンポジットにオーバーレイを追加する方法を探しています。オーバーレイには、「データがありません」というテキストのラベルが含まれます。基礎となるコンポジットは表示する必要がありますが、ユーザーは何もできません。私のアプリケーションには1つの画面に異なる複合部品が含まれているため、複合材の1つにオーバーレイを配置する方法が必要です。 SWTでこれを実装する方法はありますか?SWTの他のコンポジットに透明コンポジットを配置する
3
A
答えて
4
可能な解決策は、覆いたいComposite
の上にトリムを適用せずに半透明のものを置くことです。
Shell
のオーバーレイを更新して、Composite
とその親のサイズ、位置、および可視性を継続的に一致させることが難しいのは、子どもの境界や視認性にも影響するためです。
私はそれを行うためにクラスをOverlay
にしようと決めました。任意のControl
をカバーするために使用することができ、基底のControl
を追跡して一致させるためにコントロールとペイントリスナーを使用します。これらのリスナーは、Control
の親の階層全体にも関連付けられています。
対応する方法を使用してOverlay
に色、透明度、およびテキストを設定できます。
私はいくつかの簡単なテストを行い、正しく動作しているように見えましたが、何も保証できません。あなたはそれを試してみたいかもしれません。
それを使った簡単な例:
public class OverlayTest {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout(SWT.VERTICAL));
shell.setSize(250, 250);
// create the composite
Composite composite = new Composite(shell, SWT.NONE);
composite.setLayout(new FillLayout(SWT.VERTICAL));
// add stuff to the composite
for (int i = 0; i < 5; i++) {
new Text(composite, SWT.BORDER).setText("Text " + i);
}
// create the overlay over the composite
Overlay overlay = new Overlay(composite);
overlay.setText("No data available");
// create the button to show/hide the overlay
Button button = new Button(shell, SWT.PUSH);
button.setText("Show/hide overlay");
button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent arg0) {
// if the overlay is showing we hide it, otherwise we show it
if (overlay.isShowing()) {
overlay.remove();
}
else {
overlay.show();
}
}
});
shell.open();
while (shell != null && !shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
}
そしてOverlay
クラス:
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Scrollable;
import org.eclipse.swt.widgets.Shell;
/**
* A customizable overlay over a control.
*
* @author Loris Securo
*/
public class Overlay {
private List<Composite> parents;
private Control objectToOverlay;
private Shell overlay;
private Label label;
private ControlListener controlListener;
private DisposeListener disposeListener;
private PaintListener paintListener;
private boolean showing;
private boolean hasClientArea;
private Scrollable scrollableToOverlay;
public Overlay(Control objectToOverlay) {
Objects.requireNonNull(objectToOverlay);
this.objectToOverlay = objectToOverlay;
// if the object to overlay is an instance of Scrollable (e.g. Shell) then it has
// the getClientArea method, which is preferable over Control.getSize
if (objectToOverlay instanceof Scrollable) {
hasClientArea = true;
scrollableToOverlay = (Scrollable) objectToOverlay;
}
else {
hasClientArea = false;
scrollableToOverlay = null;
}
// save the parents of the object, so we can add/remove listeners to them
parents = new ArrayList<Composite>();
Composite parent = objectToOverlay.getParent();
while (parent != null) {
parents.add(parent);
parent = parent.getParent();
}
// listener to track position and size changes in order to modify the overlay bounds as well
controlListener = new ControlListener() {
@Override
public void controlMoved(ControlEvent e) {
reposition();
}
@Override
public void controlResized(ControlEvent e) {
reposition();
}
};
// listener to track paint changes, like when the object or its parents become not visible (for example changing tab in a TabFolder)
paintListener = new PaintListener() {
@Override
public void paintControl(PaintEvent arg0) {
reposition();
}
};
// listener to remove the overlay if the object to overlay is disposed
disposeListener = new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
remove();
}
};
// create the overlay shell
overlay = new Shell(objectToOverlay.getShell(), SWT.NO_TRIM);
// default values of the overlay
overlay.setBackground(objectToOverlay.getDisplay().getSystemColor(SWT.COLOR_GRAY));
overlay.setAlpha(200);
// so the label can inherit the background of the overlay
overlay.setBackgroundMode(SWT.INHERIT_DEFAULT);
// label to display a text
// style WRAP so if it is too long the text get wrapped
label = new Label(overlay, SWT.WRAP);
// to center the label
overlay.setLayout(new GridLayout());
label.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true));
showing = false;
overlay.open();
overlay.setVisible(showing);
}
public void show() {
// if it's already visible we just exit
if (showing) {
return;
}
// set the overlay position over the object
reposition();
// show the overlay
overlay.setVisible(true);
// add listeners to the object to overlay
objectToOverlay.addControlListener(controlListener);
objectToOverlay.addDisposeListener(disposeListener);
objectToOverlay.addPaintListener(paintListener);
// add listeners also to the parents because if they change then also the visibility of our object could change
for (Composite parent : parents) {
parent.addControlListener(controlListener);
parent.addPaintListener(paintListener);
}
showing = true;
}
public void remove() {
// if it's already not visible we just exit
if (!showing) {
return;
}
// remove the listeners
if (!objectToOverlay.isDisposed()) {
objectToOverlay.removeControlListener(controlListener);
objectToOverlay.removeDisposeListener(disposeListener);
objectToOverlay.removePaintListener(paintListener);
}
// remove the parents listeners
for (Composite parent : parents) {
if (!parent.isDisposed()) {
parent.removeControlListener(controlListener);
parent.removePaintListener(paintListener);
}
}
// remove the overlay shell
if (!overlay.isDisposed()) {
overlay.setVisible(false);
}
showing = false;
}
public void setBackground(Color background) {
overlay.setBackground(background);
}
public Color getBackground() {
return overlay.getBackground();
}
public void setAlpha(int alpha) {
overlay.setAlpha(alpha);
}
public int getAlpha() {
return overlay.getAlpha();
}
public boolean isShowing() {
return showing;
}
public void setText(String text) {
label.setText(text);
// to adjust the label size accordingly
overlay.layout();
}
public String getText() {
return label.getText();
}
private void reposition() {
// if the object is not visible, we hide the overlay and exit
if (!objectToOverlay.isVisible()) {
overlay.setBounds(new Rectangle(0, 0, 0, 0));
return;
}
// if the object is visible we need to find the visible region in order to correctly place the overlay
// get the display bounds of the object to overlay
Point objectToOverlayDisplayLocation = objectToOverlay.toDisplay(0, 0);
Point objectToOverlaySize;
// if it has a client area, we prefer that instead of the size
if (hasClientArea) {
Rectangle clientArea = scrollableToOverlay.getClientArea();
objectToOverlaySize = new Point(clientArea.width, clientArea.height);
}
else {
objectToOverlaySize = objectToOverlay.getSize();
}
Rectangle objectToOverlayBounds = new Rectangle(objectToOverlayDisplayLocation.x, objectToOverlayDisplayLocation.y, objectToOverlaySize.x,
objectToOverlaySize.y);
Rectangle intersection = objectToOverlayBounds;
// intersect the bounds of the object with its parents bounds so we get only the visible bounds
for (Composite parent : parents) {
Rectangle parentClientArea = parent.getClientArea();
Point parentLocation = parent.toDisplay(parentClientArea.x, parentClientArea.y);
Rectangle parentBounds = new Rectangle(parentLocation.x, parentLocation.y, parentClientArea.width, parentClientArea.height);
intersection = intersection.intersection(parentBounds);
// if intersection has no size then it would be a waste of time to continue
if (intersection.width == 0 || intersection.height == 0) {
break;
}
}
overlay.setBounds(intersection);
}
}
関連する問題
- 1. スクロールコンポジットVSコンポジットSWT
- 2. SWT Java - イメージバックグラウンドを持つコンポジットをイメージバックグラウンドのシェルに配置する
- 3. スクロール・コンポジット内の多数のコンポジットのSWTパフォーマンス
- 4. swt - コンポジットを再作成
- 5. SWTでコンポジットをフォーカス可能にする
- 6. コンポジット内のコンポジット
- 7. SWTコンポジット - 再描画の問題
- 8. RCP用のSWTコンポジットの表示に関する問題
- 9. SWTコンポジットをスムーズにスクロールする方法は?
- 10. SWTコンポジットを非表示にする方法
- 11. EF6のコンポジット・キーによるコンポジット・タイプ(TPC)マッピングのテーブル
- 12. SWTコンポジットが右側に表示されます
- 13. SWT:コンポジットにaddFilterまたはaddKeyListenerを追加
- 14. コンポジットの子を直ちに表示してSWTに再度ロードする方法
- 15. コンポジットWPFアプリケーションのテスト
- 16. コンポジット@HibernateエンティティのNaturalId
- 17. コンポジットIDとJPA
- 18. NHibernate 3.2コンポジットid
- 19. トラブル(コンポジット)キー
- 20. コンポジットにBeanメソッドを渡す
- 21. スクロール可能なコンポジット - 自動サイズ変更 - swt
- 22. ウィンドウ上でSWTコンポジットが表示されない
- 23. コンポジットをコンテンツとするTreeViewer
- 24. SWT:コンポジットに新しい子があることを通知します。
- 25. HBaseコンポジットの行キーのフォーマット
- 26. SWTは、私は私の<code>SWT</code> GUIに問題があるコンポジットが完全に親
- 27. MySQLインデックス:コンポジット対カラム
- 28. GAE ImagesServiceFactoryコンポジットがPNG透過性を尊重しない
- 29. コンポジットWPF(プリズム)モジュールのリソースデータテンプレート
- 30. Hibernateカスケード+コンポジットidの問題
これが正しい答えとしてマークされていないのはなぜ?多くのことを試した後、これはうまくいきました。ありがとう! – sura2k