📄 gtk_tut_it-16.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML><HEAD> <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9"> <TITLE>GTK Tutorial: La gestione delle selezioni</TITLE> <LINK HREF="gtk_tut_it-17.html" REL=next> <LINK HREF="gtk_tut_it-15.html" REL=previous> <LINK HREF="gtk_tut_it.html#toc16" REL=contents></HEAD><BODY BGCOLOR="#FFFFFF"><A HREF="gtk_tut_it-17.html">Avanti</A><A HREF="gtk_tut_it-15.html">Indietro</A><A HREF="gtk_tut_it.html#toc16">Indice</A><HR NOSHADE><H2><A NAME="s16">16. La gestione delle selezioni</A></H2><H2><A NAME="ss16.1">16.1 Overview</A></H2><P><P>Le <EM>selezioni</EM> sono un tipo di comunicazione tra processisupportato da GTK. Una selezione identifica un frammento di dati; per esempio, una porzione di testo selezionata dall'utente in qualche modo,magari con il mouse. Su un display solo un'applicazione alla volta(il <EM>proprietario</EM>) puó essere proprietaria di unaparticolare selezione, sicché quando un'applicazione richiedeuna selezione il precedente proprietario deve comunicare all'utente chela selezione è stata ceduta. Altre applicazioni possono richiedereil contenuto di una selezione in diverse forme, chiamate <EM>obiettivi</EM>.Ci può essere un numero qualsiasi di selezioni, ma la maggior partedelle applicazioni X può gestirne solo una, la <EM>selezioneprimaria</EM>.<P><P>Nella maggior parte dei casi per una applicazione GTK non è necessario gestire esplicitamente le selezioni. I widget standard,come quello di Ingresso, hanno già la capacità dichiedere la selezione se necessario (p. e., quando l'utenteseleziona sul testo), e di recuperare il contenuto di una selezionedi un altro widget o di un'altra applicazione (p. e., quando l'utenteclicca il tasto centrale del mouse). Ci possono comunque essere deicasi nei quali si vuole dare ad altri widget la capacità difornire la selezione, o si vogliono recuperare degli obiettivi nonsupportati direttamente.<P><P>Un concetto fondamentale necessario per comprendere la gestione delleselezioni è quello di <EM>atomo</EM>. Un atomo è un interoche identifica univocamente una stringa (su un certo display).Certi atomi sono predefiniti dal server X, e in alcuni casi in <CODE>gtk.h</CODE>ci sono costanti corrispondenti a questi atomi. Per esempio, la costante<CODE>GDK_PRIMARY_SELECTION</CODE> corrisponde alla stringa ``PRIMARY''.Negli altri casi bisogna usare le funzioni <CODE>gdk_atom_intern()</CODE>per ottenere l'atomo corrispondente ad una stringa, e <CODE>gdk_atom_name()</CODE>per ottenere il nome di un atomo. Sia le selezioni sia gli obiettivi sonoidentificati da atomi.<H2><A NAME="ss16.2">16.2 Recuperare le selezioni</A></H2><P><P>Il recupero di una selezione è un processo asincrono. Per iniziare il processo, si chiama:<BLOCKQUOTE><CODE><PRE>gint gtk_selection_convert (GtkWidget *widget, GdkAtom selection, GdkAtom target, guint32 time)</PRE></CODE></BLOCKQUOTE><P>Questo <EM>converte</EM> la selezione nella forma specificata dall'obiettivo <CODE>target</CODE>. Se possibile, il campo <CODE>time</CODE> dovrebbe essere il tempo dell'evento che ha attivato la selezione.Questo aiuta a far si che gli eventi avvengano nell'ordine in cuil'utente li ha richiesti. Se comunque non fosse disponibile (peresempio, se la conversione è stata attivata da un segnale di``cliccato''), allora si può usare la costante <CODE>GDK_CURRENT_TIME</CODE>.<P><P>Quando il proprietario di una selezione risponde ad una richiesta,un segnale ``selection_received'' (selezione ricevuta) viene inviatoalla vostra applicazione. Il gestore di questo segnale riceve un puntatore ad una struttura <CODE>GtkSelectionData</CODE>, che èdefinita nel modo seguente:<BLOCKQUOTE><CODE><PRE>struct _GtkSelectionData{ GdkAtom selection; GdkAtom target; GdkAtom type; gint format; guchar *data; gint length;};</PRE></CODE></BLOCKQUOTE><CODE>selection</CODE> e <CODE>target</CODE> sono i valori da voi specificatinella chiamata <CODE>gtk_selection_convert()</CODE>. <CODE>type</CODE> èun atomo che identifica il tipo di dati restituiti dal proprietario dellaselezione. Alcuni valori possibili sono ``STRING'', una stringa di caratteri latin-1, ``ATOM'', una serie di atomi, ``INTEGER'', un intero, ecc. La maggior parte degli obiettivi può restituire solo un tipo.<CODE>format</CODE> ci dà la lunghezza delle unità (per esempio caratteri)in bit. Di solito, quando si ricevono i dati non ci si cura di questo.<CODE>data</CODE> è un puntatore ai dati restituiti, e <CODE>length</CODE>è la lunghezza dei dati restituiti, in byte. Se <CODE>length</CODE>è negativo allora si è verificato un errore e non èstato possibile recuperare la selezione. Questo può avvenire senessuna applicazione era proprietaria della selezione, o se si èrichiesto un obiettivo non supportato dall'applicazione. Viene garantitoche il buffer sia un byte più lungo di <CODE>length</CODE>; il bytein più sarà sempre zero, in modo che non sia necessarioricopiare le stringhe solo per farle terminare con zero.<P><P>Nell'esempio che segue viene recuperato l'obiettivo speciale ``TARGETS'',che è una lista di tutti gli obiettivi in cui può essereconvertita la selezione.<BLOCKQUOTE><CODE><PRE>/* gettargets.c */#include <gtk/gtk.h>void selection_received (GtkWidget *widget, GtkSelectionData *selection_data, gpointer data);/* Gestore di segnale chiamato quando l'utente clicca nel bottone *//* "Get Targets" */voidget_targets (GtkWidget *widget, gpointer data){ static GdkAtom targets_atom = GDK_NONE; /* Prende l'atomo corrispondente alla stringa "TARGETS" */ if (targets_atom == GDK_NONE) targets_atom = gdk_atom_intern ("TARGETS", FALSE); /* E richiede l'obiettivo "TARGETS" per la selezione primaria */ gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom, GDK_CURRENT_TIME);}/* Gestore di segnale chiamato quando il proprietario della selezione *//* restituisce i dati */voidselection_received (GtkWidget *widget, GtkSelectionData *selection_data, gpointer data){ GdkAtom *atoms; GList *item_list; int i; /* **** IMPORTANTE **** Controlla che il recupero sia riuscito */ if (selection_data->length < 0) { g_print ("Selection retrieval failed\n"); return; } /* Make sure we got the data in the expected form */ if (selection_data->type != GDK_SELECTION_TYPE_ATOM) { g_print ("Selection \"TARGETS\" was not returned as atoms!\n"); return; } /* Stampa gli atomi ricevuti */ atoms = (GdkAtom *)selection_data->data; item_list = NULL; for (i=0; i<selection_data->length/sizeof(GdkAtom); i++) { char *name; name = gdk_atom_name (atoms[i]); if (name != NULL) g_print ("%s\n",name); else g_print ("(bad atom)\n"); } return;}int main (int argc, char *argv[]){ GtkWidget *window; GtkWidget *button; gtk_init (&argc, &argv); /* Create the toplevel window */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (window), "Event Box"); gtk_container_border_width (GTK_CONTAINER (window), 10); gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (gtk_exit), NULL); /* Crea un bottone che l'utente può cliccare per ottenere gli obiettivi */ button = gtk_button_new_with_label ("Get Targets"); gtk_container_add (GTK_CONTAINER (window), button); gtk_signal_connect (GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC (get_targets), NULL); gtk_signal_connect (GTK_OBJECT(button), "selection_received", GTK_SIGNAL_FUNC (selection_received), NULL); gtk_widget_show (button); gtk_widget_show (window); gtk_main (); return 0;}</PRE></CODE></BLOCKQUOTE><P><H2><A NAME="ss16.3">16.3 Fornire una selezione </A></H2><P>Fornire la selezione è un po' più complicato. Bisognaregistrare i gestori che verranno chiamati quando viene richiesta lapropria selezione. Per ogni coppia selezione/obiettivo che si gestiràoccorre una chiamata a:<P><BLOCKQUOTE><CODE><PRE>void gtk_selection_add_handler (GtkWidget *widget, GdkAtom selection, GdkAtom target, GtkSelectionFunction function, GtkRemoveFunction remove_func, gpointer data);</PRE></CODE></BLOCKQUOTE><P><CODE>widget</CODE>, <CODE>selection</CODE>, e <CODE>target</CODE> identificano le richiesteche questo gestore soddisferà. <CODE>remove_func</CODE>, se non èNULL, verrà chiamato quando il gestore di segnale viene rimosso.Questo è utile, per esempio, per linguaggi interpretati ai qualiserve di tener traccia di un conteggio di riferimento per <CODE>data</CODE>.<P><P>La funzione di richiamo ha la forma:<P><BLOCKQUOTE><CODE><PRE>typedef void (*GtkSelectionFunction) (GtkWidget *widget, GtkSelectionData *selection_data, gpointer data);</PRE></CODE></BLOCKQUOTE><P>La GtkSelectionData è la stessa di prima, ma stavolta siamoresponsabili di riempire i campi <CODE>type</CODE>, <CODE>format</CODE>, <CODE>data</CODE>,e <CODE>length</CODE>. (Il campo <CODE>format</CODE> qui è effettivamente importante - il server X lo usa per capire se occorre che i bytedei dati vengano scambiati o no. Di solito sarà 8 - cioèun carattere - o 32 - cioè un intero.) Questo viene fattochiamando la funzione:<P><BLOCKQUOTE><CODE><PRE>void gtk_selection_data_set (GtkSelectionData *selection_data, GdkAtom type, gint format, guchar *data, gint length);</PRE></CODE></BLOCKQUOTE>Questa funzione si prende cura di fare propriamente una copia dei datiin modo che non ci si debba preoccupare di conservarli (è opportunoevitare di riempire a mano i campi della struttura GtkSelectionData).<P><P>Quando richiesto dall'utente, richiederete la proprietà della selezionechiamando:<P><BLOCKQUOTE><CODE><PRE>gint gtk_selection_owner_set (GtkWidget *widget, GdkAtom selection, guint32 time);</PRE></CODE></BLOCKQUOTE><P>Se un'altra applicazione richiede la proprietà della selezione,riceverete un evento di azzeramento della selezione (``selection_clear_event'').<P>Come esempio di fornitura della selezione, il programma seguente aggiungela funzionalità di selezione a un bottone di attivazione. Quando ilbottone viene premuto, il programma richiede la selezione primaria.L'unico obiettivo supportato (oltre a certi obiettivi come ``TARGETS''fornito dalla stessa GTK) è l'obiettivo ``STRING''. Quando vienerichiesto questo obiettivo, viene restituita una rappresentazione stringadel tempo.<P><BLOCKQUOTE><CODE><PRE>/* setselection.c */#include <gtk/gtk.h>#include <time.h>/* Richiamata quando l'utente attiva la selezione */ voidselection_toggled (GtkWidget *widget, gint *have_selection){ if (GTK_TOGGLE_BUTTON(widget)->active) { *have_selection = gtk_selection_owner_set (widget, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); /* se il richiamo della selezione è fallito, si riporta il bottone nello stato non premuto */ if (!*have_selection) gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE); } else { if (*have_selection) { /* Prima di annullare la selezione mettendone a NULL il proprietario, controlliamo se siamo i veri proprietari */ if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window) gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); *have_selection = FALSE; } }}/* Chiamata quando un'altra applicazione richiede la selezione */gintselection_clear (GtkWidget *widget, GdkEventSelection *event, gint *have_selection){ *have_selection = FALSE; gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE); return TRUE;}/* Fornisce come selezione il tempo attuale */voidselection_handle (GtkWidget *widget, GtkSelectionData *selection_data, gpointer data){ gchar *timestr; time_t current_time; current_time = time (NULL); timestr = asctime (localtime(&current_time)); /* Quando si restituisce una singola stringa, non occorre che finisca con NULL. Questo verrà fatto automaticamente */ gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING, 8, timestr, strlen(timestr));}intmain (int argc, char *argv[]){ GtkWidget *window; GtkWidget *selection_button; static int have_selection = FALSE; gtk_init (&argc, &argv); /* Crea la finestra di livello superiore */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (window), "Event Box"); gtk_container_border_width (GTK_CONTAINER (window), 10); gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (gtk_exit), NULL); /* Crea un bottone a commutazione che agisce come la selezione */ selection_button = gtk_toggle_button_new_with_label ("Claim Selection"); gtk_container_add (GTK_CONTAINER (window), selection_button); gtk_widget_show (selection_button); gtk_signal_connect (GTK_OBJECT(selection_button), "toggled", GTK_SIGNAL_FUNC (selection_toggled), &have_selection); gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event", GTK_SIGNAL_FUNC (selection_clear), &have_selection); gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY, GDK_SELECTION_TYPE_STRING, selection_handle, NULL); gtk_widget_show (selection_button); gtk_widget_show (window); gtk_main (); return 0;}</PRE></CODE></BLOCKQUOTE><P><HR NOSHADE><A HREF="gtk_tut_it-17.html">Avanti</A><A HREF="gtk_tut_it-15.html">Indietro</A><A HREF="gtk_tut_it.html#toc16">Indice</A></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -