📄 gtk_tut_it-20.html
字号:
le parti corrispondenti.<P><P>Per creare una ppixmap fuori dallo schermo, usiamo la funzione:<P><BLOCKQUOTE><CODE><PRE>GdkPixmap* gdk_pixmap_new (GdkWindow *window, gint width, gint height, gint depth);</PRE></CODE></BLOCKQUOTE><P>Il parametro <CODE>window</CODE>specifica una finestra GDK dalla quale questapixmap prende alcune delle sue proprietà. <CODE>width</CODE> e <CODE>height</CODE>specificano le dimensioni della pixmap. <CODE>depth</CODE> specifica la <EM>profondità di colore</EM>, cioè il numero di bit per ogni pixel, perla nuova pixmap. Se alla profondità è assegnato il valore <CODE>-1</CODE>, questaverrà posta identica a quella di <CODE>window</CODE>.<P><P>Creiamo la pixmap all'interno del gestore di ``configure_event''. Questo eventoè generato ogni volta che la finestra cambia di dimensione, compreso ilmomento in cui viene creata per la prima volta.<P><BLOCKQUOTE><CODE><PRE>/* Pixmap di supporto per l'area di disegno */static GdkPixmap *pixmap = NULL;/* Creare una pixmap della dimensione appropriata */static gintconfigure_event (GtkWidget *widget, GdkEventConfigure *event){ if (pixmap) { gdk_pixmap_destroy(pixmap); } pixmap = gdk_pixmap_new(widget->window, widget->allocation.width, widget->allocation.height, -1); gdk_draw_rectangle (pixmap, widget->style->white_gc, TRUE, 0, 0, widget->allocation.width, widget->allocation.height); return TRUE;}</PRE></CODE></BLOCKQUOTE><P>La chiamata a <CODE>gdk_draw_rectangle()</CODE> inizialmente rende bianca l'interapixmap. Fra un momento ne riparleremo.<P><P>Il gestore dell'evento ``esposizione'', copia quindi la porzione appropriatadella pixmap sullo schermo (determiniamo qual è l'area da ridisegnare usandoil campo event->area dell'evento di esposizione):<P><BLOCKQUOTE><CODE><PRE>/* Ridisegna sullo schermo a partire dalla pixmap di supporto */static gintexpose_event (GtkWidget *widget, GdkEventExpose *event){ gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], pixmap, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); return FALSE;}</PRE></CODE></BLOCKQUOTE><P>Abbiamo quindi visto come tenete aggiornato lo schermo con la nostrapixmap, ma come facciamo per disegnare delle cose interessanti sullapixmap? Ci sono un bel po' di funzioni nella libreria GDK di GTK cheservono per disegnare su superfici <EM>disegnabili</EM>. Una superficiedisegnabile è semplicemente qualcosa su cui si può disegnare un'immagine.Può essere una finestra, una pixmap o una bitmap (un'immagine in bianco enero). Abbiamo già visto sopra due di chiamate,<CODE>gdk_draw_rectangle()</CODE> and <CODE>gdk_draw_pixmap()</CODE>. La listacompleta è la seguente:<P><BLOCKQUOTE><CODE><PRE>gdk_draw_line ()gdk_draw_rectangle ()gdk_draw_arc ()gdk_draw_polygon ()gdk_draw_string ()gdk_draw_text ()gdk_draw_pixmap ()gdk_draw_bitmap ()gdk_draw_image ()gdk_draw_points ()gdk_draw_segments ()</PRE></CODE></BLOCKQUOTE><P>Per ulteriori dettagli su queste funzioni, vedete la documentazione diriferimento nei file header <CODE><gdk/gdk.h></CODE>.Tutte queste funzioni hanno i medesimi primi due argomenti. Il primoè la superficie disegnabili su cui disegnare, il secondo è un <EM>contesto grafico</EM> (GC). <P><P>Un contesto grafico incapsula delle informazioni riguardo a cose comeil colore di sfondo e di primo piano e lo spessore della linea.GDK ha un ampio insieme di funzioni per crare e modificare contesti grafici,ma per tenere le cose semplici useremo solo dei contesti grafici predefiniti.Ogni widget ha uno stile associato (che può essere modificato agendo su unfile gtkrc). Questo, fra le altre cose, contiene un certo numero di contestigrafici. Alcuni esempi di come accedere a questi contesti grafici sonoi seguenti:<P><BLOCKQUOTE><CODE><PRE>widget->style->white_gcwidget->style->black_gcwidget->style->fg_gc[GTK_STATE_NORMAL]widget->style->bg_gc[GTK_WIDGET_STATE(widget)]</PRE></CODE></BLOCKQUOTE><P>I campi <CODE>fg_gc</CODE>, <CODE>bg_gc</CODE>, <CODE>dark_gc</CODE>, e<CODE>light_gc</CODE> sono indicizzati tramite un parametri di tipo<CODE>GtkStateType</CODE>, che può assumere i valori:<P><BLOCKQUOTE><CODE><PRE>GTK_STATE_NORMAL,GTK_STATE_ACTIVE,GTK_STATE_PRELIGHT,GTK_STATE_SELECTED,GTK_STATE_INSENSITIVE</PRE></CODE></BLOCKQUOTE><P>Per esempio, per <CODE>GTK_STATE_SELECTED</CODE> il colore di sfondo predefinitoè blu scuro e quello di primo piano bianco.<P><P>La nostra funzione <CODE>draw_brush()</CODE>, che efettivamente disegna sulloschermo, diventa quindi:<P><BLOCKQUOTE><CODE><PRE>/* Disegna un rettangolo sullo schermo */static voiddraw_brush (GtkWidget *widget, gdouble x, gdouble y){ GdkRectangle update_rect; update_rect.x = x - 5; update_rect.y = y - 5; update_rect.width = 10; update_rect.height = 10; gdk_draw_rectangle (pixmap, widget->style->black_gc, TRUE, update_rect.x, update_rect.y, update_rect.width, update_rect.height); gtk_widget_draw (widget, &update_rect);}</PRE></CODE></BLOCKQUOTE><P>Dopo aver disegnato il rettangolo sulla pixmap, chiamiamo la funzione:<P><BLOCKQUOTE><CODE><PRE>void gtk_widget_draw (GtkWidget *widget, GdkRectangle *area);</PRE></CODE></BLOCKQUOTE><P>che notifica a X che l'area data dal parametro <CODE>area</CODE> deve essereaggiornata. X poi genererà un evento di esposizione (che può essere combinatocon le aree passate da diverse chiamate a <CODE>gtk_widget_draw()</CODE>) chefarà sì che il nostro gestore dell'evento di esposizione, copi le porzionirilevanti sullo schermo.<P><P>Abbiamo a questo punto creato tutto il programma di disegno, tranne cheper qualche dettaglio irrilevante come la creazione della finestra principale.Il codice sorgente completo è reperibile dove avete ottenuto questo tutorial,oppure da:<P><A HREF="http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial">http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial</A><P><H2><A NAME="ss20.4">20.4 Aggiungere il supporto per XInput</A></H2><P>Al giorno d'oggi è possibile acquistare dei dispositivi abbastanza a buonmercato, come tavolette grafice, che permettono di disegnare con unaespressività artistica molto semplificata rispetto ad un mouse.Il modo più semplice per usare questi dispositivi è di sostituirlisemplicemente al mouse, ma in questo modo si perdono molti dei lorovantaggi, come:<P><UL><LI> Sensibilità alla pressione</LI><LI> Sensibilità all'inclinazione</LI><LI> Posizionamento infra-pixel</LI><LI> Ingressi multipli (per esempio, uno stilo che contiene sia una ``matita''sia una ``gomma'')</LI></UL><P>Per ulteriori informazioni sulle estensioni XInput, vedere l'<A HREF="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html">XInput-HOWTO</A>.<P><P>Se esaminiamo, per esempio, la definizione completa della strutturaGdkEventMotion, possiamo vedere che contiene dei campi per il supportodelle informazioni estese dai dispositivi.<P><BLOCKQUOTE><CODE><PRE>struct _GdkEventMotion{ GdkEventType type; GdkWindow *window; guint32 time; gdouble x; gdouble y; gdouble pressure; gdouble xtilt; gdouble ytilt; guint state; gint16 is_hint; GdkInputSource source; guint32 deviceid;};</PRE></CODE></BLOCKQUOTE><P><CODE>pressure</CODE> fornisce la pressione sotto forma di un numero decimalecompreso fra 0 e 1. <CODE>xtilt</CODE> e <CODE>ytilt</CODE> possono assumere valoricompresi fra -1 e 1, corrispondenti al grado di inclinazione in ciascunadirezione. <CODE>source</CODE> e <CODE>deviceid</CODE> specificano il dispositivo per ilquale si è verificato l'evento in due modi distinti. <CODE>source</CODE> da alcunesemplici informazioni sul tipo di dispositivo, e può assumere i valori:<P><BLOCKQUOTE><CODE><PRE>GDK_SOURCE_MOUSEGDK_SOURCE_PENGDK_SOURCE_ERASERGDK_SOURCE_CURSOR</PRE></CODE></BLOCKQUOTE><P><CODE>deviceid</CODE> specifica invece un identificativo numerico univoco per ildispositivo. Questo può essere a sua volta utilizzato per avere ulterioriinformazioni sul dispositivo tramite la chiamata a <CODE>gdk_input_list_devices()</CODE>(vedi sotto). Il valore speciale <CODE>GDK_CORE_POINTER</CODE> viene usato per identificareil dispositivo di puntamento principale (di solito il mouse).<P><H3>Abilitare le informazioni estese</H3><P>Per far sì che GTK sappia che ci interessano le informazioni estese daidispositivi, basta aggiungere un'unica linea al nostro programma:<P><BLOCKQUOTE><CODE><PRE>gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);</PRE></CODE></BLOCKQUOTE><P>Dando il valore <CODE>GDK_EXTENSION_EVENTS_CURSOR</CODE>, diciamo che ci interessanogli eventi relativi alle estensioni, ma solo se non dobbiamo disegnare da noiil nostro cursore. Si veda più sotto alla sezione <A HREF="#sec_Further_Sophistications">Ulteriori Sofisticazioni</A> per ulterioriinformazioni sul modo si disegnare i cursori. Potremmo anche dare i valori<CODE>GDK_EXTENSION_EVENTS_ALL</CODE> se vogliamo disegnare il nostro cursore o<CODE>GDK_EXTENSION_EVENTS_NONE</CODE> se vogliamo tornare alle condizioni predefinite.<P><P>Comunque, non finisce tutto qui. Non ci sono estensioni abilitate per difetto.Abbiamo bisogno di un meccanismo per permettere agli utenti l'abilitazione ela configurazione delle estensioni dei loro dispositivi, GTK fornisce ilwidget InputDialog per automatizzare questo processo. La seguente proceduramostra come gestire un widget InputDialog. Crea la finestra di dialogo nelcaso non sia presente, mentre la porta in primo piano in caso contrario.<P><BLOCKQUOTE><CODE><PRE>voidinput_dialog_destroy (GtkWidget *w, gpointer data){ *((GtkWidget **)data) = NULL;}voidcreate_input_dialog (){ static GtkWidget *inputd = NULL; if (!inputd) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -