SWT GC: Color not correctly drawn on Windows
Frage
Still looking for a solution
I have the following problem: I use SWT GC
to draw figures contained in GraphNodes to a Zest Graph.
As far as Linux and MacOS are concerned, everything works fine. But when I run my jar on Windows the nodes look very odd. The color is not painted correctly and there is no transparency (achieved via setAlpha()
of GC
).
Here are two screenshots to illustrate my problem:
Linux:
Windows:
EDIT:
I just created this working "mini" example to test out. If anybody has an idea, why the rectangle is black on windows, I would highly appreciate an answer. Here is the back.png
image:
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.ToolbarLayout;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.zest.core.widgets.Graph;
import org.eclipse.zest.core.widgets.GraphNode;
import org.eclipse.zest.core.widgets.IContainer;
public class MiniExample
{
public static void main(String[] args)
{
Display display = Display.getDefault();
Shell shell = new Shell(display);
Graph graph = new Graph(shell, SWT.NONE);
graph.setSize(100, 100);
CustomFigure fig = new CustomFigure(new Label());
fig.setSize(-1, -1);
CustomNode node = new CustomNode(graph, SWT.NONE, fig);
node.setLocation(5, 5);
shell.pack();
shell.open();
while(!shell.isDisposed())
{
if(!display.readAndDispatch())
display.sleep();
}
}
/* Minimal helper class for the figure */
static class CustomFigure extends Figure
{
private Image background = new Image(Display.getDefault(), "back.png");
private GC gcBack = new GC(background);
private Label all = new Label(background);
private Color blau = new Color(Display.getDefault(), 19, 59, 94);
public CustomFigure(Label label)
{
ToolbarLayout layout = new ToolbarLayout();
setLayoutManager(layout);
setMiddle(3);
add(all);
}
/* The problem has to occur somewhere here... */
public void setMiddle(int value)
{
gcBack.setBackground(blau);
gcBack.setForeground(blau);
gcBack.setAlpha(255);
/* color background blue and draw the nr of connections */
gcBack.drawRoundRectangle(6, 6, 15, 15, 3, 3);
gcBack.fillRoundRectangle(6, 6, 15, 15, 3, 3);
gcBack.setForeground(ColorConstants.white);
gcBack.drawText(value+"", 9, 6, true);
gcBack.setAlpha(255);
all.repaint();
}
}
/* Minimal helper class for the node */
static class CustomNode extends GraphNode
{
public CustomNode(IContainer graphModel, int style, CustomFigure figure)
{
super(graphModel, style, figure);
}
@Override
protected IFigure createFigureForModel()
{
return (IFigure) this.getData();
}
}
}
Lösung
It is definitely your background image what causes the problem. I have run some tests with the following example. I used a pure white background image and your background image . All is fine with the white background image, but if I use your background image only black colors are painted. It is most likely a bug in SWT.
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class MiniExample {
public static void main( String[] args ) {
Display display = Display.getDefault();
Shell shell = new Shell( display );
ACanvas canvas = new ACanvas( shell, SWT.None );
canvas.setSize( 150, 150 );
shell.pack();
shell.open();
while( !shell.isDisposed() ) {
if( !display.readAndDispatch() )
display.sleep();
}
}
static class ACanvas extends Canvas {
public ACanvas( Composite parent, int style ) {
super( parent, style );
this.addPaintListener( new PaintListener() {
@Override
public void paintControl( PaintEvent arg0 ) {
int value = 5;
Image background = new Image( Display.getDefault(), "back2.png" );
GC gcBack = new GC( background );
//Color blue = Display.getDefault().getSystemColor( SWT.COLOR_BLUE );
Color blue = new Color( Display.getDefault(), 0, 0, 255 );
gcBack.setBackground( blue );
gcBack.setForeground( blue );
gcBack.setAlpha( 255 );
gcBack.drawRoundRectangle( 6, 6, 15, 15, 3, 3 );
gcBack.fillRoundRectangle( 6, 6, 15, 15, 3, 3 );
gcBack.setForeground( Display.getDefault().getSystemColor( SWT.COLOR_WHITE ) );
gcBack.drawText( value + "", 9, 6, true );
gcBack.setAlpha( 255 );
arg0.gc.drawImage( background, 0, 0 );
}
} );
}
}
}
Andere Tipps
The gray image used in your program and the white image posted by Tobias Willig are significantly different:
Gray:
Image Width: 28 Image Length: 28
Bitdepth (Bits/Sample): 1
Channels (Samples/Pixel): 1
Pixel depth (Pixel Depth): 1
Colour Type (Photometric Interpretation): PALETTED COLOUR (1 colours, 0 transparent)
Image filter: Single row per byte filter
Interlacing: No interlacing
Compression Scheme: Deflate method 8, 32k window
Resolution: 2835, 2835 (pixels per meter)
FillOrder: msb-to-lsb
Byte Order: Network (Big Endian)
Number of text strings: 0 of 0
White:
Image Width: 28 Image Length: 28
Bitdepth (Bits/Sample): 8
Channels (Samples/Pixel): 3
Pixel depth (Pixel Depth): 24
Colour Type (Photometric Interpretation): RGB
Image filter: Single row per byte filter
Interlacing: No interlacing
Compression Scheme: Deflate method 8, 32k window
Resolution: 2835, 2835 (pixels per meter)
FillOrder: msb-to-lsb
Byte Order: Network (Big Endian)
Number of text strings: 0 of 0
As you can see, the Colour Type
of the gray image contains only 1 colour, whereas the one of the white image is RGB.
So it's definately the image that's causing your problems.
swt color are context dependent, you should not take a color from a gc and use it in another
Did you check if you run out of handles in Windows? AFAIK SWT is using a handle from the OS in every instance of Font, Color, Image, etc. so you can even bring your application in trouble by not reusing certain objects (or dispose the old ones; a difference to AWT/Swing). And afaik Linux and probably Mac OS don't have such a terrible behaviour when it comes to "running out of handles"...