⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gtk_tut_it-19.html

📁 gtk是linux一款强大的夸平台的图形化开发工具
💻 HTML
📖 第 1 页 / 共 4 页
字号:
  GTK_TYPE_UINT,  GTK_TYPE_LONG,  GTK_TYPE_ULONG,  GTK_TYPE_FLOAT,  GTK_TYPE_DOUBLE,  GTK_TYPE_STRING,  GTK_TYPE_ENUM,  GTK_TYPE_FLAGS,  GTK_TYPE_BOXED,  GTK_TYPE_FOREIGN,  GTK_TYPE_CALLBACK,  GTK_TYPE_ARGS,  GTK_TYPE_POINTER,  /* sarebbe bello poter togliere alla fine i prossimi due */  GTK_TYPE_SIGNAL,  GTK_TYPE_C_CALLBACK,  GTK_TYPE_OBJECT} GtkFundamentalType;</PRE></CODE></BLOCKQUOTE><P><P><CODE>gtk_signal_new()</CODE> restituisce un identificatore unico intero per il segnale, che memorizziamo nel vettore  <CODE>tictactoe_signals</CODE>, cheindicizzeremo usando una enumerazione. (Convenzionalmente, gli elementi dell'enumerazionesono i nomi dei segnali, in maiuscolo, ma qui ci potrebbe essere un conflitto con la macro <CODE>TICTACTOE()</CODE>, quindi l'abbiamo chiamato  <CODE>TICTACTOE_SIGNAL</CODE><P>Dopo aver creato un nostro segnale, abbiamo bisogno di dire a GTKdi associare il nostro segnale alla classe Tictactoe. Lo facciamoinvocando <CODE>gtk_object_class_add_signals()</CODE>. Settiamo quindi a NULLil puntatore che punta al gestore predefinito per il segnale ``tictactoe'' a NULL, indicando che non ci sono azioni predefinite.<P><H3>La funzione <CODE>_init()</CODE></H3><P><P>Ogni classe di Widget necessita anche di una funzione per inizializzare la struttura dell'oggetto. Usualmente questa funzione ha il ruolo abbastanzalimitato di assegnare ai campi della struttura i valori predefiniti.Per widget composti, comunque, questa funzione crea, anche,i widget componenti del widget composto.<P><BLOCKQUOTE><CODE><PRE>static voidtictactoe_init (Tictactoe *ttt){  GtkWidget *table;  gint i,j;    table = gtk_table_new (3, 3, TRUE);  gtk_container_add (GTK_CONTAINER(ttt), table);  gtk_widget_show (table);  for (i=0;i&lt;3; i++)    for (j=0;j&lt;3; j++)      {        ttt->buttons[i][j] = gtk_toggle_button_new ();        gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j],                                    i, i+1, j, j+1);        gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",                            GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);        gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);        gtk_widget_show (ttt->buttons[i][j]);      }}</PRE></CODE></BLOCKQUOTE><P><H3>E il resto...</H3><P><P>C'&egrave; un'altra funzione che ogni widget (eccetto i Widget di base come GtkBin che non possono essere instanziati) deve avere : la funzioneche l'utente invoca per creare un oggetto di quel tipo. Questa &egrave; convenzionalmente chiamata <CODE>WIDGETNAME_new()</CODE>. In alcuni widget,non nel caso del nostro Tictactoe, questa funzione richiede degli argomenti, e fa alcune operazioni basandosi su di essi. Le altredue funzioni sono specifiche del widget Tictactoe.<P><P><CODE>tictactoe_clear()</CODE> &egrave; una funzione pubblica che resetta tutti i bottoni, nel widget, allo stato iniziale (non premuto). Notate l'uso di <CODE>gtk_signal_handler_block_by_data()</CODE> per impedire che il nostrogestore dei segnali venga attivato quando non ce n'&egrave; bisogno.<P><P><CODE>tictactoe_toggle()</CODE> &egrave; il gestore del segnale che viene invocato quando l'utente preme il bottone. Esso guarda se vi &egrave;qualche combinazione vincente che coinvolge i bottoni premuti, e nelcaso ci fosse, emette il segnale ``tictactoe''.<P><BLOCKQUOTE><CODE><PRE>  GtkWidget*tictactoe_new (){  return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));}void           tictactoe_clear (Tictactoe *ttt){  int i,j;  for (i=0;i&lt;3;i++)    for (j=0;j&lt;3;j++)      {        gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);        gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),                                     FALSE);        gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);      }}static voidtictactoe_toggle (GtkWidget *widget, Tictactoe *ttt){  int i,k;  static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },                             { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },                             { 0, 1, 2 }, { 0, 1, 2 } };  static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },                             { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },                             { 0, 1, 2 }, { 2, 1, 0 } };  int success, found;  for (k=0; k&lt;8; k++)    {      success = TRUE;      found = FALSE;      for (i=0;i&lt;3;i++)        {          success = success &amp;&amp;             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;          found = found ||            ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;        }            if (success &amp;&amp; found)        {          gtk_signal_emit (GTK_OBJECT (ttt),                            tictactoe_signals[TICTACTOE_SIGNAL]);          break;        }    }}</PRE></CODE></BLOCKQUOTE><P><P><P>E finalmente un programma di esempio che usa il nostro widgetTictactoe:<P><BLOCKQUOTE><CODE><PRE>#include &lt;gtk/gtk.h>#include "tictactoe.h"/* Invocato quando una riga, colonna o diagonale e' completata. */voidwin (GtkWidget *widget, gpointer data){  g_print ("Yay!\n");  tictactoe_clear (TICTACTOE (widget));}int main (int argc, char *argv[]){  GtkWidget *window;  GtkWidget *ttt;    gtk_init (&amp;argc, &amp;argv);  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);    gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");    gtk_signal_connect (GTK_OBJECT (window), "destroy",                      GTK_SIGNAL_FUNC (gtk_exit), NULL);    gtk_container_border_width (GTK_CONTAINER (window), 10);  /* Crea un nuovo widget Tictactoe. */  ttt = tictactoe_new ();  gtk_container_add (GTK_CONTAINER (window), ttt);  gtk_widget_show (ttt);  /* E gli aggancia il segnale "tictactoe" */  gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",                      GTK_SIGNAL_FUNC (win), NULL);  gtk_widget_show (window);    gtk_main ();    return 0;}</PRE></CODE></BLOCKQUOTE><P><H2><A NAME="ss19.4">19.4 Creare un widget a partire da zero</A></H2><H3>Introduzione</H3><P><P>In questa sezione impareremo meglio come i widget si mostrano sullo schermoe interagiscono con gli eventi. Come esempio, creeremoun widget di quadrante analogico con un puntatore che l'utente pu&ograve; trascinare per assegnare il valore.<P><H3>Mostrare un widget sullo schermo</H3><P>Ci sono alcuni passi che sono necessari nella visualizzazione sulloschermo. Dopo che il widget &egrave; stato creato con una chiamata a <CODE>WIDGETNAME_new()</CODE>, sono necessarie alcune altre funzioni:<P><UL><LI> <CODE>WIDGETNAME_realize()</CODE> &egrave; responsabile della creazione di una finestra X per il widget se ne ha una.</LI><LI> <CODE>WIDGETNAME_map()</CODE> &egrave; invocata dopo che l'utente ha chiamato <CODE>gtk_widget_show()</CODE>. E' responsabile di vedere se ilwidget &egrave; attualmente disegnato sullo schermo (<EM>mappato</EM>). Per una classe contenitore, essa deve anche creare chiamate alle funzioni  <CODE>map()</CODE>> per ogni widget figlio.</LI><LI> <CODE>WIDGETNAME_draw()</CODE> &egrave; invocata quando <CODE>gtk_widget_draw()</CODE> viene chiamata per il widget o per uno dei suoipredecessori. Esso fa s&igrave; che l'attuale chiamata allafunzione di disegno del widget disegni il widget sullo schermo.Per la classe contenitore, questa funzione deve eseguire lechiamate alla funzioni <CODE>gtk_widget_draw()</CODE> di ogni suo widgetfiglio.</LI><LI> <CODE>WIDGETNAME_expose()</CODE> &egrave; un gestore per l'evento di esposizioneper il widget. Esso crea le chiamate necessarie alle funzioni di disegnoper disegnare la porzione che si &egrave; resa visibile. Per le classi contenitore, questa funzione deve generare gli eventi di ``expose'' per tutti i widget figli che non hanno una propria finestra (se essi hannouna loro finestra, sar&agrave; X che generer&agrave; i necessari eventi di expose).</LI></UL><P><P>Potete notare che le ultime due funzioni sono molto simili, ognuna &egrave;responsabile per il disegno del widget sullo schermo. Infatti moltitipi di widget non sanno relamente la differenza tra le due.La funzione di predefinita <CODE>draw()</CODE> nella classe widget, semplicementegenera un sintetico evento di ``expose'' per l'area da ridisegnare.Comunque, alcuni tipi di widget possono risparmiare tempo distinguendole due funzioni. Per esempio, se un widget ha piu' finestre X, allora visto che l'evento ``expose'' identifica solo la finestra esposta, esso pu&ograve; ridisegnare solo la finestra interessata, cosa che non &egrave; possibile per chiamate a <CODE>draw()</CODE>.<P><P>I widget contenitori, anche se essi non farebbero differenze,non possono semplicemente usare la funzione <CODE>draw()</CODE> perch&egrave; per i loro widget figli la differenza potrebbere essere importante. Comunque, sarebbe uno spreco duplicare il codice di disegno nelle duefunzioni. La convenzione &egrave; che questi widget abbiano una funzionechiamata <CODE>WIDGETNAME_paint()</CODE> che disegna il widget, che &egrave; poichiamata dalle funzioni <CODE>draw()</CODE> e <CODE>expose()</CODE><P><P>Nell'approccio del nostro esempio, visto che il widget, ha una sola finestra, possiamo utilizzare il modo piu' sempliceed usare la funzione predefinita <CODE>draw()</CODE> e implementaresolamente la funzione <CODE>expose()</CODE>.<P><H3>Le origini del widget Dial</H3><P>Come tutti gli animali terresti sono semplicemente varianti del primoamfibio, i widget Gtk tendono ad essere varianti di altri widget, precedentementescritti. Cos&igrave;, anche se questa sezione &egrave; intitolata ``Creareun widget a partire da zero", il nostro widget inizia in realt&agrave; con il codice sorgente del widget Range. Questo &egrave; stato preso come punto d'inizioperche' sarebbe carino se il nostro widget avesse lastessa interfaccia del widget Scale il quale &egrave; semplicemente unaspecializzazione del widget Range. Cos&igrave;, sebbene  il codice sorgente e' presentato sotto in forma definitiva, non si deve pensare che sia statoscritto <EM>deus ex machina</EM> in questo modo. Se poi non avete familiarit&agrave;con il funzionamento del widget Scale dal punto di vista di chi scriveun'applicazione, potrebbe essere una buona idea guardare indietro prima di continuare.<P><H3>Le basi</H3><P>Una parte del nostro widget potrebbe essere simileal widget Tictactoe. In primo luogo, abbiamo il file header:<P><BLOCKQUOTE><CODE><PRE>/* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#ifndef __GTK_DIAL_H__#define __GTK_DIAL_H__#include &lt;gdk/gdk.h>#include &lt;gtk/gtkadjustment.h>#include &lt;gtk/gtkwidget.h>#ifdef __cplusplusextern "C" {#endif /* __cplusplus */#define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)#define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)#define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())typedef struct _GtkDial        GtkDial;typedef struct _GtkDialClass   GtkDialClass;struct _GtkDial{  GtkWidget widget;  /* Politica di update (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */  guint policy : 2;  /* Bottone correntemente premuto o 0 altrimenti */  guint8 button;  /* Dimensione della componente Dial. */  gint radius;  gint pointer_width;  /* ID del timer di update, o 0 altrimenti */  guint32 timer;  /* Angolo corrente. */  gfloat angle;  /* Vecchi valori dell'aggiustamento cos&igrave; sappiamo quando    * qualcosa cambia */  gfloat old_value;  gfloat old_lower;  gfloat old_upper;  /* L'oggetto adjustament che memorizza i dati per questo dial */  GtkAdjustment *adjustment;};struct _GtkDialClass{  GtkWidgetClass parent_class;};GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -