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

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關(guān)于我們
? 蟲蟲下載站

?? 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

?? 快捷鍵說明

復(fù)制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
亚洲综合免费观看高清在线观看| 欧美日韩电影在线| 884aa四虎影成人精品一区| 日本一区二区视频在线| 日日夜夜免费精品| 91麻豆6部合集magnet| 亚洲影院在线观看| 成人av在线资源网| 亚洲精品在线免费观看视频| 亚洲国产日韩一级| 91视视频在线观看入口直接观看www | 久久久久9999亚洲精品| 丝袜美腿亚洲一区二区图片| 色综合天天综合网国产成人综合天 | 精品久久久久久久久久久久包黑料 | 精品久久久久一区二区国产| 亚洲一区二区三区四区在线免费观看 | 欧美日韩综合一区| 亚洲欧美在线视频| 国产成人8x视频一区二区| 欧美精品一区男女天堂| 日本欧美肥老太交大片| 欧美精品高清视频| 性欧美疯狂xxxxbbbb| 色成人在线视频| 中文字幕第一区综合| 国产麻豆成人传媒免费观看| 日韩欧美国产精品| 免费不卡在线视频| 日韩一区二区三区四区| 美日韩黄色大片| 日韩午夜电影av| 久久精品国产亚洲一区二区三区 | 99久久综合狠狠综合久久| 国产欧美精品区一区二区三区 | 丝袜亚洲另类丝袜在线| 精品视频在线免费| 亚洲bdsm女犯bdsm网站| 欧美日韩精品系列| 日本欧美在线看| 日韩欧美激情在线| 精品一区二区在线视频| 久久亚洲精品小早川怜子| 国产在线乱码一区二区三区| 亚洲精品一区二区三区香蕉| 国产麻豆一精品一av一免费| 久久蜜臀精品av| 国产999精品久久久久久| 国产欧美一区二区精品忘忧草| 国产不卡免费视频| 国产精品美女久久久久久久| 99免费精品在线观看| 亚洲欧美日韩久久| 一本色道久久综合亚洲aⅴ蜜桃 | 中文字幕人成不卡一区| 91麻豆视频网站| 亚洲国产一区视频| 日韩欧美精品在线视频| 国产成人精品一区二区三区四区 | 99久久久精品| 亚洲香肠在线观看| 日韩免费福利电影在线观看| 国产在线精品免费| 日韩一区在线免费观看| 欧美伊人久久久久久久久影院| 午夜日韩在线观看| 精品久久久三级丝袜| 成人涩涩免费视频| 洋洋av久久久久久久一区| 欧美丰满嫩嫩电影| 国产高清不卡二三区| 椎名由奈av一区二区三区| 欧美羞羞免费网站| 激情综合网av| 自拍偷在线精品自拍偷无码专区| 在线观看日韩av先锋影音电影院| 日韩电影免费一区| 国产喷白浆一区二区三区| 色综合久久六月婷婷中文字幕| 天堂影院一区二区| 国产欧美综合在线观看第十页| 色拍拍在线精品视频8848| 青娱乐精品在线视频| 中文字幕+乱码+中文字幕一区| 色菇凉天天综合网| 国模少妇一区二区三区| 亚洲欧美色图小说| 日韩精品一区二区三区四区| 成人精品免费看| 亚洲成a人v欧美综合天堂| 2欧美一区二区三区在线观看视频| 99久久精品国产精品久久| 性久久久久久久久久久久| 中文字幕免费观看一区| 欧美日韩高清一区二区不卡 | 97久久人人超碰| 婷婷久久综合九色综合伊人色| 久久先锋影音av鲁色资源| 91免费看片在线观看| 国内外精品视频| 亚洲丰满少妇videoshd| 久久精品水蜜桃av综合天堂| 欧美日韩国产美| 懂色av一区二区三区免费观看| 亚洲一二三四在线| 中文字幕av一区 二区| 欧美一级午夜免费电影| 91浏览器打开| 国产精品夜夜爽| 无吗不卡中文字幕| 最新日韩av在线| 2024国产精品视频| 欧美精品1区2区| 99麻豆久久久国产精品免费| 精品亚洲porn| 日韩中文字幕区一区有砖一区| 国产精品福利影院| 精品国产乱码久久久久久浪潮| 欧美丝袜丝nylons| 91免费视频网址| 国产成人午夜高潮毛片| 美女被吸乳得到大胸91| 亚洲福利视频一区| 亚洲精品亚洲人成人网 | 欧美va亚洲va在线观看蝴蝶网| 在线看一区二区| 不卡的电视剧免费网站有什么| 精品一区二区精品| 午夜精品福利在线| 亚洲一区在线观看免费| 亚洲欧美在线另类| 国产精品三级电影| 久久精品免费在线观看| 精品欧美一区二区在线观看| 欧美老肥妇做.爰bbww| 欧美综合在线视频| 色综合天天综合狠狠| 不卡av电影在线播放| 国产激情偷乱视频一区二区三区 | 亚洲老妇xxxxxx| 亚洲欧美怡红院| 日韩一区在线播放| 国产精品传媒在线| 亚洲国产精品ⅴa在线观看| 2020国产精品自拍| 精品国一区二区三区| 精品国产三级电影在线观看| 欧美一区二区黄色| 91精品国产欧美一区二区| 51精品秘密在线观看| 欧美精三区欧美精三区| 精品视频在线看| 在线不卡a资源高清| 欧美日韩高清在线播放| 欧美高清视频一二三区| 91精品国产黑色紧身裤美女| 欧美猛男超大videosgay| 欧美日韩国产小视频在线观看| 欧美日韩中文国产| 在线电影一区二区三区| 欧美一区二区三区四区五区 | 欧美一区二区人人喊爽| 欧美一级精品大片| 欧美mv和日韩mv国产网站| 2017欧美狠狠色| 中文av字幕一区| 中文字幕一区二区三区乱码在线 | 久久精品亚洲一区二区三区浴池| 久久综合久久综合久久综合| 久久精品一级爱片| 国产精品久久久久国产精品日日| 一区在线播放视频| 亚洲最大成人网4388xx| 日日夜夜精品视频天天综合网| 久久精品国产免费| 国产精品538一区二区在线| 成+人+亚洲+综合天堂| 成人手机电影网| 色哟哟一区二区| 欧美精品在线一区二区| 久久影视一区二区| 国产精品久久久久一区二区三区共| 亚洲日本va在线观看| 亚洲成人激情社区| 另类小说综合欧美亚洲| 成人免费的视频| 欧美午夜在线一二页| 欧美成人精品高清在线播放 | 在线成人免费观看| 国产亚洲午夜高清国产拍精品 | 欧美高清在线视频| 亚洲综合无码一区二区| 视频一区二区三区入口| 国产一区二区久久| 色婷婷av久久久久久久| 日韩三级中文字幕| 国产精品理论片| 午夜精品一区二区三区三上悠亚| 麻豆91精品视频| 99国产精品一区|