Blob Blame History Raw
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML
><HEAD
><TITLE
>Progress Bars</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK
REL="HOME"
TITLE="GTK+ 2.0 Tutorial"
HREF="book1.html"><LINK
REL="UP"
TITLE="Miscellaneous Widgets"
HREF="c753.html"><LINK
REL="PREVIOUS"
TITLE="The Tooltips Object"
HREF="x810.html"><LINK
REL="NEXT"
TITLE="Dialogs"
HREF="x861.html"></HEAD
><BODY
CLASS="SECT1"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>GTK+ 2.0 Tutorial</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="x810.html"
ACCESSKEY="P"
>&#60;&#60;&#60; Previous</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
>Miscellaneous Widgets</TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="x861.html"
ACCESSKEY="N"
>Next &#62;&#62;&#62;</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="SECT1"
><H1
CLASS="SECT1"
><A
NAME="SEC-PROGRESSBARS"
>Progress Bars</A
></H1
><P
>Progress bars are used to show the status of an operation. They are
pretty easy to use, as you will see with the code below. But first
lets start out with the calls to create a new progress bar.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>GtkWidget *gtk_progress_bar_new( void );</PRE
></TD
></TR
></TABLE
><P
>Now that the progress bar has been created we can use it.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>void gtk_progress_bar_set_fraction ( GtkProgressBar *pbar,
                                     gdouble        fraction );</PRE
></TD
></TR
></TABLE
><P
>The first argument is the progress bar you wish to operate on, and the
second argument is the amount "completed", meaning the amount the
progress bar has been filled from 0-100%. This is passed to the
function as a real number ranging from 0 to 1.</P
><P
>GTK v1.2 has added new functionality to the progress bar that enables
it to display its value in different ways, and to inform the user of
its current value and its range.</P
><P
>A progress bar may be set to one of a number of orientations using the
function</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>void gtk_progress_bar_set_orientation( GtkProgressBar *pbar,
                                       GtkProgressBarOrientation orientation );</PRE
></TD
></TR
></TABLE
><P
>The <TT
CLASS="LITERAL"
>orientation</TT
> argument may take one of the following
values to indicate the direction in which the progress bar moves:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>  GTK_PROGRESS_LEFT_TO_RIGHT
  GTK_PROGRESS_RIGHT_TO_LEFT
  GTK_PROGRESS_BOTTOM_TO_TOP
  GTK_PROGRESS_TOP_TO_BOTTOM</PRE
></TD
></TR
></TABLE
><P
>As well as indicating the amount of progress that has occured, the
progress bar may be set to just indicate that there is some activity. 
This can be useful in situations where progress cannot be measured against 
a value range. The following function indicates that some progress has been 
made.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>void gtk_progress_bar_pulse ( GtkProgressBar *progress );</PRE
></TD
></TR
></TABLE
><P
>The step size of the activity indicator is set using the following 
function.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>void gtk_progress_bar_set_pulse_step( GtkProgressBar *pbar,
                                      gdouble         fraction );</PRE
></TD
></TR
></TABLE
><P
>When not in activity mode, the progress bar can also display a
configurable text string within its trough, using the following
function.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>void gtk_progress_bar_set_text( GtkProgressBar *progress,
                                const gchar    *text );</PRE
></TD
></TR
></TABLE
><DIV
CLASS="NOTE"
><P
></P
><TABLE
CLASS="NOTE"
WIDTH="100%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="./stylesheet-images/note.gif"
HSPACE="5"
ALT="Note"></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
>Note that gtk_progress_set_text() doesn't support the printf()-like formatting
of the GTK+ 1.2 Progressbar.</P
></TD
></TR
></TABLE
></DIV
><P
>You can turn off the display of the string by calling gtk_progess_bar_set_text()
again with NULL as second argument.</P
><P
>The current text setting of a progressbar can be retrieved with the 
following function. Do not free the returned string.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>const gchar *gtk_progress_bar_get_text( GtkProgressBar *pbar );</PRE
></TD
></TR
></TABLE
><P
>Progress Bars are usually used with timeouts or other such functions
(see section on <A
HREF="c1759.html"
>Timeouts, I/O and Idle Functions</A
>) 
to give the illusion of multitasking. All will employ the
gtk_progress_bar_set_fraction() or gtk_progress_bar_pulse() functions in the 
same manner.</P
><P
>Here is an example of the progress bar, updated using timeouts. This
code also shows you how to reset the Progress Bar.</P
><P
><SPAN
CLASS="INLINEMEDIAOBJECT"
><IMG
SRC="images/progressbar.png"></SPAN
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>&#13;#include &#60;gtk/gtk.h&#62;

typedef struct _ProgressData {
  GtkWidget *window;
  GtkWidget *pbar;
  int timer;
  gboolean activity_mode;
} ProgressData;

/* Update the value of the progress bar so that we get
 * some movement */
static gboolean progress_timeout( gpointer data )
{
  ProgressData *pdata = (ProgressData *)data;
  gdouble new_val;
  
  if (pdata-&#62;activity_mode) 
    gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata-&#62;pbar));
  else 
    {
      /* Calculate the value of the progress bar using the
       * value range set in the adjustment object */
      
      new_val = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pdata-&#62;pbar)) + 0.01;
      
      if (new_val &#62; 1.0)
	new_val = 0.0;
      
      /* Set the new value */
      gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata-&#62;pbar), new_val);
    }
  
  /* As this is a timeout function, return TRUE so that it
   * continues to get called */
  return TRUE;
} 

/* Callback that toggles the text display within the progress bar trough */
static void toggle_show_text( GtkWidget    *widget,
                              ProgressData *pdata )
{
  const gchar *text;
  
  text = gtk_progress_bar_get_text (GTK_PROGRESS_BAR (pdata-&#62;pbar));
  if (text &#38;&#38; *text)
    gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata-&#62;pbar), "");
  else 
    gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata-&#62;pbar), "some text");
}

/* Callback that toggles the activity mode of the progress bar */
static void toggle_activity_mode( GtkWidget    *widget,
                                  ProgressData *pdata )
{
  pdata-&#62;activity_mode = !pdata-&#62;activity_mode;
  if (pdata-&#62;activity_mode) 
      gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata-&#62;pbar));
  else
      gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata-&#62;pbar), 0.0);
}

 
/* Callback that toggles the orientation of the progress bar */
static void toggle_orientation( GtkWidget    *widget,
                                ProgressData *pdata )
{
  switch (gtk_progress_bar_get_orientation (GTK_PROGRESS_BAR (pdata-&#62;pbar))) {
  case GTK_PROGRESS_LEFT_TO_RIGHT:
    gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata-&#62;pbar), 
				      GTK_PROGRESS_RIGHT_TO_LEFT);
    break;
  case GTK_PROGRESS_RIGHT_TO_LEFT:
    gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata-&#62;pbar), 
				      GTK_PROGRESS_LEFT_TO_RIGHT);
    break;
  default:;
    /* do nothing */
  }
}

 
/* Clean up allocated memory and remove the timer */
static void destroy_progress( GtkWidget    *widget,
                              ProgressData *pdata)
{
    g_source_remove (pdata-&#62;timer);
    pdata-&#62;timer = 0;
    pdata-&#62;window = NULL;
    g_free (pdata);
    gtk_main_quit ();
}

int main( int   argc,
          char *argv[])
{
    ProgressData *pdata;
    GtkWidget *align;
    GtkWidget *separator;
    GtkWidget *table;
    GtkWidget *button;
    GtkWidget *check;
    GtkWidget *vbox;

    gtk_init (&#38;argc, &#38;argv);

    /* Allocate memory for the data that is passed to the callbacks */
    pdata = g_malloc (sizeof (ProgressData));
  
    pdata-&#62;window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_resizable (GTK_WINDOW (pdata-&#62;window), TRUE);

    g_signal_connect (pdata-&#62;window, "destroy",
	              G_CALLBACK (destroy_progress),
                      (gpointer) pdata);
    gtk_window_set_title (GTK_WINDOW (pdata-&#62;window), "GtkProgressBar");
    gtk_container_set_border_width (GTK_CONTAINER (pdata-&#62;window), 0);

    vbox = gtk_vbox_new (FALSE, 5);
    gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
    gtk_container_add (GTK_CONTAINER (pdata-&#62;window), vbox);
    gtk_widget_show (vbox);
  
    /* Create a centering alignment object */
    align = gtk_alignment_new (0.5, 0.5, 0, 0);
    gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 5);
    gtk_widget_show (align);

    /* Create the GtkProgressBar */
    pdata-&#62;pbar = gtk_progress_bar_new ();
    pdata-&#62;activity_mode = FALSE;

    gtk_container_add (GTK_CONTAINER (align), pdata-&#62;pbar);
    gtk_widget_show (pdata-&#62;pbar);

    /* Add a timer callback to update the value of the progress bar */
    pdata-&#62;timer = g_timeout_add (100, progress_timeout, pdata);

    separator = gtk_hseparator_new ();
    gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
    gtk_widget_show (separator);

    /* rows, columns, homogeneous */
    table = gtk_table_new (2, 3, FALSE);
    gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
    gtk_widget_show (table);

    /* Add a check button to select displaying of the trough text */
    check = gtk_check_button_new_with_label ("Show text");
    gtk_table_attach (GTK_TABLE (table), check, 0, 1, 0, 1,
                      GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
		      5, 5);
    g_signal_connect (check, "clicked",
                      G_CALLBACK (toggle_show_text),
                      pdata);
    gtk_widget_show (check);

    /* Add a check button to toggle activity mode */
    check = gtk_check_button_new_with_label ("Activity mode");
    gtk_table_attach (GTK_TABLE (table), check, 0, 1, 1, 2,
                      GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
                      5, 5);
    g_signal_connect (check, "clicked",
                      G_CALLBACK (toggle_activity_mode),
                      pdata);
    gtk_widget_show (check);

    /* Add a check button to toggle orientation */
    check = gtk_check_button_new_with_label ("Right to Left");
    gtk_table_attach (GTK_TABLE (table), check, 0, 1, 2, 3,
                      GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
                      5, 5);
    g_signal_connect (check, "clicked",
                      G_CALLBACK (toggle_orientation),
                      pdata);
    gtk_widget_show (check);

    /* Add a button to exit the program */
    button = gtk_button_new_with_label ("close");
    g_signal_connect_swapped (button, "clicked",
                              G_CALLBACK (gtk_widget_destroy),
                              pdata-&#62;window);
    gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);

    /* This makes it so the button is the default. */
    gtk_widget_set_can_default (button, TRUE);

    /* This grabs this button to be the default button. Simply hitting
     * the "Enter" key will cause this button to activate. */
    gtk_widget_grab_default (button);
    gtk_widget_show (button);

    gtk_widget_show (pdata-&#62;window);

    gtk_main ();
    
    return 0;
}</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="x810.html"
ACCESSKEY="P"
>&#60;&#60;&#60; Previous</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="book1.html"
ACCESSKEY="H"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="x861.html"
ACCESSKEY="N"
>Next &#62;&#62;&#62;</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>The Tooltips Object</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="c753.html"
ACCESSKEY="U"
>Up</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Dialogs</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>