亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? gtk_tut-23.html

?? GTK development guide
?? HTML
?? 第 1 頁 / 共 2 頁
字號:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
 <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.7">
 <TITLE>GTK v1.2 Tutorial: Scribble, A Simple Example Drawing Program</TITLE>
 <LINK HREF="gtk_tut-24.html" REL=next>
 <LINK HREF="gtk_tut-22.html" REL=previous>
 <LINK HREF="gtk_tut.html#toc23" REL=contents>
</HEAD>
<BODY TEXT="#CCCCCC" BGCOLOR="#000000" LINK="#33cc00" VLINK="#009900" ALINK="#FF0000">
<A HREF="gtk_tut-24.html">Next</A>
<A HREF="gtk_tut-22.html">Previous</A>
<A HREF="gtk_tut.html#toc23">Contents</A>
<HR>
<H2><A NAME="s23">23. Scribble, A Simple Example Drawing Program</A></H2>

<H2><A NAME="ss23.1">23.1 Overview</A>
</H2>

<P>In this section, we will build a simple drawing program. In the
process, we will examine how to handle mouse events, how to draw in a
window, and how to do drawing better by using a backing pixmap. After
creating the simple drawing program, we will extend it by adding
support for XInput devices, such as drawing tablets. GTK provides
support routines which makes getting extended information, such as
pressure and tilt, from such devices quite easy.
<P>
<H2><A NAME="ss23.2">23.2 Event Handling</A>
</H2>

<P>The GTK signals we have already discussed are for high-level actions,
such as a menu item being selected. However, sometimes it is useful to
learn about lower-level occurrences, such as the mouse being moved, or
a key being pressed. There are also GTK signals corresponding to these
low-level <EM>events</EM>. The handlers for these signals have an
extra parameter which is a pointer to a structure containing
information about the event. For instance, motion event handlers are
passed a pointer to a GdkEventMotion structure which looks (in part)
like:
<P>
<BLOCKQUOTE><CODE>
<PRE>
struct _GdkEventMotion
{
  GdkEventType type;
  GdkWindow *window;
  guint32 time;
  gdouble x;
  gdouble y;
  ...
  guint state;
  ...
};
</PRE>
</CODE></BLOCKQUOTE>
<P><CODE>type</CODE> will be set to the event type, in this case
<CODE>GDK_MOTION_NOTIFY</CODE>, window is the window in which the event
occurred. <CODE>x</CODE> and <CODE>y</CODE> give the coordinates of the event.
<CODE>state</CODE> specifies the modifier state when the event
occurred (that is, it specifies which modifier keys and mouse buttons
were pressed). It is the bitwise OR of some of the following:
<P>
<BLOCKQUOTE><CODE>
<PRE>
GDK_SHIFT_MASK  
GDK_LOCK_MASK   
GDK_CONTROL_MASK
GDK_MOD1_MASK   
GDK_MOD2_MASK   
GDK_MOD3_MASK   
GDK_MOD4_MASK   
GDK_MOD5_MASK   
GDK_BUTTON1_MASK
GDK_BUTTON2_MASK
GDK_BUTTON3_MASK
GDK_BUTTON4_MASK
GDK_BUTTON5_MASK
</PRE>
</CODE></BLOCKQUOTE>
<P>As for other signals, to determine what happens when an event occurs
we call <CODE>gtk_signal_connect()</CODE>. But we also need let GTK
know which events we want to be notified about. To do this, we call
the function:
<P>
<BLOCKQUOTE><CODE>
<PRE>
void gtk_widget_set_events (GtkWidget *widget,
                            gint      events);
</PRE>
</CODE></BLOCKQUOTE>
<P>The second field specifies the events we are interested in. It
is the bitwise OR of constants that specify different types
of events. For future reference the event types are:
<P>
<BLOCKQUOTE><CODE>
<PRE>
GDK_EXPOSURE_MASK
GDK_POINTER_MOTION_MASK
GDK_POINTER_MOTION_HINT_MASK
GDK_BUTTON_MOTION_MASK     
GDK_BUTTON1_MOTION_MASK    
GDK_BUTTON2_MOTION_MASK    
GDK_BUTTON3_MOTION_MASK    
GDK_BUTTON_PRESS_MASK      
GDK_BUTTON_RELEASE_MASK    
GDK_KEY_PRESS_MASK         
GDK_KEY_RELEASE_MASK       
GDK_ENTER_NOTIFY_MASK      
GDK_LEAVE_NOTIFY_MASK      
GDK_FOCUS_CHANGE_MASK      
GDK_STRUCTURE_MASK         
GDK_PROPERTY_CHANGE_MASK   
GDK_PROXIMITY_IN_MASK      
GDK_PROXIMITY_OUT_MASK     
</PRE>
</CODE></BLOCKQUOTE>
<P>There are a few subtle points that have to be observed when calling
<CODE>gtk_widget_set_events()</CODE>. First, it must be called before the X window
for a GTK widget is created. In practical terms, this means you
should call it immediately after creating the widget. Second, the
widget must have an associated X window. For efficiency, many widget
types do not have their own window, but draw in their parent's window.
These widgets are:
<P>
<BLOCKQUOTE><CODE>
<PRE>
GtkAlignment
GtkArrow
GtkBin
GtkBox
GtkImage
GtkItem
GtkLabel
GtkPixmap
GtkScrolledWindow
GtkSeparator
GtkTable
GtkAspectFrame
GtkFrame
GtkVBox
GtkHBox
GtkVSeparator
GtkHSeparator
</PRE>
</CODE></BLOCKQUOTE>
<P>To capture events for these widgets, you need to use an EventBox
widget. See the section on the 
<A HREF="gtk_tut-10.html#sec_EventBox">EventBox</A> widget for details.
<P>For our drawing program, we want to know when the mouse button is
pressed and when the mouse is moved, so we specify
<CODE>GDK_POINTER_MOTION_MASK</CODE> and <CODE>GDK_BUTTON_PRESS_MASK</CODE>. We also
want to know when we need to redraw our window, so we specify
<CODE>GDK_EXPOSURE_MASK</CODE>. Although we want to be notified via a
Configure event when our window size changes, we don't have to specify
the corresponding <CODE>GDK_STRUCTURE_MASK</CODE> flag, because it is
automatically specified for all windows.
<P>It turns out, however, that there is a problem with just specifying
<CODE>GDK_POINTER_MOTION_MASK</CODE>. This will cause the server to add a new
motion event to the event queue every time the user moves the mouse.
Imagine that it takes us 0.1 seconds to handle a motion event, but the
X server queues a new motion event every 0.05 seconds. We will soon
get way behind the users drawing. If the user draws for 5 seconds,
it will take us another 5 seconds to catch up after they release 
the mouse button! What we would like is to only get one motion
event for each event we process. The way to do this is to 
specify <CODE>GDK_POINTER_MOTION_HINT_MASK</CODE>. 
<P>When we specify <CODE>GDK_POINTER_MOTION_HINT_MASK</CODE>, the server sends
us a motion event the first time the pointer moves after entering
our window, or after a button press or release event. Subsequent 
motion events will be suppressed until we explicitly ask for
the position of the pointer using the function:
<P>
<BLOCKQUOTE><CODE>
<PRE>
GdkWindow*    gdk_window_get_pointer     (GdkWindow       *window,
                                          gint            *x,
                                          gint            *y,
                                          GdkModifierType *mask);
</PRE>
</CODE></BLOCKQUOTE>
<P>(There is another function, <CODE>gtk_widget_get_pointer()</CODE> which
has a simpler interface, but turns out not to be very useful, since
it only retrieves the position of the mouse, not whether the buttons
are pressed.)
<P>The code to set the events for our window then looks like:
<P>
<BLOCKQUOTE><CODE>
<PRE>
  gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
                      (GtkSignalFunc) expose_event, NULL);
  gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
                      (GtkSignalFunc) configure_event, NULL);
  gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
                      (GtkSignalFunc) motion_notify_event, NULL);
  gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
                      (GtkSignalFunc) button_press_event, NULL);

  gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
                         | GDK_LEAVE_NOTIFY_MASK
                         | GDK_BUTTON_PRESS_MASK
                         | GDK_POINTER_MOTION_MASK
                         | GDK_POINTER_MOTION_HINT_MASK);
</PRE>
</CODE></BLOCKQUOTE>
<P>We'll save the "expose_event" and "configure_event" handlers for
later. The "motion_notify_event" and "button_press_event" handlers
are pretty simple:
<P>
<BLOCKQUOTE><CODE>
<PRE>
static gint
button_press_event (GtkWidget *widget, GdkEventButton *event)
{
  if (event->button == 1 &amp;&amp; pixmap != NULL)
      draw_brush (widget, event->x, event->y);

  return TRUE;
}

static gint
motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
{
  int x, y;
  GdkModifierType state;

  if (event->is_hint)
    gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
  else
    {
      x = event->x;
      y = event->y;
      state = event->state;
    }
    
  if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
    draw_brush (widget, x, y);
  
  return TRUE;
}
</PRE>
</CODE></BLOCKQUOTE>
<P>
<H2><A NAME="ss23.3">23.3 The DrawingArea Widget, And Drawing</A>
</H2>

<P>We now turn to the process of drawing on the screen. The 
widget we use for this is the DrawingArea widget. A drawing area
widget is essentially an X window and nothing more. It is a blank
canvas in which we can draw whatever we like. A drawing area
is created using the call:
<P>
<BLOCKQUOTE><CODE>
<PRE>
GtkWidget* gtk_drawing_area_new        (void);
</PRE>
</CODE></BLOCKQUOTE>
<P>A default size for the widget can be specified by calling:
<P>
<BLOCKQUOTE><CODE>
<PRE>
void       gtk_drawing_area_size       (GtkDrawingArea      *darea,
                                        gint                 width,
                                        gint                 height);
</PRE>
</CODE></BLOCKQUOTE>
<P>This default size can be overridden, as is true for all widgets,
by calling <CODE>gtk_widget_set_usize()</CODE>, and that, in turn, can
be overridden if the user manually resizes the the window containing
the drawing area.
<P>It should be noted that when we create a DrawingArea widget, we are
<EM>completely</EM> responsible for drawing the contents. If our
window is obscured then uncovered, we get an exposure event and must
redraw what was previously hidden.
<P>Having to remember everything that was drawn on the screen so we
can properly redraw it can, to say the least, be a nuisance. In
addition, it can be visually distracting if portions of the
window are cleared, then redrawn step by step. The solution to
this problem is to use an offscreen <EM>backing pixmap</EM>.
Instead of drawing directly to the screen, we draw to an image
stored in server memory but not displayed, then when the image
changes or new portions of the image are displayed, we copy the
relevant portions onto the screen.
<P>To create an offscreen pixmap, we call the function:
<P>
<BLOCKQUOTE><CODE>
<PRE>
GdkPixmap* gdk_pixmap_new               (GdkWindow  *window,
                                         gint        width,
                                         gint        height,
                                         gint        depth);
</PRE>
</CODE></BLOCKQUOTE>
<P>The <CODE>window</CODE> parameter specifies a GDK window that this pixmap
takes some of its properties from. <CODE>width</CODE> and <CODE>height</CODE>
specify the size of the pixmap. <CODE>depth</CODE> specifies the <EM>color
depth</EM>, that is the number of bits per pixel, for the new window.
If the depth is specified as <CODE>-1</CODE>, it will match the depth
of <CODE>window</CODE>.
<P>We create the pixmap in our "configure_event" handler. This event
is generated whenever the window changes size, including when it
is originally created.
<P>
<BLOCKQUOTE><CODE>
<PRE>
/* Backing pixmap for drawing area */
static GdkPixmap *pixmap = NULL;

/* Create a new backing pixmap of the appropriate size */
static gint
configure_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>
</CODE></BLOCKQUOTE>
<P>The call to <CODE>gdk_draw_rectangle()</CODE> clears the pixmap
initially to white. We'll say more about that in a moment.
<P>Our exposure event handler then simply copies the relevant portion
of the pixmap onto the screen (we determine the area we need
to redraw by using the event->area field of the exposure event):
<P>
<BLOCKQUOTE><CODE>
<PRE>
/* Redraw the screen from the backing pixmap */
static gint
expose_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>
</CODE></BLOCKQUOTE>
<P>We've now seen how to keep the screen up to date with our pixmap, but
how do we actually draw interesting stuff on our pixmap?  There are a
large number of calls in GTK's GDK library for drawing on
<EM>drawables</EM>. A drawable is simply something that can be drawn
upon. It can be a window, a pixmap, or a bitmap (a black and white
image).  We've already seen two such calls above,
<CODE>gdk_draw_rectangle()</CODE> and <CODE>gdk_draw_pixmap()</CODE>. The
complete list is:
<P>
<BLOCKQUOTE><CODE>
<PRE>
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>
</CODE></BLOCKQUOTE>
<P>See the reference documentation or the header file
<CODE>&lt;gdk/gdk.h&gt;</CODE> for further details on these functions.
These functions all share the same first two arguments. The first
argument is the drawable to draw upon, the second argument is a
<EM>graphics context</EM> (GC). 
<P>A graphics context encapsulates information about things such as
foreground and background color and line width. GDK has a full set of
functions for creating and modifying graphics contexts, but to keep
things simple we'll just use predefined graphics contexts. Each widget
has an associated style. (Which can be modified in a gtkrc file, see
the section GTK's rc file.) This, among other things, stores a number
of graphics contexts. Some examples of accessing these graphics
contexts are:
<P>
<BLOCKQUOTE><CODE>
<PRE>
widget->style->white_gc
widget->style->black_gc
widget->style->fg_gc[GTK_STATE_NORMAL]
widget->style->bg_gc[GTK_WIDGET_STATE(widget)]
</PRE>
</CODE></BLOCKQUOTE>
<P>The fields <CODE>fg_gc</CODE>, <CODE>bg_gc</CODE>, <CODE>dark_gc</CODE>, and
<CODE>light_gc</CODE> are indexed by a parameter of type
<CODE>GtkStateType</CODE> which can take on the values:
<P>
<BLOCKQUOTE><CODE>
<PRE>
GTK_STATE_NORMAL,
GTK_STATE_ACTIVE,
GTK_STATE_PRELIGHT,
GTK_STATE_SELECTED,
GTK_STATE_INSENSITIVE
</PRE>
</CODE></BLOCKQUOTE>
<P>For instance, for <CODE>GTK_STATE_SELECTED</CODE> the default foreground
color is white and the default background color, dark blue.
<P>Our function <CODE>draw_brush()</CODE>, which does the actual drawing

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
免费成人在线影院| 欧美日韩在线综合| 欧美日本一区二区三区| 精品久久久久久久久久久久久久久 | 日韩欧美一区中文| 亚洲免费在线视频| 福利一区福利二区| 日韩美女一区二区三区四区| 一区二区三区国产| 色婷婷久久久亚洲一区二区三区| 欧美成人精品1314www| 亚洲 欧美综合在线网络| 国产成人精品1024| 精品少妇一区二区三区视频免付费| 亚洲精品国产成人久久av盗摄| 国产专区欧美精品| 欧美电影免费观看高清完整版在线| 亚洲色图欧美在线| 国产主播一区二区三区| 日韩欧美一卡二卡| 天堂一区二区在线| 欧美美女直播网站| 亚洲亚洲精品在线观看| 欧洲激情一区二区| 亚洲伊人色欲综合网| 色综合天天综合网国产成人综合天| 国产精品少妇自拍| 成人免费观看av| 国产清纯在线一区二区www| 国产伦精品一区二区三区视频青涩 | 2022国产精品视频| 狠狠色丁香婷婷综合久久片| 精品国产一区二区精华 | 一区二区三区四区高清精品免费观看| www..com久久爱| 日韩理论在线观看| 欧美特级限制片免费在线观看| 亚洲欧美色综合| 色综合久久九月婷婷色综合| 亚洲精品国久久99热| 99精品视频在线观看| 亚洲精品视频一区| 欧美日韩视频一区二区| 奇米影视一区二区三区小说| 久久一日本道色综合| 91福利精品视频| 亚洲亚洲精品在线观看| 日韩一区二区不卡| 国产一区二区三区av电影 | 高清免费成人av| 亚洲女爱视频在线| 欧美日本在线一区| 国内久久精品视频| 国产精品久久久久久久久免费樱桃| 91欧美一区二区| 日韩二区在线观看| 欧美国产一区视频在线观看| 92精品国产成人观看免费| 亚洲黄色免费网站| 精品国产乱码久久久久久老虎 | ...xxx性欧美| 欧美日韩一区小说| 国产黄色成人av| 亚洲一区二区三区四区五区中文| 日韩欧美www| 石原莉奈一区二区三区在线观看| 天堂影院一区二区| 日韩欧美123| 成人a级免费电影| 丝袜国产日韩另类美女| 久久精品视频一区| 欧美日韩国产系列| 91久久精品午夜一区二区| 日本aⅴ免费视频一区二区三区| 国产亚洲va综合人人澡精品| 色婷婷狠狠综合| 精品系列免费在线观看| 亚洲人成精品久久久久久| 日韩欧美国产综合一区| 色婷婷综合久久久中文一区二区| 久久精品国产亚洲5555| 一区二区三区在线观看网站| 久久久99精品免费观看| 欧美日韩一区高清| 色哟哟国产精品| 日韩国产成人精品| 欧美激情中文字幕一区二区| 91麻豆精品国产91久久久资源速度| 国产suv精品一区二区883| 奇米影视一区二区三区| 亚洲图片一区二区| 亚洲色大成网站www久久九九| 欧美mv和日韩mv的网站| 91精品在线免费观看| 色狠狠桃花综合| 不卡的av中国片| 国产美女视频一区| 日本亚洲天堂网| 日韩精品欧美精品| 婷婷六月综合网| 亚洲综合激情另类小说区| 最新欧美精品一区二区三区| 久久品道一品道久久精品| 欧美大片国产精品| 日韩午夜三级在线| 91精品在线免费观看| 欧美精选在线播放| 777久久久精品| 欧美一区二区私人影院日本| 欧美精品在线一区二区三区| 欧美视频在线一区| 欧美专区在线观看一区| 91黄色在线观看| 欧美视频一区二区在线观看| 欧美伊人久久久久久久久影院 | 香港成人在线视频| 亚洲一区二区三区在线看| 一区二区三区免费在线观看| 亚洲美女屁股眼交3| 亚洲欧美偷拍卡通变态| 亚洲宅男天堂在线观看无病毒| 亚洲欧美激情插| 亚洲国产精品自拍| 成人小视频在线| 国产精品99久久久久| 大尺度一区二区| 91亚洲午夜精品久久久久久| 欧美综合久久久| 91精品国产综合久久香蕉的特点 | 免费成人美女在线观看.| 免费在线欧美视频| 国产高清精品网站| 成人晚上爱看视频| 欧美亚洲一区三区| 欧美本精品男人aⅴ天堂| 久久亚洲精精品中文字幕早川悠里| 久久久青草青青国产亚洲免观| 国产精品麻豆视频| 洋洋av久久久久久久一区| 日韩电影一区二区三区| 国产一区91精品张津瑜| 99精品视频在线免费观看| 欧美日韩精品欧美日韩精品一 | 日韩一区二区三区电影在线观看| 欧美变态tickling挠脚心| 中文字幕av资源一区| 亚洲国产精品久久人人爱蜜臀| 麻豆精品视频在线观看| 91尤物视频在线观看| 在线不卡一区二区| 国产精品视频麻豆| 午夜精品国产更新| 国产成人8x视频一区二区| 欧美日韩视频专区在线播放| 久久精品夜色噜噜亚洲a∨| 一区二区三区在线视频播放| 精品一区二区久久久| 色婷婷亚洲婷婷| 久久久不卡网国产精品二区| 亚洲自拍都市欧美小说| 大陆成人av片| 欧美大片一区二区| 一区二区三区免费在线观看| 国产精品香蕉一区二区三区| 欧美色图在线观看| 1000精品久久久久久久久| 久久成人免费网| 欧美精品色一区二区三区| 国产精品国产三级国产有无不卡 | 日韩你懂的电影在线观看| 一区二区三区在线免费观看| 国产风韵犹存在线视精品| 91精品欧美一区二区三区综合在| 亚洲欧美另类小说视频| 国产成人亚洲综合a∨猫咪| 3atv一区二区三区| 一区二区三区不卡在线观看 | 欧美日本一道本在线视频| 中文字幕精品一区 | 蜜臀久久99精品久久久久久9| 色婷婷综合中文久久一本| 欧美激情资源网| 国产精品一级片在线观看| 日韩欧美一区二区不卡| 视频一区免费在线观看| 日本精品一级二级| 日韩毛片视频在线看| www.亚洲色图.com| 国产精品天天摸av网| 国产成人免费在线| 国产人成亚洲第一网站在线播放| 国精产品一区一区三区mba桃花 | 国产午夜一区二区三区| 美女尤物国产一区| 日韩免费视频线观看| 久久av老司机精品网站导航| 日韩欧美不卡在线观看视频| 日本欧美韩国一区三区| 欧美一区二区大片| 久久99国产精品久久99果冻传媒|