📄 gtkfaq.sgml
字号:
<sect1>How do I catch a double click event (in a list widget, for example)?<p>Tim Janik wrote to gtk-list (slightly modified):Define a signal handler:<tscreen><verb>gintsignal_handler_event(GtkWiget *widget, GdkEvenButton *event, gpointer func_data){ if (GTK_IS_LIST_ITEM(widget) && (event->type==GDK_2BUTTON_PRESS || event->type==GDK_3BUTTON_PRESS) ) { printf("I feel %s clicked on button %d\", event->type==GDK_2BUTTON_PRESS ? "double" : "triple", event->button); } return FALSE;}</verb></tscreen>And connect the handler to your object:<tscreen><verb>{ /* list, list item init stuff */ gtk_signal_connect(GTK_OBJECT(list_item), "button_press_event", GTK_SIGNAL_FUNC(signal_handler_event), NULL); /* and/or */ gtk_signal_connect(GTK_OBJECT(list_item), "button_release_event", GTK_SIGNAL_FUNC(signal_handler_event), NULL); /* something else */}</verb></tscreen>and, Owen Taylor wrote:Note that a single button press will be received beforehand, andif you are doing this for a button, you will therefore also get a"clicked" signal for the button. (This is going to be true forany toolkit, since computers aren't good at reading one'smind.) <!-- ----------------------------------------------------------------- --><sect1>By the way, what are the differences between signals and events?<p>First of all, Havoc Pennington gives a rather complete description of thedifferences between events and signals in his free book (two chapters canbe found at <htmlurl url="http://www106.pair.com/rhp/sample_chapters.html"name="http://www106.pair.com/rhp/sample_chapters.html">).Moreover, Havoc posted this to the <tt/gtk-list/<quote> Events are a stream of messages received from the X server. They drive the Gtk main loop; which more or less amounts to "wait for events, process them" (not exactly, it is really more general than that and can wait on many different input streams at once). Events are a Gdk/Xlib concept.<P> Signals are a feature of GtkObject and its subclasses. They have nothing to do with any input stream; really a signal is just a way to keep a list of callbacks around and invoke them ("emit" the signal). There are lots of details and extra features of course. Signals are emitted by object instances, and are entirely unrelated to the Gtk main loop. Conventionally, signals are emitted "when something changes" about the object emitting the signal.<P> Signals and events only come together because GtkWidget happens to emit signals when it gets events. This is purely a convenience, so you can connect callbacks to be invoked when a particular widget receives a particular event. There is nothing about this that makes signals and events inherently related concepts, any more than emitting a signal when you click a button makes button clicking and signals related concepts.</quote><!-- ----------------------------------------------------------------- --><sect1>I have my signal connected to the the (whatever) event, but it seems I don't catch it. What's wrong?<p>There is some special initialisation to do in order to catch some particular events. In fact, you must set the correct event mask bit of yourwidget before getting some particular events.For example, <tscreen><verb> gtk_widget_add_events(window, GDK_KEY_RELEASE_MASK);</verb></tscreen>lets you catch the key release events. If you want to catch every events,simply us the GDK_ALL_EVENTS_MASK event mask.All the event masks are defined in the <tt/gdktypes.h/ file.<!-- ----------------------------------------------------------------- --><sect1>Is it possible to get some text displayed which is truncated to fit inside its allocation? <p>GTK's behavior (no clipping) is a consequence of its attempts toconserve X resources. Label widgets (among others) don't get their ownX window - they just draw their contents on their parent's window.While it might be possible to have clipping occur by setting the clipmask before drawing the text, this would probably cause a substantialperformance penalty.Its possible that, in the long term, the best solution to suchproblems might be just to change gtk to give labels X windows.A short term workaround is to put the label widget inside anotherwidget that does get it's own window - one possible candidate wouldbe the viewport widget.<tscreen><verb>viewport = gtk_viewport (NULL, NULL);gtk_widget_set_usize (viewport, 50, 25);gtk_viewport_set_shadow_type (GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);gtk_widget_show(viewport);label = gtk_label ("a really long label that won't fit");gtk_container_add (GTK_CONTAINER(viewport), label);gtk_widget_show (label);</verb></tscreen>If you were doing this for a bunch of widgets, you might want tocopy gtkviewport.c and strip out the adjustment and shadowfunctionality (perhaps you could call it GtkClipper).<!-- ----------------------------------------------------------------- --><sect1>How do I make my window modal? / How do I make a single window active?<p>After you create your window, do <tt/gtk_grab_add(my_window)/. And after closing the window do <tt/gtk_grab_remove(my_window)/.<!-- ----------------------------------------------------------------- --><sect1>Why doesn't my widget (e.g. progressbar) update?<p>You are probably doing all the changes within a function without returning control to <tt/gtk_main()/. This may be the case if you do some lengthy calculation in your code. Most drawing updates are only placed on a queue, which is processed within <tt/gtk_main()/. You canforce the drawing queue to be processed using something like:<tscreen><verb>while (gtk_events_pending()) gtk_main_iteration();</verb></tscreen>inside you're function that changes the widget.What the above snippet does is run all pending events and high priority idle functions, then return immediately (the drawing is done in a high priority idle function).<!-- ----------------------------------------------------------------- --><sect1>How do I attach data to some GTK+ object/widget?<p>First of all, the attached data is stored in the object_data field of a GtkObject. The type of this field is GData, which is defined in glib.h. So you should read the gdataset.c file in your glib source directory very carefully.There are two (easy) ways to attach some data to a gtk object. Using <tt/gtk_object_set_data()/ and <tt/gtk_object_get_data()/ seems to be the most common way to do this, as it provides a powerfull interface to connect objects and data.<tscreen><verb>void gtk_object_set_data(GtkObject *object, const gchar *key, gpointer data);gpointer gtk_object_get_data(GtkObject *object, const gchar *key);</verb></tscreen>Since a short example is better than any lengthy speech:<tscreen><verb>struct my_struct p1,p2,*result;GtkWidget *w;gtk_object_set_data(GTK_OBJECT(w),"p1 data",(gpointer)&p1);gtk_object_set_data(GTK_OBJECT(w),"p2 data",(gpointer)&p2);result = gtk_object_get_data(GTK_OBJECT(w),"p1 data");</verb></tscreen>The <tt/gtk_object_set_user_data()/ and <tt/gtk_object_get_user_data()/functions does exactly the same thingas the functions above, but does not let you specify the "key" parameter.Instead, it uses a standard "user_data" key. Note that the use of thesefunctions is deprecated in 1.2. They only provide a compatibility mode with some old gtk packages.<!-- ----------------------------------------------------------------- --><sect1>How do I remove the data I have attached to an object?<p>When attaching the data to the object, you can use the <tt/gtk_object_set_data_full()/function. The three first arguments of the function are the same as in<tt/gtk_object_set_data()/. The fourth one is a pointer to a callback functionwhich is called when the data is destroyed. The data is destroyed whenyou:<itemize><item> destroy the object<item> replace the data with a new one (with the same key)<item> replace the data with NULL (with the same key)</itemize><!-- ----------------------------------------------------------------- --><sect1>How could I get any widgets position?<p>As Tim Janik pointed out, there are different cases, and each case requiresa different solution.<itemize><item> If you want the position of a widget relative to its parent, you should use <tt/widget->allocation.x/ and <tt/widget->allocation.y/.<item> If you want the position of a window relative to the X root window, you should use <tt/gdk_window_get_geometry()/ or <tt/gdk_window_get_origin()/.<item> Last but not least, if you want to get a Window Manager frame position, you should use <tt/gdk_window_get_deskrelative_origin()/.</itemize><!-- ----------------------------------------------------------------- --><sect1>How do I set the size of a widget/window? How do I prevent the user resizing my window?<p>The <tt/gtk_widget_set_uposition()/ function is used to set theposition of any widget.The <tt/gtk_widget_set_usize()/ function is used to set thesize of a widget. In order to use all the features that are provided bythis function when it acts on a window, you may want to use the<tt/gtk_window_set_policy/ function. The definition of these functionsis:<tscreen><verb>void gtk_widget_set_usize (GtkWidget *widget, gint width, gint height);void gtk_window_set_policy (GtkWindow *window, gint allow_shrink, gint allow_grow, gint auto_shrink);</verb></tscreen><tt/Auto_shrink/ will automatically shrink the window when therequested size of the child widgets goes below the current size of thewindow. <tt/Allow_shrink/ will give the user the authorisation tomake the window smaller that it should normally be. <tt/Allow_grow/will give the user will have the ability to make the windowbigger. The default values for these parameters are:<tscreen><verb>allow_shrink = FALSEallow_grow = TRUEauto_shrink = FALSE</verb></tscreen><!-- ----------------------------------------------------------------- --><sect1>How do I add a popup menu to my GTK+ application?<p>The <tt/menu/ example in the examples/menu directory of the GTK+ distributionimplements a popup menu with this technique :<tscreen><verb>static gint button_press (GtkWidget *widget, GdkEvent *event){ if (event->type == GDK_BUTTON_PRESS) { GdkEventButton *bevent = (GdkEventButton *) event; gtk_menu_popup (GTK_MENU(widget), NULL, NULL, NULL, NULL, bevent->button, bevent->time); /* Tell calling code that we have handled this event; the buck * stops here. */ return TRUE; } /* Tell calling code that we have not handled this event; pass it on. */ return FALSE;}</verb></tscreen><!-- ----------------------------------------------------------------- --><sect1>How do I disable or enable a widget, such as a button?<p>To disable (or to enable) a widget, use the <tt/gtk_widget_set_sensitive()/function. The first parameter is you widget pointer. The second parameteris a boolean value: when this value is TRUE, the widget is enabled.<!-- ----------------------------------------------------------------- --><sect1>Shouldn't the text argument in the gtk_clist_* functions be declared const?<p>For example:<verb>gint gtk_clist_prepend (GtkCList *clist, gchar *text[]);</verb>Answer: No, while a type "gchar*" (pointer to char) can automaticallybe cast into "const gchar*" (pointer to const char), this does notapply for "gchar *[]" (array of an unspecified number of pointers tochar) into "const gchar *[]" (array of an unspecified number ofpointers to const char).The type qualifier "const" may be subject to automatic casting, butin the array case, it is not the array itself that needs the (const)qualified cast, but its members, thus changing the whole type.<!-- ***************************************************************** --><sect>Development with GTK+: widget specific questions <!-- ***************************************************************** --><!-- ----------------------------------------------------------------- --><sect1>How do I find out about the selection of a GtkList?<p>Get the selection something like this:<tscreen><verb>GList *sel;sel = GTK_LIST(list)->selection;</verb></tscreen>This is how GList is defined (quoting glist.h):<tscreen><verb>typedef struct _GList GList;struct _GList{ gpointer data; GList *next; GList *prev;};</verb></tscreen>A GList structure is just a simple structure for doubly linked lists.there exist several g_list_*() functions to modify a linked list inglib.h. However the GTK_LIST(MyGtkList)->selection is maintainedby the gtk_list_*() functions and should not be modified.The selection_mode of the GtkList determines the selectionfacilities of a GtkList and therefore the contentsof GTK_LIST(AnyGtkList)->selection:<verb>selection_mode GTK_LIST()->selection contents------------------------------------------------------GTK_SELECTION_SINGLE) selection is either NULL or contains a GList* pointer for a single selected item.GTK_SELECTION_BROWSE) selection is NULL if the list contains no widgets, otherwise it contains a GList* pointer
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -