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

📄 gtk_tut_it-19.html

📁 gtk是linux一款强大的夸平台的图形化开发工具
💻 HTML
📖 第 1 页 / 共 4 页
字号:
  /* Draw pointer */  s = sin(dial->angle);  c = cos(dial->angle);  points[0].x = xc + s*dial->pointer_width/2;  points[0].y = yc + c*dial->pointer_width/2;  points[1].x = xc + c*dial->radius;  points[1].y = yc - s*dial->radius;  points[2].x = xc - s*dial->pointer_width/2;  points[2].y = yc - c*dial->pointer_width/2;  gtk_draw_polygon (widget->style,                    widget->window,                    GTK_STATE_NORMAL,                    GTK_SHADOW_OUT,                    points, 3,                    TRUE);    return FALSE;}</PRE></CODE></BLOCKQUOTE><P><H3>Gestione degli eventi</H3><P><P>Il resto del codice del widget manipola vari tipi di eventi, e non&egrave; differente da quello che pu&ograve; essere trovato in molte applicazioneGTK. Due tipi di eventi possono verificarsi: l'utente pu&ograve; clickare sul widget con il mouse e trascinare per muovere il puntatore, o il valore dell'oggetto Adjustmente pu&ograve; cambiare a causa di alcunecircostanze esterne.<P><P>Quando l'utente clicka sul widget, noi vediamo se la pressioneera veramente vicina al puntatore, e se cos&igrave;, memorizziamo il bottonepremuto dall'utente con il campo <CODE>button</CODE> della struttura delwidget, e prendiamo tutti gli eventi del mouse con una chiamata allafunzione <CODE>gtk_grab_add()</CODE>. Successivi movimenti del mouse causano il ricalcolo dei valori di controllo (fatto dalla funzione <CODE>gtk_dial_update_mouse</CODE>). Dipendentemente dalla politica che abbiamostabilito, gli eventi ``value_changed'' possono essere  generatiistantaneamente (<CODE>GTK_UPDATE_CONTINUOUS</CODE>), dopo un certo tempo aggiuntocon la funzione <CODE>gtk_timeout_add()</CODE> (<CODE>GTK_UPDATE_DELAYED</CODE>), osolamente quando il bottone del mouse e' rilasciato (<CODE>GTK_UPDATE_DISCONTINUOUS</CODE>).<P><BLOCKQUOTE><CODE><PRE>static gintgtk_dial_button_press (GtkWidget      *widget,                       GdkEventButton *event){  GtkDial *dial;  gint dx, dy;  double s, c;  double d_parallel;  double d_perpendicular;  g_return_val_if_fail (widget != NULL, FALSE);  g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);  g_return_val_if_fail (event != NULL, FALSE);  dial = GTK_DIAL (widget);  /* Determina se il bottone premuto era dentro la regione del puntatore:     lo facciamo calcolando la distanza parallela e      perpendicolare dal punto dove il bottone del mouse e' stato premuto     alla linea passante per il puntatore. */    dx = event->x - widget->allocation.width / 2;  dy = widget->allocation.height / 2 - event->y;    s = sin(dial->angle);  c = cos(dial->angle);    d_parallel = s*dy + c*dx;  d_perpendicular = fabs(s*dx - c*dy);    if (!dial->button &amp;&amp;      (d_perpendicular &lt; dial->pointer_width/2) &amp;&amp;      (d_parallel > - dial->pointer_width))    {      gtk_grab_add (widget);      dial->button = event->button;      gtk_dial_update_mouse (dial, event->x, event->y);    }  return FALSE;}static gintgtk_dial_button_release (GtkWidget      *widget,                          GdkEventButton *event){  GtkDial *dial;  g_return_val_if_fail (widget != NULL, FALSE);  g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);  g_return_val_if_fail (event != NULL, FALSE);  dial = GTK_DIAL (widget);  if (dial->button == event->button)    {      gtk_grab_remove (widget);      dial->button = 0;      if (dial->policy == GTK_UPDATE_DELAYED)        gtk_timeout_remove (dial->timer);            if ((dial->policy != GTK_UPDATE_CONTINUOUS) &amp;&amp;          (dial->old_value != dial->adjustment->value))        gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");    }  return FALSE;}static gintgtk_dial_motion_notify (GtkWidget      *widget,                         GdkEventMotion *event){  GtkDial *dial;  GdkModifierType mods;  gint x, y, mask;  g_return_val_if_fail (widget != NULL, FALSE);  g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);  g_return_val_if_fail (event != NULL, FALSE);  dial = GTK_DIAL (widget);  if (dial->button != 0)    {      x = event->x;      y = event->y;      if (event->is_hint || (event->window != widget->window))        gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);      switch (dial->button)        {        case 1:          mask = GDK_BUTTON1_MASK;          break;        case 2:          mask = GDK_BUTTON2_MASK;          break;        case 3:          mask = GDK_BUTTON3_MASK;          break;        default:          mask = 0;          break;        }      if (mods &amp; mask)        gtk_dial_update_mouse (dial, x,y);    }  return FALSE;}static gintgtk_dial_timer (GtkDial *dial){  g_return_val_if_fail (dial != NULL, FALSE);  g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);  if (dial->policy == GTK_UPDATE_DELAYED)    gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");  return FALSE;}static voidgtk_dial_update_mouse (GtkDial *dial, gint x, gint y){  gint xc, yc;  gfloat old_value;  g_return_if_fail (dial != NULL);  g_return_if_fail (GTK_IS_DIAL (dial));  xc = GTK_WIDGET(dial)->allocation.width / 2;  yc = GTK_WIDGET(dial)->allocation.height / 2;  old_value = dial->adjustment->value;  dial->angle = atan2(yc-y, x-xc);  if (dial->angle &lt; -M_PI/2.)    dial->angle += 2*M_PI;  if (dial->angle &lt; -M_PI/6)    dial->angle = -M_PI/6;  if (dial->angle > 7.*M_PI/6.)    dial->angle = 7.*M_PI/6.;  dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *    (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);  if (dial->adjustment->value != old_value)    {      if (dial->policy == GTK_UPDATE_CONTINUOUS)        {          gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");        }      else        {          gtk_widget_draw (GTK_WIDGET(dial), NULL);          if (dial->policy == GTK_UPDATE_DELAYED)            {              if (dial->timer)                gtk_timeout_remove (dial->timer);              dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,                                             (GtkFunction) gtk_dial_timer,                                             (gpointer) dial);            }        }    }}</PRE></CODE></BLOCKQUOTE><P><P>Cambiamenti esterni all'Adjustment sono comunicati al nostro widgetdai segnali ``changed'' e ``value_changed''. Il gestore per queste funzioni chiama  <CODE>gtk_dial_update()</CODE> per validare gliargomenti, calcolare il nuovo angolo del puntatore e ridisegnare ilwidget (chiamando <CODE>gtk_widget_draw()</CODE>).<P><BLOCKQUOTE><CODE><PRE>static voidgtk_dial_update (GtkDial *dial){  gfloat new_value;    g_return_if_fail (dial != NULL);  g_return_if_fail (GTK_IS_DIAL (dial));  new_value = dial->adjustment->value;    if (new_value &lt; dial->adjustment->lower)    new_value = dial->adjustment->lower;  if (new_value > dial->adjustment->upper)    new_value = dial->adjustment->upper;  if (new_value != dial->adjustment->value)    {      dial->adjustment->value = new_value;      gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");    }  dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /    (dial->adjustment->upper - dial->adjustment->lower);  gtk_widget_draw (GTK_WIDGET(dial), NULL);}static voidgtk_dial_adjustment_changed (GtkAdjustment *adjustment,                              gpointer       data){  GtkDial *dial;  g_return_if_fail (adjustment != NULL);  g_return_if_fail (data != NULL);  dial = GTK_DIAL (data);  if ((dial->old_value != adjustment->value) ||      (dial->old_lower != adjustment->lower) ||      (dial->old_upper != adjustment->upper))    {      gtk_dial_update (dial);      dial->old_value = adjustment->value;      dial->old_lower = adjustment->lower;      dial->old_upper = adjustment->upper;    }}static voidgtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,                                    gpointer       data){  GtkDial *dial;  g_return_if_fail (adjustment != NULL);  g_return_if_fail (data != NULL);  dial = GTK_DIAL (data);  if (dial->old_value != adjustment->value)    {      gtk_dial_update (dial);      dial->old_value = adjustment->value;    }}</PRE></CODE></BLOCKQUOTE><P><H3>Possibili Miglioramenti</H3><P><P>Il widget Dial, da come l'abbiamo costruito, &egrave; lungo circa 670 lineedi codice C. Anche se questo potrebbe sembrare un po' troppo, abbiamorealmente fatto un bel po' con quel tanto di codice, specialmente considerando che molta della lunghezza &egrave; costituita da file header ecommmenti. Comunque ci sono alcuni miglioramenti che potrebbero esserefatti a questo widget:<P><UL><LI> Se tu provate questo widget, troverete che ci sono alcuni lampeggiamentiquando il puntatore viene trascinato in giro. Questo perch&egrave; l'intero widget &egrave; cancellato ogni volta che il puntatore viene mosso, prima di essere ridisegnato. Spesso, il modo miglioreper gestire questo tipo di problema &egrave; il disegnare il tutto su una pixmap non visibile, poi copiare il risultato finale sullo schermo in una passata sola (il widget ProgressBar viene disegnato in questomodo).</LI><LI> L'utente potrebbe essere abilitato ad usare le frecce su e giu perincrementare e diminuire il valore.</LI><LI> Potrebbe essere carino se il widget avesse i bottoni per incrementare e decrementare il valore di step. Anche se potrebbe esserepossibile usare dei widget Bottone incorporati per questo, possiamo anchefar s&igrave; che il bottone sia auto-ripentente quando premuto, come le freccein una barra di scorrimento. Molto del codice per implementare questo tipo di comportamento pu&ograve; essere trovato nel widget GtkRange.</LI><LI> il widget Dial potrebbe essere fatto/creato dentro un widget contenitore con un singolo widget figlio posizionato all'inizio tra i 2 bottoni menzionati prima. L'utente potrebbe poi aggiungere o una etichettao un widget ``entry'' per mostrare il valore corrente del dial.</LI></UL><P><H2><A NAME="ss19.5">19.5 Impararne di pi&ugrave;</A></H2><P> Fin qui abbiamo esposto solo una piccola parte di tutto quello che serveper creare un widget. Se volete davvero  scrivere un vostro widget, lamiglior risorsa di esempi &egrave; lo stesso codice sorgente GTK. Chiedete a voistessi alcune cose su come deve essere il widget che volete scrivere: &egrave;un widget contenitore? dovr&agrave; avere una propria finestra? &egrave; una modifica di un widget precedente? Trovate poi un widget simile e iniziate a fargli delle modifiche.Buone Fortuna.<P><HR NOSHADE><A HREF="gtk_tut_it-20.html">Avanti</A><A HREF="gtk_tut_it-18.html">Indietro</A><A HREF="gtk_tut_it.html#toc19">Indice</A></BODY></HTML>

⌨️ 快捷键说明

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