📄 sec-thedrawingareawidget.html
字号:
<HTML><HEAD><TITLE>The DrawingArea Widget, And Drawing</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.49"><LINKREL="HOME"TITLE="GTK+ 1.2 Tutorial"HREF="gtk-tut.html"><LINKREL="UP"TITLE="Scribble, A Simple Example Drawing Program"HREF="ch-scribble.html"><LINKREL="PREVIOUS"TITLE="Event Handling"HREF="sec-eventhandling.html"><LINKREL="NEXT"TITLE="Adding XInput support"HREF="sec-addingxinputsupport.html"></HEAD></head><body bgcolor="#FFFFFF" marginheight=0 marginwidth=0 width="100%"><table cellspacing=6 border=0 cellpadding=0 width="100%"> <tr> <td bgcolor="#FFFFFF" valign=top nowrap> <centeR><A HREF="/"><img src="/images/gtk-logo-rgb.gif" width=107 height=140 border=0></A> <font face="helvetica,lucidia" color="#000000"><BR><BR><b>GTK+<BR>The GIMP Toolkit</b></center><BR><table width=100% cellspacing=0 cellpadding=2 border=0><tr><td bgcolor="#000000"><table width=100% cellspacing=0 cellpadding=4 border=0><tr><td bgcolor="#AAAAEE" nowrap><B>General</B></td></tr><tr><td bgcolor="#FFFFFF" nowrap><A HREF="/">Introduction</A><BR><A HREF="/screenshots/">Screenshots</A><br><A HREF="/download/">Download</A><br><A HREF="/mailinglists.html">Mailing Lists</A><BR><A HREF="/bindings.html">Language Bindings</A><BR><A HREF="http://gtk.themes.org/">Themes</A><BR><A HREF="/bugs.html">Bug Tracker</A><BR></td></tr></table></td></tr></table><BR> <table width=100% cellspacing=0 cellpadding=2 border=0><tr><td bgcolor="#000000"><table width=100% cellspacing=0 cellpadding=4 border=0><tr><td bgcolor="#AAAAEE" nowrap><B>Documentation</B></td></tr><tr><td bgcolor="#FFFFFF" nowrap><A HREF="/faq/">FAQ</A><br><A HREF="/tutorial/">Tutorial</A><BR><A HREF="/api/">API Reference</A><br><A HREF="/books.html">Published Books</A><BR></td></tr></table></td></tr></table><BR> <table width=100% cellspacing=0 cellpadding=2 border=0><tr><td bgcolor="#000000"><table width=100% cellspacing=0 cellpadding=4 border=0><tr><td bgcolor="#AAAAEE" nowrap><B>Projects</B></td></tr><tr><td bgcolor="#FFFFFF" nowrap><A HREF="http://www.pango.org/">Pango</A><BR><A HREF="http://sources.redhat.com/inti/">Inti</A><BR><A HREF="http://www.gnome.org/">GNOME</A><BR><A HREF="http://user.sgic.fi/~tml/gimp/win32/">GTK+ for Win32</A><br><A HREF="http://people.redhat.com/sopwith/gtkfb/">GtkFB (Framebuffer)</A><br><A HREF="http://www.directfb.org/gtk.xml">GTK+ on DirectFB</A><BR><A HREF="/beos/">GTK+ for BeOS</A></td></tr></table></td></tr></table><BR> <table width=100% cellspacing=0 cellpadding=2 border=0><tr><td bgcolor="#000000"><table width=100% cellspacing=0 cellpadding=4 border=0><tr><td bgcolor="#AAAAEE" nowrap><B><B>Applications</B></B></td></tr><tr><td bgcolor="#FFFFFF" nowrap><A HREF="http://www.gimp.org/">GIMP</A><BR><A HREF="http://www.abiword.org/">Abiword</A><BR><A HREF="http://www.lysator.liu.se/~alla/dia/dia.html">Dia</A><BR><A HREF="http://glade.pn.org/">Glade</A><BR><A HREF="http://www.gnucash.org/">GnuCash</A><BR><A HREF="http://www.gnome.org/projects/gnumeric/">Gnumeric</A><BR><BR><A HREF="http://www.gnome.org/applist/">GNOME Software Map</A><br></td></tr></table></td></tr></table><BR> </td> <td bgcolor="#ffffff" valign=top width="99%"><font face="lucida,helvetica"><BODYCLASS="SECT1"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLEWIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">GTK+ 1.2 Tutorial</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="sec-eventhandling.html"><<< Previous</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">Chapter 25. Scribble, A Simple Example Drawing Program</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="sec-addingxinputsupport.html">Next >>></A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="SEC-THEDRAWINGAREAWIDGET">25.3. The DrawingArea Widget, And Drawing</A></H1><P>We now turn to the process of drawing on the screen. The widget we use for this is the DrawingArea widget. A drawing areawidget is essentially an X window and nothing more. It is a blankcanvas in which we can draw whatever we like. A drawing areais created using the call:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">GtkWidget* gtk_drawing_area_new (void);</PRE></TD></TR></TABLE><P>A default size for the widget can be specified by calling:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">void gtk_drawing_area_size (GtkDrawingArea *darea, gint width, gint height);</PRE></TD></TR></TABLE><P>This default size can be overridden, as is true for all widgets,by calling <TTCLASS="LITERAL">gtk_widget_set_usize()</TT>, and that, in turn, canbe overridden if the user manually resizes the the window containingthe drawing area.</P><P>It should be noted that when we create a DrawingArea widget, we are<ICLASS="EMPHASIS">completely</I> responsible for drawing the contents. If ourwindow is obscured then uncovered, we get an exposure event and mustredraw what was previously hidden.</P><P>Having to remember everything that was drawn on the screen so wecan properly redraw it can, to say the least, be a nuisance. Inaddition, it can be visually distracting if portions of thewindow are cleared, then redrawn step by step. The solution tothis problem is to use an offscreen <ICLASS="EMPHASIS">backing pixmap</I>.Instead of drawing directly to the screen, we draw to an imagestored in server memory but not displayed, then when the imagechanges or new portions of the image are displayed, we copy therelevant portions onto the screen.</P><P>To create an offscreen pixmap, we call the function:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">GdkPixmap* gdk_pixmap_new (GdkWindow *window, gint width, gint height, gint depth);</PRE></TD></TR></TABLE><P>The <TTCLASS="LITERAL">window</TT> parameter specifies a GDK window that this pixmaptakes some of its properties from. <TTCLASS="LITERAL">width</TT> and <TTCLASS="LITERAL">height</TT>specify the size of the pixmap. <TTCLASS="LITERAL">depth</TT> specifies the <ICLASS="EMPHASIS">colordepth</I>, that is the number of bits per pixel, for the new window.If the depth is specified as <TTCLASS="LITERAL">-1</TT>, it will match the depthof <TTCLASS="LITERAL">window</TT>.</P><P>We create the pixmap in our "configure_event" handler. This eventis generated whenever the window changes size, including when itis originally created.</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">/* Backing pixmap for drawing area */static GdkPixmap *pixmap = NULL;/* Create a new backing pixmap of the appropriate size */static gintconfigure_event (GtkWidget *widget, GdkEventConfigure *event){ if (pixmap) gdk_pixmap_unref(pixmap); pixmap = gdk_pixmap_new(widget->window, widget->allocation.width, widget->allocation.height, -1); gdk_draw_rectangle (pixmap, widget->style->white_gc, TRUE, 0, 0, widget->allocation.width, widget->allocation.height); return TRUE;}</PRE></TD></TR></TABLE><P>The call to <TTCLASS="LITERAL">gdk_draw_rectangle()</TT> clears the pixmapinitially to white. We'll say more about that in a moment.</P><P>Our exposure event handler then simply copies the relevant portionof the pixmap onto the screen (we determine the area we needto redraw by using the event->area field of the exposure event):</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">/* Redraw the screen from the backing pixmap */static gintexpose_event (GtkWidget *widget, GdkEventExpose *event){ gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], pixmap, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); return FALSE;}</PRE></TD></TR></TABLE><P>We've now seen how to keep the screen up to date with our pixmap, buthow do we actually draw interesting stuff on our pixmap? There are alarge number of calls in GTK's GDK library for drawing on<ICLASS="EMPHASIS">drawables</I>. A drawable is simply something that can be drawnupon. It can be a window, a pixmap, or a bitmap (a black and whiteimage). We've already seen two such calls above,<TTCLASS="LITERAL">gdk_draw_rectangle()</TT> and <TTCLASS="LITERAL">gdk_draw_pixmap()</TT>. Thecomplete list is:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">gdk_draw_line ()gdk_draw_rectangle ()gdk_draw_arc ()gdk_draw_polygon ()gdk_draw_string ()gdk_draw_text ()gdk_draw_pixmap ()gdk_draw_bitmap ()gdk_draw_image ()gdk_draw_points ()gdk_draw_segments ()</PRE></TD></TR></TABLE><P>See the reference documentation or the header file<TTCLASS="LITERAL"><gdk/gdk.h></TT> for further details on these functions.These functions all share the same first two arguments. The firstargument is the drawable to draw upon, the second argument is a<ICLASS="EMPHASIS">graphics context</I> (GC). </P><P>A graphics context encapsulates information about things such asforeground and background color and line width. GDK has a full set offunctions for creating and modifying graphics contexts, but to keepthings simple we'll just use predefined graphics contexts. Each widgethas an associated style. (Which can be modified in a gtkrc file, seethe section GTK's rc file.) This, among other things, stores a numberof graphics contexts. Some examples of accessing these graphicscontexts are:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">widget->style->white_gcwidget->style->black_gcwidget->style->fg_gc[GTK_STATE_NORMAL]widget->style->bg_gc[GTK_WIDGET_STATE(widget)]</PRE></TD></TR></TABLE><P>The fields <TTCLASS="LITERAL">fg_gc</TT>, <TTCLASS="LITERAL">bg_gc</TT>, <TTCLASS="LITERAL">dark_gc</TT>, and<TTCLASS="LITERAL">light_gc</TT> are indexed by a parameter of type<TTCLASS="LITERAL">GtkStateType</TT> which can take on the values:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">GTK_STATE_NORMAL,GTK_STATE_ACTIVE,GTK_STATE_PRELIGHT,GTK_STATE_SELECTED,GTK_STATE_INSENSITIVE</PRE></TD></TR></TABLE><P>For instance, for <TTCLASS="LITERAL">GTK_STATE_SELECTED</TT> the default foregroundcolor is white and the default background color, dark blue.</P><P>Our function <TTCLASS="LITERAL">draw_brush()</TT>, which does the actual drawingon the screen, is then:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">/* Draw a rectangle on the screen */static voiddraw_brush (GtkWidget *widget, gdouble x, gdouble y){ GdkRectangle update_rect; update_rect.x = x - 5; update_rect.y = y - 5; update_rect.width = 10; update_rect.height = 10; gdk_draw_rectangle (pixmap, widget->style->black_gc, TRUE, update_rect.x, update_rect.y, update_rect.width, update_rect.height); gtk_widget_draw (widget, &update_rect);}</PRE></TD></TR></TABLE><P>After we draw the rectangle representing the brush onto the pixmap,we call the function:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">void gtk_widget_draw (GtkWidget *widget, GdkRectangle *area);</PRE></TD></TR></TABLE><P>which notifies X that the area given by the <TTCLASS="LITERAL">area</TT> parameterneeds to be updated. X will eventually generate an expose event(possibly combining the areas passed in several calls to<TTCLASS="LITERAL">gtk_widget_draw()</TT>) which will cause our expose event handlerto copy the relevant portions to the screen.</P><P>We have now covered the entire drawing program except for a fewmundane details like creating the main window.</P></DIV><DIVCLASS="NAVFOOTER"><HRALIGN="LEFT"WIDTH="100%"><TABLEWIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><AHREF="sec-eventhandling.html"><<< Previous</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="gtk-tut.html">Home</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><AHREF="sec-addingxinputsupport.html">Next >>></A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Event Handling</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="ch-scribble.html">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Adding XInput support</TD></TR></TABLE></DIV> </td> </tr></table> </td> </tr></table></body></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -