[Mono-list] Expose / Cairo not working properly?
Pupeno
pupeno at pupeno.com
Sat Feb 24 10:05:20 EST 2007
Hello,
I have a problem with Cairo and Expose events. I am trying to make a custom
widget. I need a canvas ta draw on. If there's a different way to achieve it,
please, tell me.
First, the example in
http://www.go-mono.com/docs/monodoc.ashx?link=T%3aCairo.Context seems not to
work, when I hide and un-hide the app it works correctly, but move a smaller
window over it and it doesn't re-draw itself. Is this a problem in my
workstation, does anybody else see this same problem?
Based on that example and on a Python implementation of the same thing I wrote
the code (at the bottom) that draws a pentagram. This has a deeper problem.
It redraws itself incorrectly. It seems like when. It seems like if the part
exposed gets re-drawn, but the coordinate system is moved from 0,0 to x,y
where x,y is where the exposing starts. It's hard to explain, I'll attach a
screenshot.
Any help is appreciated.
--
Pupeno <pupeno at pupeno.com> (http://pupeno.com)
PS: The code:
namespace ScoreReadingTrainer {
public enum Clef {
G, F, C3, C4
}
public class Score: Gtk.DrawingArea {
// Margin, in %, on the left of the score (right has no margin).
readonly private byte margin = 2;
readonly private byte steps = 24;
private Clef clef;
public Score() {
this.clef = Clef.G;
this.ExposeEvent += Draw;
}
void Draw(object o, Gtk.ExposeEventArgs e) {
Score score = o as Score;
if(score != null) { // Either it is a Score or we are in problems.
Cairo.Context context = Gdk.Context.CreateDrawable(score.GdkWindow);
this.Draw(context, e.Event.Area.X, e.Event.Area.Y, e.Event.Area.Width,
e.Event.Area.Height);
}
}
void Draw(Cairo.Context context, int x, int y, int width, int height) {
context.Rectangle(x, y, width, height);
context.Clip();
this.Draw(context);
}
void Draw(Cairo.Context context) {
int width = this.Allocation.Width;
int height = this.Allocation.Height;
int realMargin = this.margin * width / 100;
Console.WriteLine("{0}: width={1}, height={2}", System.DateTime.Now, width,
height);
// Paint a white background.
context.Save();
context.Color = new Cairo.Color(1,1,1);
context.Paint();
context.Restore();
// Draw the pentagram.
context.Save();
context.Color = new Cairo.Color(0, 0, 0); // TODO: maybe use 0.2, 0.2, 0.2.
context.LineWidth = height / 200; // Make a relative line width so
we don't end up with a lines too fat or too thin.
if(context.LineWidth < 1) { // Ensure that lines
context.LineWidth = 1; // are at least one pixel wide.
}
for(int line = -2; line <= 2; line++) {// line in self.lines:
double y = this.stepToPixels(line);
if(context.LineWidth == 1) { // Ensure that if lines are one
pixel wide
y += 0.5; // they will be one full pixel and
not two half pixels: http://cairographics.org/FAQ
}
Console.WriteLine("{0}: Line {1} at {2} of width {3}.",
System.DateTime.Now, line, y, context.LineWidth);
context.MoveTo(realMargin, y);
context.LineTo(width, y);
context.Stroke();
}
context.Restore();
}
int stepToPixels(int step) {
// """ Having the step number, return the pixel. A step is the minimum
possible separations between notes, vertically."""
int height = this.Allocation.Height;
int middle = height / 2;
int stepDistance = height / this.steps;
return middle - step * stepDistance;
}
}
}
namespace Gdk {
public class Context {
//Use [DllImport("libgdk-win32-2.0-0.dll")] for Win32
[DllImport("libgdk-x11-2.0.so")]
internal static extern IntPtr gdk_x11_drawable_get_xdisplay(IntPtr raw);
[DllImport("libgdk-x11-2.0.so")]
internal static extern IntPtr gdk_x11_drawable_get_xid(IntPtr raw);
[DllImport("libgdk-x11-2.0.so")]
internal static extern IntPtr gdk_drawable_get_visual(IntPtr raw);
[DllImport("libgdk-x11-2.0.so")]
internal static extern IntPtr gdk_x11_visual_get_xvisual(IntPtr raw);
public static Cairo.Context CreateDrawable(Gdk.Drawable drawable) {
IntPtr x_drawable = IntPtr.Zero;
int x_off = 0, y_off = 0;
int x, y, w, h, d;
((Gdk.Window)drawable).GetGeometry(out x, out y, out w, out h, out d);
if(drawable is Gdk.Window) {
((Gdk.Window) drawable).GetInternalPaintInfo(out drawable, out x_off, out
y_off);
}
x_drawable = drawable.Handle;
IntPtr visual = gdk_drawable_get_visual(x_drawable);
IntPtr Xdisplay = gdk_x11_drawable_get_xdisplay(x_drawable);
IntPtr Xvisual = gdk_x11_visual_get_xvisual(visual);
IntPtr Xdrawable = gdk_x11_drawable_get_xid(x_drawable);
Cairo.XlibSurface s = new Cairo.XlibSurface(Xdisplay, Xdrawable, Xvisual,
w, h);
Cairo.Context g = new Cairo.Context(s);
if(drawable is Gdk.Window){
g.Translate(-(double)x_off,-(double)y_off);
}
return g;
}
}
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: correct.png
Type: image/png
Size: 1165 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/mono-list/attachments/20070224/386eb3a4/attachment.png
-------------- next part --------------
A non-text attachment was scrubbed...
Name: scrambled.png
Type: image/png
Size: 1348 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/mono-list/attachments/20070224/386eb3a4/attachment-0001.png
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/mono-list/attachments/20070224/386eb3a4/attachment.bin
More information about the Mono-list
mailing list