📄 gtkfaq.txt
字号:
} 55..44.. WWhhyy ddoonn''tt tthhee ccoonntteennttss ooff aa bbuuttttoonn mmoovvee wwhheenn tthhee bbuuttttoonn iiss pprreesssseedd?? HHeerree''ss aa ppaattcchh ttoo mmaakkee iitt wwoorrkk tthhaatt wwaayy...... From: Peter Mattis The reason buttons don't move their child down and to the right when they are depressed is because I don't think that's what is happening visually. My view of buttons is that you are looking at them straight on. That is, the user interface lies in a plane and you're above it looking straight at it. When a button gets pressed it moves directly away from you. To be absolutely correct I guess the child should actually shrink a tiny amount. But I don't see why the child should shift down and to the left. Remember, the child is supposed to be attached to the buttons surface. Its not good for it to appear like the child is slipping on the surface of the button. On a more practical note, I did implement this at one point and determined it didn't look good and removed it. 55..55.. HHooww ttoo II iiddeennttiiffiiyy aa wwiiddggeettss ttoopp lleevveell wwiinnddooww oorr ootthheerr aanncceessttoorr?? There are a couple of ways to find the top level parent of a widget. The easier way is to call the gtk_widget_top_level() function that returns a pointer to a GtkWidget that is the top level window. A more complicated way to do this (but less limited, as it allows the user to get the closest ancestor of a known type) is to use gtk_widget_get_ancestor() as in: GtkWidget *widget; widget = gtk_widget_get_ancestor(w, GTK_TYPE_WINDOW); Since virtually all the GTK_TYPEs can be used as the second parameter of this function, you can get any parent widget of a particular widget. Suppose you have an hbox which contains a vbox, which in turn contains some other atomic widget (entry, label, etc. To find the master hbox using the entry widget simply use: GtkWidget *hbox; hbox = gtk_widget_get_ancestor(w, GTK_TYPE_HBOX); 55..66.. HHooww ddoo II ccaattcchh aa ddoouubbllee cclliicckk eevveenntt ((iinn aa lliisstt wwiiddggeett,, ffoorr eexxaamm-- ppllee))?? Tim Janik wrote to gtk-list (slightly modified): Define a signal handler: gint signal_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; } And connect the handler to your object: { /* 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 */ } and, Owen Taylor wrote: Note that a single button press will be received beforehand, and if you are doing this for a button, you will therefore also get a "clicked" signal for the button. (This is going to be true for any toolkit, since computers aren't good at reading one's mind.) 55..77.. BByy tthhee wwaayy,, wwhhaatt aarree tthhee ddiiffffeerreenncceess bbeettwweeeenn ssiiggnnaallss aanndd eevveennttss?? First of all, Havoc Pennington gives a rather complete description of the differences between events and signals in his free book (two chapters can be found at http://www106.pair.com/rhp/sample_chapters.html). Moreover, Havoc posted this to the gtk-list 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. 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. 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. 55..88.. II hhaavvee mmyy ssiiggnnaall ccoonnnneecctteedd ttoo tthhee tthhee ((wwhhaatteevveerr)) eevveenntt,, bbuutt iitt sseeeemmss II ddoonn''tt ccaattcchh iitt.. WWhhaatt''ss wwrroonngg?? 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 your widget before getting some particular events. For example, gtk_widget_add_events(window, GDK_KEY_RELEASE_MASK); 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 gdktypes.h file. 55..99.. IIss iitt ppoossssiibbllee ttoo ggeett ssoommee tteexxtt ddiissppllaayyeedd wwhhiicchh iiss ttrruunnccaatteedd ttoo ffiitt iinnssiiddee iittss aallllooccaattiioonn?? GTK's behavior (no clipping) is a consequence of its attempts to conserve X resources. Label widgets (among others) don't get their own X window - they just draw their contents on their parent's window. While it might be possible to have clipping occur by setting the clip mask before drawing the text, this would probably cause a substantial performance penalty. Its possible that, in the long term, the best solution to such problems might be just to change gtk to give labels X windows. A short term workaround is to put the label widget inside another widget that does get it's own window - one possible candidate would be the viewport widget. 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); If you were doing this for a bunch of widgets, you might want to copy gtkviewport.c and strip out the adjustment and shadow functionality (perhaps you could call it GtkClipper). 55..1100.. HHooww ddoo II mmaakkee mmyy wwiinnddooww mmooddaall?? // HHooww ddoo II mmaakkee aa ssiinnggllee wwiinnddooww aaccttiivvee?? After you create your window, do gtk_grab_add(my_window). And after closing the window do gtk_grab_remove(my_window). 55..1111.. WWhhyy ddooeessnn''tt mmyy wwiiddggeett ((ee..gg.. pprrooggrreessssbbaarr)) uuppddaattee?? You are probably doing all the changes within a function without returning control to 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 gtk_main(). You can force the drawing queue to be processed using something like: while (gtk_events_pending()) gtk_main_iteration(); 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). 55..1122.. HHooww ddoo II aattttaacchh ddaattaa ttoo ssoommee GGTTKK++ oobbjjeecctt//wwiiddggeett?? 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 gtk_object_set_data() and 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. void gtk_object_set_data(GtkObject *object, const gchar *key, gpointer data); gpointer gtk_object_get_data(GtkObject *object, const gchar *key); Since a short example is better than any lengthy speech: 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"); The gtk_object_set_user_data() and gtk_object_get_user_data() functions does exactly the same thing as 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 these functions is deprecated in 1.2. They only provide a compatibility mode with some old gtk packages. 55..1133.. HHooww ddoo II rreemmoovvee tthhee ddaattaa II hhaavvee aattttaacchheedd ttoo aann oobbjjeecctt?? When attaching the data to the object, you can use the gtk_object_set_data_full() function. The three first arguments of the function are the same as in gtk_object_set_data(). The fourth one is a pointer to a callback function which is called when the data is destroyed. The data is destroyed when you: +o destroy the object +o replace the data with a new one (with the same key) +o replace the data with NULL (with the same key) 55..1144.. HHooww ccoouulldd II ggeett aannyy wwiiddggeettss ppoossiittiioonn?? As Tim Janik pointed out, there are different cases, and each case requires a different solution. +o If you want the position of a widget relative to its parent, you should use widget->allocation.x and widget->allocation.y. +o If you want the position of a window relative to the X root window, you should use gdk_window_get_geometry() or gdk_window_get_origin(). +o Last but not least, if you want to get a Window Manager frame position, you should use gdk_window_get_deskrelative_origin(). 55..1155.. HHooww ddoo II sseett tthhee ssiizzee ooff aa wwiiddggeett//wwiinnddooww?? HHooww ddoo II pprreevveenntt tthhee uusseerr rreessiizziinngg mmyy wwiinnddooww?? The gtk_widget_set_uposition() function is used to set the position of any widget. The gtk_widget_set_usize() function is used to set the size of a widget. In order to use all the features that are provided by this function when it acts on a window, you may want to use the gtk_window_set_policy function. The definition of these functions is: 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); Auto_shrink will automatically shrink the window when the requested size of the child widgets goes below the current size of the window. Allow_shrink will give the user the authorisation to make the window smaller that it should normally be. Allow_grow will give the user will have the ability to make the window bigger. The default values for these parameters are: allow_shrink = FALSE allow_grow = TRUE auto_shrink = FALSE 55..1166.. HHooww ddoo II aadddd aa ppooppuupp mmeennuu ttoo mmyy GGTTKK++ aapppplliiccaattiioonn?? The menu example in the examples/menu directory of the GTK+ distribution implements a popup menu with this technique : 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; } 55..1177.. HHooww ddoo II ddiissaabbllee oorr eennaabbllee aa wwiiddggeett,, ssuucchh aass aa bbuuttttoonn?? To disable (or to enable) a widget, use the gtk_widget_set_sensitive() function. The first parameter is you widget pointer. The second parameter is a boolean value: when this value is TRUE, the widget is enabled. 55..1188.. SShhoouullddnn''tt tthhee tteexxtt aarrgguummeenntt iinn tthhee ggttkk__cclliisstt__** ffuunnccttiioonnss bbee ddeeccllaarreedd ccoonnsstt?? For example: gint gtk_clist_prepend (GtkCList *clist, gchar *text[]); Answer: No, while a type "gchar*" (pointer to char) can automatically be cast into "const gchar*" (pointer to const char), this does not
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -