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

📄 gtk_tut-20.html

📁 gtk 开发手册和参考文档。 包括gtk glib gdk等
💻 HTML
📖 第 1 页 / 共 3 页
字号:
  attributes.event_mask = gtk_widget_get_events (widget) |     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |    GDK_POINTER_MOTION_HINT_MASK;  attributes.visual = gtk_widget_get_visual (widget);  attributes.colormap = gtk_widget_get_colormap (widget);  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;  widget-&gt;window = gdk_window_new (widget-&gt;parent-&gt;window, &amp;attributes, attributes_mask);  widget-&gt;style = gtk_style_attach (widget-&gt;style, widget-&gt;window);  gdk_window_set_user_data (widget-&gt;window, widget);  gtk_style_set_background (widget-&gt;style, widget-&gt;window, GTK_STATE_ACTIVE);}</PRE></CODE></BLOCKQUOTE><P><H3>大小的设定</H3><P>在所有视窗被显示出来之前, GTK会先问每个子物件的大小.该事件是由<CODE>gtk_dial_size_request()</CODE>所处理的. 既然我们的物件不是container物件, 而且没什麽大小约束,就用个合理的数字就行了.<P><BLOCKQUOTE><CODE><PRE>static void gtk_dial_size_request (GtkWidget      *widget,                       GtkRequisition *requisition){  requisition-&gt;width = DIAL_DEFAULT_SIZE;  requisition-&gt;height = DIAL_DEFAULT_SIZE;}</PRE></CODE></BLOCKQUOTE><P><P>最後所有物件都有理想的大小.一般会尽可能用原定大小,但使用者会改变它的大小.大小的改变是由<CODE>gtk_dial_size_allocate()</CODE>. <P><BLOCKQUOTE><CODE><PRE>static voidgtk_dial_size_allocate (GtkWidget     *widget,                        GtkAllocation *allocation){  GtkDial *dial;  g_return_if_fail (widget != NULL);  g_return_if_fail (GTK_IS_DIAL (widget));  g_return_if_fail (allocation != NULL);  widget-&gt;allocation = *allocation;  if (GTK_WIDGET_REALIZED (widget))    {      dial = GTK_DIAL (widget);      gdk_window_move_resize (widget-&gt;window,                              allocation-&gt;x, allocation-&gt;y,                              allocation-&gt;width, allocation-&gt;height);      dial-&gt;radius = MAX(allocation-&gt;width,allocation-&gt;height) * 0.45;      dial-&gt;pointer_width = dial-&gt;radius / 5;    }}</PRE></CODE></BLOCKQUOTE>.<P><H3><CODE>gtk_dial_expose()</CODE></H3><P>就如之前所提到的一样,所有物件的绘出都是由expose事件来处理.没什麽可多提的, 除了用<CODE>gtk_draw_polygon</CODE> 来画出三维阴影.<P><BLOCKQUOTE><CODE><PRE>static gintgtk_dial_expose (GtkWidget      *widget,                 GdkEventExpose *event){  GtkDial *dial;  GdkPoint points[3];  gdouble s,c;  gdouble theta;  gint xc, yc;  gint tick_length;  gint i;  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);  if (event-&gt;count &gt; 0)    return FALSE;    dial = GTK_DIAL (widget);  gdk_window_clear_area (widget-&gt;window,                         0, 0,                         widget-&gt;allocation.width,                         widget-&gt;allocation.height);  xc = widget-&gt;allocation.width/2;  yc = widget-&gt;allocation.height/2;  /* Draw ticks */  for (i=0; i&lt;25; i++)    {      theta = (i*M_PI/18. - M_PI/6.);      s = sin(theta);      c = cos(theta);      tick_length = (i%6 == 0) ? dial-&gt;pointer_width : dial-&gt;pointer_width/2;            gdk_draw_line (widget-&gt;window,                     widget-&gt;style-&gt;fg_gc[widget-&gt;state],                     xc + c*(dial-&gt;radius - tick_length),                     yc - s*(dial-&gt;radius - tick_length),                     xc + c*dial-&gt;radius,                     yc - s*dial-&gt;radius);    }  /* Draw pointer */  s = sin(dial-&gt;angle);  c = cos(dial-&gt;angle);  points[0].x = xc + s*dial-&gt;pointer_width/2;  points[0].y = yc + c*dial-&gt;pointer_width/2;  points[1].x = xc + c*dial-&gt;radius;  points[1].y = yc - s*dial-&gt;radius;  points[2].x = xc - s*dial-&gt;pointer_width/2;  points[2].y = yc - c*dial-&gt;pointer_width/2;  gtk_draw_polygon (widget-&gt;style,                    widget-&gt;window,                    GTK_STATE_NORMAL,                    GTK_SHADOW_OUT,                    points, 3,                    TRUE);    return FALSE;}</PRE></CODE></BLOCKQUOTE><P><H3>事件处理</H3><P><P>最後一段程式处理各种事件,跟我们之前所做的没有什麽太大的不同.有两种事件会发生, 使用者滑鼠的动作及其它因素所造成的物件参数调整. <P><P>当使用者在物件上按钮时, 我们检查是否靠近我们的指标,如果是, 将资料存到<CODE>button</CODE>一栏,并用<CODE>gtk_grab_add()</CODE>将所有滑鼠事件抓住. 接下来的滑鼠的动作将会被<CODE>gtk_dial_update_mouse</CODE>所接管.. 接下来就看我们是如何做的,"value_changed"事件可以用(<CODE>GTK_UPDATE_CONTINUOUS</CODE>)来产生, 或用<CODE>gtk_timeout_add()</CODE>来延迟一下(<CODE>GTK_UPDATE_DELAYED</CODE>), 或仅在按钮按下时反应(<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);  /* Determine if button press was within pointer region - we      do this by computing the parallel and perpendicular distance of     the point where the mouse was pressed from the line passing through     the pointer */    dx = event-&gt;x - widget-&gt;allocation.width / 2;  dy = widget-&gt;allocation.height / 2 - event-&gt;y;    s = sin(dial-&gt;angle);  c = cos(dial-&gt;angle);    d_parallel = s*dy + c*dx;  d_perpendicular = fabs(s*dx - c*dy);    if (!dial-&gt;button &&      (d_perpendicular &lt; dial-&gt;pointer_width/2) &&      (d_parallel &gt; - dial-&gt;pointer_width))    {      gtk_grab_add (widget);      dial-&gt;button = event-&gt;button;      gtk_dial_update_mouse (dial, event-&gt;x, event-&gt;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-&gt;button == event-&gt;button)    {      gtk_grab_remove (widget);      dial-&gt;button = 0;      if (dial-&gt;policy == GTK_UPDATE_DELAYED)        gtk_timeout_remove (dial-&gt;timer);            if ((dial-&gt;policy != GTK_UPDATE_CONTINUOUS) &&          (dial-&gt;old_value != dial-&gt;adjustment-&gt;value))        gtk_signal_emit_by_name (GTK_OBJECT (dial-&gt;adjustment), &quot;value_changed&quot;);    }  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-&gt;button != 0)    {      x = event-&gt;x;      y = event-&gt;y;      if (event-&gt;is_hint || (event-&gt;window != widget-&gt;window))        gdk_window_get_pointer (widget-&gt;window, &amp;x, &amp;y, &amp;mods);      switch (dial-&gt;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 & 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-&gt;policy == GTK_UPDATE_DELAYED)    gtk_signal_emit_by_name (GTK_OBJECT (dial-&gt;adjustment), &quot;value_changed&quot;);  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)-&gt;allocation.width / 2;  yc = GTK_WIDGET(dial)-&gt;allocation.height / 2;  old_value = dial-&gt;adjustment-&gt;value;  dial-&gt;angle = atan2(yc-y, x-xc);  if (dial-&gt;angle &lt; -M_PI/2.)    dial-&gt;angle += 2*M_PI;  if (dial-&gt;angle &lt; -M_PI/6)    dial-&gt;angle = -M_PI/6;  if (dial-&gt;angle &gt; 7.*M_PI/6.)    dial-&gt;angle = 7.*M_PI/6.;  dial-&gt;adjustment-&gt;value = dial-&gt;adjustment-&gt;lower + (7.*M_PI/6 - dial-&gt;angle) *    (dial-&gt;adjustment-&gt;upper - dial-&gt;adjustment-&gt;lower) / (4.*M_PI/3.);  if (dial-&gt;adjustment-&gt;value != old_value)    {      if (dial-&gt;policy == GTK_UPDATE_CONTINUOUS)        {          gtk_signal_emit_by_name (GTK_OBJECT (dial-&gt;adjustment), &quot;value_changed&quot;);        }      else        {          gtk_widget_draw (GTK_WIDGET(dial), NULL);          if (dial-&gt;policy == GTK_UPDATE_DELAYED)            {              if (dial-&gt;timer)                gtk_timeout_remove (dial-&gt;timer);              dial-&gt;timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,                                             (GtkFunction) gtk_dial_timer,                                             (gpointer) dial);            }        }    }}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-&gt;adjustment-&gt;value;    if (new_value &lt; dial-&gt;adjustment-&gt;lower)    new_value = dial-&gt;adjustment-&gt;lower;  if (new_value &gt; dial-&gt;adjustment-&gt;upper)    new_value = dial-&gt;adjustment-&gt;upper;  if (new_value != dial-&gt;adjustment-&gt;value)    {      dial-&gt;adjustment-&gt;value = new_value;      gtk_signal_emit_by_name (GTK_OBJECT (dial-&gt;adjustment), &quot;value_changed&quot;);    }  dial-&gt;angle = 7.*M_PI/6. - (new_value - dial-&gt;adjustment-&gt;lower) * 4.*M_PI/3. /    (dial-&gt;adjustment-&gt;upper - dial-&gt;adjustment-&gt;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-&gt;old_value != adjustment-&gt;value) ||      (dial-&gt;old_lower != adjustment-&gt;lower) ||      (dial-&gt;old_upper != adjustment-&gt;upper))    {      gtk_dial_update (dial);      dial-&gt;old_value = adjustment-&gt;value;      dial-&gt;old_lower = adjustment-&gt;lower;      dial-&gt;old_upper = adjustment-&gt;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-&gt;old_value != adjustment-&gt;value)    {      gtk_dial_update (dial);      dial-&gt;old_value = adjustment-&gt;value;    }}</PRE></CODE></BLOCKQUOTE><P><H3>有可能的增强之处</H3><P><P>这个Dial物件到目前为止有670行.这看起来好像有不少了,不过我们真正完成的只有一点点,因为大部份都是标头及模子.还是有许多可以加强的地方:<P><UL><LI> 如果您试过这个物件,您会发现滑鼠指标会一闪一闪的.这是因为整个物件每次都重画一次.当然了最好的方式是在offscreen pixmap上画完以後,然後整个复制到萤幕上.</LI><LI> 使用者应该可以用up及down按键来增加或减少其值.</LI><LI> 如果有个按钮来增加或减少其值, 那是再好不过的了.虽然可也以用embedded Button widgets来做,但我们会想要按钮有auto-repeat的功能.所有要做这一类功能的程式可以在GtkRange物件中发现.</LI><LI> 这个Dial物件可再做进一个container物件, 带有一个子物件, 位於按钮与最下面之间.使用者可以增加一个标签或整个物件来显示目前的值.</LI></UL><P><H2><A NAME="ss20.5">20.5 更多一点</A></H2><P>关於产生一个新的物件的细部资讯在以上被提供出来.如果您想要写一个属於自己的物件, 我想最好的范例就是GTK本身了.<P>问问您自己一些关於您想要写的物件:<PRE>它是否是个Container物件?它是否有自己的视窗?是否是个现有物件的修改?找出一个相近的物件, 然後开始动工.</PRE>祝好运!<P><H2><A NAME="ss20.6">20.6 版权</A></H2><P>This section on of the tutorial on writing widgets is Copyright (C) 1997 Owen Taylor<P>This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of the License, or (at your option) any later version.<P>This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.<P>You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.<P><HR><A HREF="gtk_tut-19.html" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/gtk_tut-19.html"><IMG SRC="prev.gif" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/prev.gif" ALT="Previous"></A><A HREF="gtk_tut-21.html" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/gtk_tut-21.html"><IMG SRC="next.gif" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/next.gif" ALT="Next"></A><A HREF="gtk_tut.html#toc20" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/gtk_tut.html#toc20"><IMG SRC="toc.gif" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/toc.gif" ALT="Contents"></A></BODY></HTML>

⌨️ 快捷键说明

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