📄 gtk_tut-2.html
字号:
<P>
<UL>
<LI> event</LI>
<LI> button_press_event</LI>
<LI> button_release_event</LI>
<LI> motion_notify_event</LI>
<LI> delete_event</LI>
<LI> destroy_event</LI>
<LI> expose_event</LI>
<LI> key_press_event</LI>
<LI> key_release_event</LI>
<LI> enter_notify_event</LI>
<LI> leave_notify_event</LI>
<LI> configure_event</LI>
<LI> focus_in_event</LI>
<LI> focus_out_event</LI>
<LI> map_event</LI>
<LI> unmap_event</LI>
<LI> property_notify_event</LI>
<LI> selection_clear_event</LI>
<LI> selection_request_event</LI>
<LI> selection_notify_event</LI>
<LI> proximity_in_event</LI>
<LI> proximity_out_event</LI>
<LI> drag_begin_event</LI>
<LI> drag_request_event</LI>
<LI> drag_end_event</LI>
<LI> drop_enter_event</LI>
<LI> drop_leave_event</LI>
<LI> drop_data_available_event</LI>
<LI> other_event</LI>
</UL>
<P>In order to connect a callback function to one of these events, you
use the function gtk_signal_connect, as described above, using one of
the above event names as the <CODE>name</CODE> parameter. The callback
function for events has a slightly different form than that for
signals:
<P>
<BLOCKQUOTE><CODE>
<PRE>
void callback_func( GtkWidget *widget,
GdkEvent *event,
gpointer callback_data );
</PRE>
</CODE></BLOCKQUOTE>
<P>GdkEvent is a C <CODE>union</CODE> structure whose type will depend upon which
of the above events has occurred. In order for us to tell which event
has been issued each of the possible alternatives has a <CODE>type</CODE>
parameter which reflects the event being issued. The other components
of the event structure will depend upon the type of the
event. Possible values for the type are:
<P>
<BLOCKQUOTE><CODE>
<PRE>
GDK_NOTHING
GDK_DELETE
GDK_DESTROY
GDK_EXPOSE
GDK_MOTION_NOTIFY
GDK_BUTTON_PRESS
GDK_2BUTTON_PRESS
GDK_3BUTTON_PRESS
GDK_BUTTON_RELEASE
GDK_KEY_PRESS
GDK_KEY_RELEASE
GDK_ENTER_NOTIFY
GDK_LEAVE_NOTIFY
GDK_FOCUS_CHANGE
GDK_CONFIGURE
GDK_MAP
GDK_UNMAP
GDK_PROPERTY_NOTIFY
GDK_SELECTION_CLEAR
GDK_SELECTION_REQUEST
GDK_SELECTION_NOTIFY
GDK_PROXIMITY_IN
GDK_PROXIMITY_OUT
GDK_DRAG_BEGIN
GDK_DRAG_REQUEST
GDK_DROP_ENTER
GDK_DROP_LEAVE
GDK_DROP_DATA_AVAIL
GDK_CLIENT_EVENT
GDK_VISIBILITY_NOTIFY
GDK_NO_EXPOSE
GDK_OTHER_EVENT /* Deprecated, use filters instead */
</PRE>
</CODE></BLOCKQUOTE>
<P>So, to connect a callback function to one of these events we would use
something like:
<P>
<BLOCKQUOTE><CODE>
<PRE>
gtk_signal_connect( GTK_OBJECT(button), "button_press_event",
GTK_SIGNAL_FUNC(button_press_callback),
NULL);
</PRE>
</CODE></BLOCKQUOTE>
<P>This assumes that <CODE>button</CODE> is a Button widget. Now, when the
mouse is over the button and a mouse button is pressed, the function
<CODE>button_press_callback</CODE> will be called. This function may be
declared as:
<P>
<BLOCKQUOTE><CODE>
<PRE>
static gint button_press_callback( GtkWidget *widget,
GdkEventButton *event,
gpointer data );
</PRE>
</CODE></BLOCKQUOTE>
<P>Note that we can declare the second argument as type
<CODE>GdkEventButton</CODE> as we know what type of event will occur for this
function to be called.
<P>The value returned from this function indicates whether the event
should be propagated further by the GTK event handling
mechanism. Returning TRUE indicates that the event has been handled,
and that it should not propagate further. Returning FALSE continues
the normal event handling. See the section on
<A HREF="gtk_tut-18.html#sec_Adv_Events_and_Signals">Advanced Event and Signal Handling</A> for more details on this
propagation process.
<P>For details on the GdkEvent data types, see the appendix entitled
<A HREF="gtk_tut-29.html#sec_GDK_Event_Types">GDK Event Types</A>.
<P>
<H2><A NAME="ss2.5">2.5 Stepping Through Hello World</A>
</H2>
<P>Now that we know the theory behind this, let's clarify by walking
through the example <EM>helloworld</EM> program.
<P>Here is the callback function that will be called when the button is
"clicked". We ignore both the widget and the data in this example, but
it is not hard to do things with them. The next example will use the
data argument to tell us which button was pressed.
<P>
<BLOCKQUOTE><CODE>
<PRE>
void hello( GtkWidget *widget,
gpointer data )
{
g_print ("Hello World\n");
}
</PRE>
</CODE></BLOCKQUOTE>
<P>The next callback is a bit special. The "delete_event" occurs when the
window manager sends this event to the application. We have a choice
here as to what to do about these events. We can ignore them, make
some sort of response, or simply quit the application.
<P>The value you return in this callback lets GTK know what action to
take. By returning TRUE, we let it know that we don't want to have
the "destroy" signal emitted, keeping our application running. By
returning FALSE, we ask that "destroy" be emitted, which in turn will
call our "destroy" signal handler.
<P>
<BLOCKQUOTE><CODE>
<PRE>
gint delete_event( GtkWidget *widget,
GdkEvent *event,
gpointer data )
{
g_print ("delete event occurred\n");
return (TRUE);
}
</PRE>
</CODE></BLOCKQUOTE>
<P>Here is another callback function which causes the program to quit by
calling gtk_main_quit(). This function tells GTK that it is to exit
from gtk_main when control is returned to it.
<P>
<BLOCKQUOTE><CODE>
<PRE>
void destroy( GtkWidget *widget,
gpointer data )
{
gtk_main_quit ();
}
</PRE>
</CODE></BLOCKQUOTE>
<P>I assume you know about the main() function... yes, as with other
applications, all GTK applications will also have one of these.
<P>
<BLOCKQUOTE><CODE>
<PRE>
int main( int argc,
char *argv[] )
{
</PRE>
</CODE></BLOCKQUOTE>
<P>This next part declares pointers to a structure of type
GtkWidget. These are used below to create a window and a button.
<P>
<BLOCKQUOTE><CODE>
<PRE>
GtkWidget *window;
GtkWidget *button;
</PRE>
</CODE></BLOCKQUOTE>
<P>Here is our gtk_init again. As before, this initializes the toolkit,
and parses the arguments found on the command line. Any argument it
recognizes from the command line, it removes from the list, and
modifies argc and argv to make it look like they never existed,
allowing your application to parse the remaining arguments.
<P>
<BLOCKQUOTE><CODE>
<PRE>
gtk_init (&argc, &argv);
</PRE>
</CODE></BLOCKQUOTE>
<P>Create a new window. This is fairly straightforward. Memory is
allocated for the GtkWidget *window structure so it now points to a
valid structure. It sets up a new window, but it is not displayed
until we call gtk_widget_show(window) near the end of our program.
<P>
<BLOCKQUOTE><CODE>
<PRE>
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
</PRE>
</CODE></BLOCKQUOTE>
<P>Here are two examples of connecting a signal handler to an object, in
this case, the window. Here, the "delete_event" and "destroy" signals
are caught. The first is emitted when we use the window manager to
kill the window, or when we use the gtk_widget_destroy() call passing
in the window widget as the object to destroy. The second is emitted
when, in the "delete_event" handler, we return FALSE.
<P>The <CODE>GTK_OBJECT</CODE> and <CODE>GTK_SIGNAL_FUNC</CODE> are macros that perform
type casting and checking for us, as well as aid the readability of
the code.
<P>
<BLOCKQUOTE><CODE>
<PRE>
gtk_signal_connect (GTK_OBJECT (window), "delete_event",
GTK_SIGNAL_FUNC (delete_event), NULL);
gtk_signal_connect (GTK_OBJECT (window), "destroy",
GTK_SIGNAL_FUNC (destroy), NULL);
</PRE>
</CODE></BLOCKQUOTE>
<P>This next function is used to set an attribute of a container object.
This just sets the window so it has a blank area along the inside of
it 10 pixels wide where no widgets will go. There are other similar
functions which we will look at in the section on
<A HREF="gtk_tut-16.html#sec_setting_widget_attributes">Setting Widget Attributes</A><P>And again, <CODE>GTK_CONTAINER</CODE> is a macro to perform type casting.
<P>
<BLOCKQUOTE><CODE>
<PRE>
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
</PRE>
</CODE></BLOCKQUOTE>
<P>This call creates a new button. It allocates space for a new GtkWidget
structure in memory, initializes it, and makes the button pointer
point to it. It will have the label "Hello World" on it when
displayed.
<P>
<BLOCKQUOTE><CODE>
<PRE>
button = gtk_button_new_with_label ("Hello World");
</PRE>
</CODE></BLOCKQUOTE>
<P>Here, we take this button, and make it do something useful. We attach
a signal handler to it so when it emits the "clicked" signal, our
hello() function is called. The data is ignored, so we simply pass in
NULL to the hello() callback function. Obviously, the "clicked" signal
is emitted when we click the button with our mouse pointer.
<P>
<BLOCKQUOTE><CODE>
<PRE>
gtk_signal_connect (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (hello), NULL);
</PRE>
</CODE></BLOCKQUOTE>
<P>We are also going to use this button to exit our program. This will
illustrate how the "destroy" signal may come from either the window
manager, or our program. When the button is "clicked", same as above,
it calls the first hello() callback function, and then this one in the
order they are set up. You may have as many callback functions as you
need, and all will be executed in the order you connected
them. Because the gtk_widget_destroy() function accepts only a
GtkWidget *widget as an argument, we use the
gtk_signal_connect_object() function here instead of straight
gtk_signal_connect().
<P>
<BLOCKQUOTE><CODE>
<PRE>
gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (gtk_widget_destroy),
GTK_OBJECT (window));
</PRE>
</CODE></BLOCKQUOTE>
<P>This is a packing call, which will be explained in depth later on in
<A HREF="gtk_tut-4.html#sec_packing_widgets">Packing Widgets</A>. But it is
fairly easy to understand. It simply tells GTK that the button is to
be placed in the window where it will be displayed. Note that a GTK
container can only contain one widget. There are other widgets, that
are described later, which are designed to layout multiple widgets in
various ways.
<P>
<BLOCKQUOTE><CODE>
<PRE>
gtk_container_add (GTK_CONTAINER (window), button);
</PRE>
</CODE></BLOCKQUOTE>
<P>Now we have everything set up the way we want it to be. With all the
signal handlers in place, and the button placed in the window where it
should be, we ask GTK to "show" the widgets on the screen. The window
widget is shown last so the whole window will pop up at once rather
than seeing the window pop up, and then the button form inside of
it. Although with such a simple example, you'd never notice.
<P>
<BLOCKQUOTE><CODE>
<PRE>
gtk_widget_show (button);
gtk_widget_show (window);
</PRE>
</CODE></BLOCKQUOTE>
<P>And of course, we call gtk_main() which waits for events to come from
the X server and will call on the widgets to emit signals when these
events come.
<P>
<BLOCKQUOTE><CODE>
<PRE>
gtk_main ();
</PRE>
</CODE></BLOCKQUOTE>
<P>And the final return. Control returns here after gtk_quit() is called.
<P>
<BLOCKQUOTE><CODE>
<PRE>
return (0);
</PRE>
</CODE></BLOCKQUOTE>
<P>Now, when we click the mouse button on a GTK button, the widget emits
a "clicked" signal. In order for us to use this information, our
program sets up a signal handler to catch that signal, which
dispatches the function of our choice. In our example, when the button
we created is "clicked", the hello() function is called with a NULL
argument, and then the next handler for this signal is called. This
calls the gtk_widget_destroy() function, passing it the window widget
as its argument, destroying the window widget. This causes the window
to emit the "destroy" signal, which is caught, and calls our destroy()
callback function, which simply exits GTK.
<P>Another course of events is to use the window manager to kill the
window, which will cause the "delete_event" to be emitted. This will
call our "delete_event" handler. If we return TRUE here, the window
will be left as is and nothing will happen. Returning FALSE will cause
GTK to emit the "destroy" signal which of course calls the "destroy"
callback, exiting GTK.
<P>
<HR>
<A HREF="gtk_tut-3.html">Next</A>
<A HREF="gtk_tut-1.html">Previous</A>
<A HREF="gtk_tut.html#toc2">Contents</A>
</BODY>
</HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -