Я пишу приложение, и наши дизайнеры хотят использовать градиенты для некоторых фонов некоторых из наших композитов.
Я написал следующий код:
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 / CLabels, Canvases и Links поверх композита.
В этих областях фон просто серый, который вы получаете при рисовании пустого холста.
Я пытался заставить метки наследовать фон следующим образом:
label.setBackgroundMode(SWT.INHERIT_DEFAULT) //SWT.INHERIT_FORCE Doesn't work either
Но это оставляет меня с тем же серым цветом по умолчанию и без градиента за компонентами поверх Composite.
Есть ли предложения по использованию градиента в качестве фона для каждого элемента?
Я бы не возражал против рисования градиента на gc с предоставленным изображением, а затем установки фона для этого изображения. Однако этот метод вообще не работал, ни составной, ни какой-либо из его элементов.
Также я не могу установить градиент индивидуально, насколько мне известно. Мы хотим, чтобы вся композиция представляла собой единый плавный градиент.
[править] Я загрузил пример на twitpic здесь.
Спасибо,
Брайан Джанфоркаро




Первое, что я бы попробовал, - это захватить изображение из виджета и нарисовать часть изображения, где дочерний виджет расположен непосредственно на дочернем виджете.
Если это не сработает, попробуйте использовать один и тот же прослушиватель рисования для обоих виджетов, но перед тем, как установить преобразование 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 после того, как вы закончите с ними. В противном случае у вас будет утечка системных ресурсов, и в конечном итоге они закончатся.
Используйте композитный.setBackgroundMode (SWT.INHERIT_DEFAULT), но не раскрашивайте композит напрямую - нарисуйте изображение и установите его в качестве фонового изображения с помощью композитный.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();
}
}
}
С небольшими изменениями и подталкиванием это отлично сработало. Спасибо!
Нет необходимости устанавливать фоновое изображение. Меня тоже устраивает установка цвета.
Это была хорошая идея, но она основана на фактическом gc элемента управления, поэтому любой текст или что-либо в элементе управления будет стерто.