⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gnome-canvas-events.html

📁 linux下gnome编程
💻 HTML
📖 第 1 页 / 共 3 页
字号:
<HTML><HEAD><TITLE>Canvas Events</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.61"><LINKREL="HOME"TITLE="Writing GNOME Applications"HREF="index.html"><LINKREL="UP"TITLE="The GNOME Canvas"HREF="gnome-canvas.html"><LINKREL="PREVIOUS"TITLE="Canvas Items"HREF="gnome-canvas-items.html"><LINKREL="NEXT"TITLE="GNU Free Documentation License"HREF="fdl.html"></HEAD><BODYCLASS="SECT1"><DIVCLASS="NAVHEADER"><TABLEWIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">Writing GNOME Applications</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="gnome-canvas-items.html">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">Chapter 11. The GNOME Canvas</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="fdl.html">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="GNOME-CANVAS-EVENTS">Canvas Events</A></H1><P>        As we learned in Section 11.1.4, only the Canvas widget as a        whole can receive true GDK events. To pass events on to        individual Canvas items, the Canvas must crack open the GDK        events and translate them into internal Canvas events. In this        section we'll investigate how to hook into the Canvas's        synthetic event queue and react to a variety of mouse and        keyboard events.      </P><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN1259">The Event Callback</A></H2><P>          To avoid reinventing the wheel and to keep things simpler          and more consistent for the developer, the GNOME Canvas          reuses the existing GdkEvent structure, with a few minor          modifications to its contents, before passing it on to the          targeted Canvas item. The most important difference is          that the event coordinates are translated from regular          pixel-based window coordinates into abstract world          coordinates. Fortunately, the coordinate fields in GdkEvent          are already of type gdouble, because of the subpixel          resolution of certain drawing devices, like drawing          tablets, so the Canvas can reuse the GdkEvent structure ex-          actly as it's defined in GTK+.        </P><P>          The item event callback looks like any other event callbacks          you'll see for a normal GTK+ widget, depending on whether or          not you care about the extra data parameter:        </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">gint (* event) (GnomeCanvasItem *item, GdkEvent *event);gint (* event) (GnomeCanvasItem *item, GdkEvent *event,    gpointer data);        </PRE></TD></TR></TABLE><P>          You set up the callback and connect the signal just as you          would with a normal event handler. As far as your Canvas          item is concerned (aside from coordinate system          remapping), it is registering itself for a true GDK          event. Naturally, you'll have to connect an event signal          for every Canvas item you want to accept outside events. Any          items you don't connect will ignore all keyboard and mouse          events and will behave like a static part of the          background. The application can still move the          nonconnected items around and change their properties          programmatically, through the API; the Canvas just won't be          able to react to GDK events directed at those particular          items. Listing 11.7 shows what your event handler might look          like.        </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">Listing 11.7 GnomeCanvasItem Event Handlergint handle_canvas_event(GnomeCanvasItem *item, GdkEvent *event,    gpointer data){  switch (event-&#62;type)  {  case GDK_BUTTON_PRESS:    /* Handle mouse button press */    return TRUE;  case GDK_BUTTON_RELEASE:    /* Handle mouse button release */    return TRUE;  case GDK_MOTION_NOTIFY:    /* Handle mouse movement */    return TRUE;  }  /* Event not handled; try parent item */  return FALSE;}int main(int argc, char *argv[]){  GnomeCanvasItem *item;  gpointer *itemdata;  ...  gtk_signal_connect(GTK_OBJECT(item), "event",    GTK_SIGNAL_FUNC(handle_canvas_event), itemdata);}        </PRE></TD></TR></TABLE><P>          The Canvas first sends the event to the item with which the          user is interacting; in the case of a mouse event, this is          the item the cursor is directly over.  If that item's event          handler returns a TRUE, the item swallows the event and the          event processing stops there. However, if the item's event          handler returns a FALSE, indicating that the item chose not          to process the event or doesn't care if its parent groups or          items see the event too, the Canvas continues to pass the          event up the hierarchy, from child item to parent item,          until an event handler returns TRUE or the event reaches the          Canvas's root item. In the example in Listing 11.7 we return          TRUE for all the events we handle, but it's just as legal to          allow a Canvas event to be handled multiple times, by          returning a FALSE from the callback function.        </P></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN1267">Clicks and Double Clicks</A></H2><P>          Handling a mouse click on a Canvas item is just like          handling a mouse click on a true GTK+ widget. You check the          GdkEvent for the type of event and react accordingly. The          most common way to do this is with a switch( ) statement, as          we did in Listing 11.7.        </P><P>          At first, it may seem intimidating to have to create an          event handler for every Canvas item you want to interact          with. If you had to do that with every normal widget, your          application would quickly bloat into a maze of event-          processing code. (Fortunately, most of this event code is          hidden inside each widget, safely tucked away in the          respective GTK+ or GNOME library.)        </P><P>          Really, though, you don't need that much event code for          Canvas items.  Items can receive only a small subset of the          possible GDK events. The only Canvas item events you'll have          to worry about are mouse clicks, mouse movements, keyboard          events, and any item-specific events a derived Canvas item          might declare. The Canvas takes care of all the rest,          including the painting and exposures, focus switching,          selection, and creation. You can also share the same event          handler with multiple similar items, using the handler's          user data parameter if you need to distinguish among them.        </P><P>          Let's dive a little deeper into mouse click events. The item          can receive two types of click events: a button press and a          button release. You can find out which type of click event,          if any, the current event is by checking the type field of          the GdkEvent structure, and you can react to that value in a          switch( ) statement, as in Listing 11.7. The GdkEvent          structure is really a union of similar structures, each          one populated with fields useful to a specific event type,          as shown in Listing 11.8. Peruse the GDK documentation for          more information about these various event types. For now,          we're interested in only the GdkEventButton structure (see          Listing 11.9).        </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">Listing 11.8 GdkEvent Structureunion _GdkEvent{  GdkEventType type;  GdkEventAny any;  GdkEventExpose expose;  GdkEventNoExpose no_expose;  GdkEventVisibility visibility;  GdkEventMotion motion;  GdkEventButton button;  GdkEventKey key;  GdkEventCrossing crossing;  GdkEventFocus focus_change;  GdkEventConfigure configure;  GdkEventProperty property;  GdkEventSelection selection;  GdkEventProximity proximity;  GdkEventClient client;  GdkEventDND dnd;};        </PRE></TD></TR></TABLE><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">Listing 11.9 GdkEventButton Structurestruct _GdkEventButton{  GdkEventType type;  GdkWindow *window;  gint8 send_event;  guint32 time;  gdouble x;  gdouble y;  gdouble pressure;  gdouble xtilt;  gdouble ytilt;  guint state;  guint button;  GdkInputSource source;  guint32 deviceid;  gdouble x_root, y_root;};        </PRE></TD></TR></TABLE><P>          The GdkEvent union carries GdkEventButton as its button          field. Thus you can find out the coordinates of the button          click (in world coordinates) inside your event handler with          event-&#62;button.x and event-&#62;button.y. If you need to          differentiate which mouse button the user clicked, you can          check the value of event-&#62;button.button. This value can be          any integer from 1 through 5.  The left button is typically          1, the middle button 2, and the right button 3, although          the user is allowed to remap these values through the X          server. Buttons 4 and 5 are most often used by wheel          mice. GTK+ does its best to handle these values for you, so          you're better off ignoring these last two buttons.        </P><P>          The other useful GdkEventButton field is state. The state          field tells you what else was being held down at the time of          the current event, not including the button or key that          caused the event. You can use this field to determine if the          user made a multibutton click, a Ctrl-click, a          Shift-Alt-click, or something else. To express more than one          concurrent state, GTK+ defines an enumeration of bit flags,          as shown in Listing 11.10. The corresponding bit is turned          on in GdkEventButton's state field for each modifier that          was active at the time of the event.        </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">Listing 11.10 GdkModifierType Enumerationtypedef enum{  GDK_SHIFT_MASK    = 1 &#60;&#60; 0,  GDK_LOCK_MASK     = 1 &#60;&#60; 1,  GDK_CONTROL_MASK  = 1 &#60;&#60; 2,  GDK_MOD1_MASK     = 1 &#60;&#60; 3,  GDK_MOD2_MASK     = 1 &#60;&#60; 4,  GDK_MOD3_MASK     = 1 &#60;&#60; 5,  GDK_MOD4_MASK     = 1 &#60;&#60; 6,  GDK_MOD5_MASK     = 1 &#60;&#60; 7,  GDK_BUTTON1_MASK  = 1 &#60;&#60; 8,  GDK_BUTTON2_MASK  = 1 &#60;&#60; 9,  GDK_BUTTON3_MASK  = 1 &#60;&#60; 10,  GDK_BUTTON4_MASK  = 1 &#60;&#60; 11,  GDK_BUTTON5_MASK  = 1 &#60;&#60; 12,  GDK_RELEASE_MASK  = 1 &#60;&#60; 13,  GDK_MODIFIER_MASK = 0x3fff} GdkModifierType;        </PRE></TD></TR></TABLE><P>          Of particular note are the Shift and Ctrl keys          (GDK_SHIFT_MASK and GDK_CONTROL_MASK), the Alt or Meta key          (GDK_MOD1_MASK), the Caps Lock key (GDK_LOCK_MASK), and the          mouse buttons (GDK_BUTTON?_MASK). Thus if the user made a          Shift-Ctrl-click with the first mouse button, the state          field would equal (GDK_SHIFT_MASK | GDK_CONTROL_MASK |          GDK_BUTTON1_MASK), and the button field would be set to          1. The GDK_RELEASE_MASK flag isn't used much for Canvas          items.        </P><P>          Be careful not to make direct equality tests against the          state field because often multiple flags are set. For          example, the aforementioned Shift-Ctrl-click would result in          a state field of 261 (256 + 4 + 1), which is not equal to          GDK_SHIFT_MASK's value of 1, nor to GDK_CONTROL_MASK's value          of 4. You should use the binary &#38; operator in your          comparisons:        </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">if((event-&#62;button.state &#38; GDK_SHIFT_MASK) &#38;&#38;  (event-&#62;button.state &#38; GDK_CONTROL_MASK))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -