GtkProgressBar-Pasek postępu
Pasek postępu jest często używany, gdy nasz program wykonuje jakąś czasochłonną operację. Może on pokazywać ile procent zostało ukończone, ale także informować, że program nadal pracuje. W tej lekcji dowiemy się jak takowy pasek umieścić w naszej aplikacji.
Tworzenie ProgressBar’a
Stworzenie takiego widżetu sprowadza się do wywołania funkcji:
GtkWidget * gtk_progress_bar_new( void )
Już wiemy jak tworzy się pasek postępu. Teraz zobaczmy przykład użycia owego widżetu.
#include <gtk/gtk.h>
#include <stdio.h>
void ChangeValue( GtkRange * widget, gpointer data )
{
gdouble value = 0;
gchar * text;
GtkWidget * progressBar = GTK_WIDGET( data );
value = gtk_range_get_value( GTK_RANGE( widget ) );
gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR( progressBar ), value / 100 );
text = g_strdup_printf( "%d%%",( int ) value );
gtk_progress_bar_set_text( GTK_PROGRESS_BAR( progressBar ), text );
g_free( text );
}
int main( int argc, char * argv[] )
{
GtkWidget * window;
GtkWidget * vbox;
GtkWidget * progressBar;
GtkWidget * scale;
gtk_init( & argc, & argv );
window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
progressBar = gtk_progress_bar_new();
scale = gtk_hscale_new_with_range( 0, 100, 1 );
gtk_progress_bar_set_text( GTK_PROGRESS_BAR( progressBar ), "0%" );
vbox = gtk_vbox_new( FALSE, 0 );
gtk_container_border_width( GTK_CONTAINER( vbox ), 5 );
gtk_container_add( GTK_CONTAINER( window ), vbox );
gtk_box_pack_start( GTK_BOX( vbox ), progressBar, TRUE, TRUE, 0 );
gtk_box_pack_start( GTK_BOX( vbox ), scale, FALSE, FALSE, 0 );
g_signal_connect( G_OBJECT( window ), "destroy", G_CALLBACK( gtk_main_quit ), NULL );
g_signal_connect( G_OBJECT( scale ), "value-changed", G_CALLBACK( ChangeValue ), progressBar );
gtk_widget_show_all( window );
gtk_main();
return 0;
}
A więc tak. Tworzymy nowe
standardowe okno i progress bar.
Dodajemy poziomą skalę (coś jak widżet ustawiania głośności) funkcją:
GtkWidget * gtk_hscale_new_with_range( gdouble min, gdouble max, gdouble step )
Pierwszy argument to minimum, drugi maksimum, a trzeci to krok o jaki skala będzie się przesuwać, gdy użyjemy klawiatury.
Napis na pasku ustawiamy wywołując:
void gtk_progress_bar_set_text( GtkProgressBar * pbar, const gchar * text )
Pierwszy argument to nasz progress bar, drugi to tekst, który chcemy ustawić.
W dalszej części ustawiamy wszystko w kontenerach, ustawiamy sygnał zamknięcia okna oraz
zmiany wartości skali.
Używamy do tego sygnału
"value-changed". Gdy wartość zostanie zmieniona wywołujemy funkcję
ChangeValue
i, aby operować na pasku, podajemy go jako argument naszej funkcji.
Czas teraz na można by rzec
"serce naszego programu", czyli
void ChangeValue( GtkRange * widget, gpointer data )
.
gdouble gtk_range_get_value( GtkRange * range )
zwraca nam aktualną wartość na jaką jest ustawiona skala.
Kolejną przydatną (i raczej najważniejszą) rzeczą jest funkcja
void gtk_progress_bar_set_fraction( GtkProgressBar * pbar, gdouble fraction )
Ustawia ona wypełnienie paska postępu. Pierwszy argument tej funkcji to widżet paska, a drugi to wypełnienie, które może przyjąć wartości od
0.0 do 1.0.
Dzięki
g_strdup_printf()
zamieniamy liczby na tekst. Następnie ustawiamy wcześniej przygotowany napis na pasku i funkcją
g_free()
zwalniamy pamięć.
Pulsujący ProgressBar
Może zajść potrzeba, kiedy to nie wiadomo ile pracy przez program ma być wykonane. W takim momencie dobrze jest użyć
pulsującego paska postępu.
Po tym przykładzie i analizie znajdującej się poniżej będziesz już wiedzieć jak takowy wykonać.
#include <gtk/gtk.h>
gboolean pulse( gpointer data )
{
gtk_progress_bar_pulse( GTK_PROGRESS_BAR( data ) );
return TRUE;
}
int main( int argc, char * argv[] )
{
GtkWidget * window;
GtkWidget * progressBar;
gtk_init( & argc, & argv );
window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
progressBar = gtk_progress_bar_new();
gtk_container_add( GTK_CONTAINER( window ), progressBar );
g_timeout_add( 90,( GSourceFunc ) pulse, progressBar );
g_signal_connect( G_OBJECT( window ), "destroy", G_CALLBACK( gtk_main_quit ), NULL );
gtk_widget_show_all( window );
gtk_main();
return 0;
}
Program pokazuje pulsujący pasek postępu.
Tworzymy nowy pasek.
Funkcją
guint g_timeout_add( guint interval, GSourceFunc function, gpointer data )
ustawiamy regularne wykonanie funkcji co określony czas. Kończy ona swoje działanie, gdy wykonywana funkcja zwróci wartość
FALSE
. Pierwszy argument to opóźnienie w
ms, drugi to
nazwa funkcji, a trzeci wskaźnik, który chcemy przekazać(są nim widżety).
W
gboolean pulse( gpointer data )
Funkcja
void gtk_progress_bar_pulse( GtkProgressBar * pbar )
Przesuwa „bloczek” o
krok, którego wartość można ustalić dodatkową funkcją (
https://developer.gnome.org/gtk3/3.4/GtkProgressBar.html#gtk-progress-bar-set-pulse-step)
Podsumowanie
To by już było na tyle, jeśli chodzi o
Progress Bar’y.
Zapamiętaj
Pasek postępu potrzebuje dodatkowego wątku w programie, aby postęp był widoczny, gdy pierwszy wątek będzie zajęty, a nie utworzyliśmy drugiego dla paska, nie uzyskamy pożądanego efektu.