Как заставить Метку наследовать GC Композита в SWT
-
02-07-2019 - |
Вопрос
Я пишу приложение, и наши дизайнеры хотят использовать градиенты для некоторых фонов в нескольких наших композитах.
Я написал следующий код:
composite.addListener (SWT.Paint, new Listener () {
public void handleEvent (Event e) {
GC gc = e.gc;
Rectangle rect = composite.getClientArea ();
Color color1 = new Color (display, 0, 0, 0);
Color color2 = new Color (display, 255, 255, 255);
gc.setForeground(color1);
gc.setBackground(color2);
gc.fillGradientRectangle (rect.x, rect.y, rect.width, rect.height , true);
}
});
Это прекрасно прорисовывает градиент на композите, но поверх композита у нас есть метки, холсты и ссылки.
В этих областях фон просто обычный серый, который вы получаете при рисовании пустого холста.
Я пытался заставить метки наследовать фон следующим образом:
label.setBackgroundMode(SWT.INHERIT_DEFAULT) //SWT.INHERIT_FORCE Doesn't work either
Но это оставляет меня с тем же серым цветом по умолчанию и без градиента за компонентами поверх Композита.
Есть какие-нибудь предложения по использованию градиента в качестве фона для каждого элемента?
Я бы не возражал против того, чтобы нарисовать градиент на gc с предоставленным изображением, а затем установить фон для этого изображения.Однако этот метод просто не работает вообще, composite или любой из его элементов.
Кроме того, насколько мне известно, я не могу настроить градиент индивидуально.Мы хотим, чтобы весь композит представлял собой один равномерный плавный градиент.
[редактировать] Я загрузил пример в twitpic здесь.
Спасибо,
Брайан Джанфоркаро
Решение
Использование composite.setBackgroundMode(SWT.INHERIT_DEFAULT), но не рисуйте композит напрямую - нарисуйте изображение и установите его в качестве фонового с помощью composite.setBackgroundImage(Изображение).Если я ничего не упускаю из виду, это означает, что вам нужно регенерировать изображение только тогда, когда размер композита тоже будет изменен.
Вы должны быть в состоянии вырезать и вставить этот код как есть, чтобы понять, что я имею в виду:
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
/**
* SWT composite with transparent label
*
* @author McDowell
*/
public class Sweet {
private Image imageGradient;
private Label label;
private Composite composite;
private void createComponents(Shell parent) {
composite = new Composite(parent, SWT.NONE);
composite.addListener(SWT.Resize, new Listener() {
public void handleEvent(Event e) {
changeImage();
}
});
composite.setLayout(new FormLayout());
composite.setBackgroundMode(SWT.INHERIT_DEFAULT);
label = new Label(composite, SWT.None);
label.setText("Hello, World!");
}
private void changeImage() {
Image oldImage = imageGradient;
Display display = composite.getDisplay();
Rectangle rect = composite.getClientArea();
imageGradient = new Image(display, rect.width, rect.height);
GC gc = new GC(imageGradient);
try {
Color color1 = new Color(display, 200, 200, 255);
try {
Color color2 = new Color(display, 255, 255, 255);
try {
gc.setForeground(color1);
gc.setBackground(color2);
gc.fillGradientRectangle(rect.x, rect.y, rect.width,
rect.height, true);
} finally {
color2.dispose();
}
} finally {
color1.dispose();
}
} finally {
gc.dispose();
}
composite.setBackgroundImage(imageGradient);
if (oldImage != null) {
oldImage.dispose();
}
}
private void openShell(Display display) {
Shell shell = new Shell(display);
try {
shell.setSize(200, 100);
shell.setLayout(new FillLayout());
createComponents(shell);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
} finally {
if (!shell.isDisposed()) {
shell.dispose();
}
}
}
public void run() {
Display display = Display.getDefault();
try {
openShell(display);
} finally {
display.dispose();
}
}
public void dispose() {
if (imageGradient != null) {
imageGradient.dispose();
}
}
public static void main(String[] args) {
Sweet sweet = new Sweet();
try {
sweet.run();
} finally {
sweet.dispose();
}
}
}
Другие советы
Первое, что я бы попробовал, это захват изображения из виджета и нарисуйте ту часть изображения, где расположен дочерний виджет, непосредственно на дочернем виджете.
Если это не сработает, попробуйте использовать один и тот же прослушиватель paint для обоих виджетов, но перед тем, как установить преобразование GC в значение после преобразования GC для перевода координат в координатное пространство метки:
Listener listener = new Listener () {
public void handleEvent (Event e) {
GC gc = e.gc;
Rectangle rect = composite.getClientArea ();
Point offset = ((Control)e.widget).toControl(composite.toDisplay(0, 0));
Color color1 = new Color (display, 0, 0, 0);
Color color2 = new Color (display, 255, 255, 255);
gc.setForeground(color1);
gc.setBackground(color2);
gc.fillGradientRectangle (rect.x + offset.x, rect.y + offset.y,
rect.width, rect.height , true);
}
}
composite.addListener (SWT.Paint, listener);
label.addListener(SWT.Paint, listener);
Кроме того, будьте осторожны при утилизации всех созданных вами экземпляров Color после того, как вы закончите с ними.В противном случае вы приведете к утечке системных ресурсов и в конечном итоге исчерпаете их.