📄 gtkfaq-5.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML><HEAD> <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9"> <TITLE>GTK+ FAQ: Development with GTK+: general questions</TITLE> <LINK HREF="gtkfaq-6.html" REL=next> <LINK HREF="gtkfaq-4.html" REL=previous> <LINK HREF="gtkfaq.html#toc5" REL=contents></HEAD><BODY BGCOLOR="#FFFFFF"><A HREF="gtkfaq-6.html">Next</A><A HREF="gtkfaq-4.html">Previous</A><A HREF="gtkfaq.html#toc5">Contents</A><HR NOSHADE><H2><A NAME="s5">5. Development with GTK+: general questions</A></H2><H2><A NAME="ss5.1">5.1 What widgets are in GTK?</A></H2><P>The GTK+ Tutorial lists the following widgets:<P><PRE> GtkObject +GtkData | +GtkAdjustment | `GtkTooltips `GtkWidget +GtkContainer | +GtkBin | | +GtkAlignment | | +GtkEventBox | | +GtkFrame | | | `GtkAspectFrame | | +GtkHandleBox | | +GtkItem | | | +GtkListItem | | | +GtkMenuItem | | | | `GtkCheckMenuItem | | | | `GtkRadioMenuItem | | | `GtkTreeItem | | +GtkViewport | | `GtkWindow | | +GtkColorSelectionDialog | | +GtkDialog | | | `GtkInputDialog | | `GtkFileSelection | +GtkBox | | +GtkButtonBox | | | +GtkHButtonBox | | | `GtkVButtonBox | | +GtkHBox | | | +GtkCombo | | | `GtkStatusbar | | `GtkVBox | | +GtkColorSelection | | `GtkGammaCurve | +GtkButton | | +GtkOptionMenu | | `GtkToggleButton | | `GtkCheckButton | | `GtkRadioButton | +GtkCList | `GtkCTree | +GtkFixed | +GtkList | +GtkMenuShell | | +GtkMenuBar | | `GtkMenu | +GtkNotebook | +GtkPaned | | +GtkHPaned | | `GtkVPaned | +GtkScrolledWindow | +GtkTable | +GtkToolbar | `GtkTree +GtkDrawingArea | `GtkCurve +GtkEditable | +GtkEntry | | `GtkSpinButton | `GtkText +GtkMisc | +GtkArrow | +GtkImage | +GtkLabel | | `GtkTipsQuery | `GtkPixmap +GtkPreview +GtkProgressBar +GtkRange | +GtkScale | | +GtkHScale | | `GtkVScale | `GtkScrollbar | +GtkHScrollbar | `GtkVScrollbar +GtkRuler | +GtkHRuler | `GtkVRuler `GtkSeparator +GtkHSeparator `GtkVSeparator</PRE><P><H2><A NAME="ss5.2">5.2 Is GTK+ thread safe? How do I write multi-threaded GTK+ applications?</A></H2><P>The GLib library can be used in a thread-safe mode by callingg_thread_init() before making any other GLib calls. In this mode GLibautomatically locks all internal data structures as needed. Thisdoes not mean that two threads can simultaneously access, forexample, a single hash table, but they can access two different hashtables simultaneously. If two different threads need to access thesame hash table, the application is responsible for lockingitself.<P>When GLib is intialized to be thread-safe, GTK+ is<EM>thread aware</EM>. There is a single global lockthat you must acquire with gdk_threads_enter() beforemaking any GDK calls, and release with gdk_threads_leave()afterwards.<P>A minimal main program for a threaded GTK+ applicationlooks like:<P><PRE>intmain (int argc, char *argv[]){ GtkWidget *window; g_thread_init(NULL); gtk_init(&argc, &argv); window = create_window(); gtk_widget_show(window); gdk_threads_enter(); gtk_main(); gdk_threads_leave(); return(0);}</PRE><P>Callbacks require a bit of attention. Callbacks from GTK+(signals) are made within the GTK+ lock. However callbacksfrom GLib (timeouts, IO callbacks, and idle functions)are made outside of the GTK+ lock. So, within a signalhandler you do not need to call gdk_threads_enter(), butwithin the other types of callbacks, you do.<P><H2><A NAME="ss5.3">5.3 Why do this strange 'x io error' occur when I <CODE>fork()</CODE> in my GTK+ app?</A></H2><P>This is not really a GTK+ problem, and the problem is not related to <CODE>fork()</CODE>too. If the 'x io error' occurs then you probably use the <CODE>exit()</CODE> functionin order to exit from the child process.<P>When GDK opens an X display, it creates a socket file descriptor. When you usethe <CODE>exit()</CODE> function, you implicitly close all the open file descriptors,and the underlying X library really doesn't like this.<P>The right function to use here is <CODE>_exit()</CODE>. <P>Erik Mouw gave the following piece of code about the fork()/exit() problem(slightly modified)<P><BLOCKQUOTE><CODE><PRE> int pid = fork(); if(pid==-1) { perror("fork"); exit(-1); } else if(pid==0) /* child */ { retval=system("a command"); /* can use exec* functions here */ _exit(retval); /* notice _exit() instead of exit() */ } else /* parent */ { for(;;) { if(waitpid(pid, &status, WNOHANG) == pid) { waitpid(pid, &status, WUNTRACED); /* anti zombie code */ break; } } return(WEXITSTATUS(status)); }</PRE></CODE></BLOCKQUOTE><P><H2><A NAME="ss5.4">5.4 Why don't the contents of a button move when the button is pressed? Here's a patch to make it work that way...</A></H2><P>From: Peter Mattis<P><BLOCKQUOTE>The reason buttons don't move their child down and to the right whenthey are depressed is because I don't think that's what is happeningvisually. My view of buttons is that you are looking at them straighton. That is, the user interface lies in a plane and you're above itlooking straight at it. When a button gets pressed it moves directlyaway from you. To be absolutely correct I guess the child shouldactually shrink a tiny amount. But I don't see why the child shouldshift down and to the left. Remember, the child is supposed to beattached to the buttons surface. Its not good for it to appear likethe child is slipping on the surface of the button.<P>On a more practical note, I did implement this at one point anddetermined it didn't look good and removed it.</BLOCKQUOTE> <P><H2><A NAME="ss5.5">5.5 How to I identifiy a widgets top level window or other ancestor?</A></H2><P>There are a couple of ways to find the top level parent of awidget. The easier way is to call the <CODE>gtk_widget_top_level()</CODE>function that returns a pointer to a GtkWidget that is the top levelwindow.<P>A more complicated way to do this (but less limited, as it allowsthe user to get the closest ancestor of a known type) is to use<CODE>gtk_widget_get_ancestor()</CODE> as in:<P><BLOCKQUOTE><CODE><PRE> GtkWidget *widget; widget = gtk_widget_get_ancestor(w, GTK_TYPE_WINDOW);</PRE></CODE></BLOCKQUOTE><P>Since virtually all the GTK_TYPEs can be used as the second parameter ofthis function, you can get any parent widget of a particularwidget. Suppose you have an hbox which contains a vbox, which in turn containssome other atomic widget (entry, label, etc. To find the master hboxusing the <CODE>entry</CODE> widget simply use:<P><BLOCKQUOTE><CODE><PRE> GtkWidget *hbox; hbox = gtk_widget_get_ancestor(w, GTK_TYPE_HBOX);</PRE></CODE></BLOCKQUOTE><P><P><H2><A NAME="ss5.6">5.6 How do I catch a double click event (in a list widget, for example)?</A></H2><P>Tim Janik wrote to gtk-list (slightly modified):<P>Define a signal handler:<P><BLOCKQUOTE><CODE><PRE>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;}</PRE></CODE></BLOCKQUOTE><P>And connect the handler to your object:<P><BLOCKQUOTE><CODE><PRE>{ /* 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",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -