Labels are used a lot in GTK--; they're the main method of placing text in windows. Labels emit no signals, because they do not have an associated X window, and therefore cannot receive X events. If you need to catch signals or do clipping for labels, you can use an Event Box; see Event Boxes.
The constructors for Gtk::Label
are
Gtk::Label(const nstring &label = 0);
The sole argument is the string you wish the label to display.
nstring
is a special GTK-- version of the C++ string, which
can also be a NULL pointer. It's internal to GTK--; all you need to
know about it is that you can pass 0 as an nstring
argument value
whenever you would want to pass a NULL
ptr - something you can't do
with a standard C++ string. This is analogous to passing a NULL
pointer to a C function taking a char*
argument:
void a_c_func(char *arg);
...
a_c_func(0);
void a_cxx_func(nstring &arg);
...
a_cxx_func(0);
To change the label's text after creation, use the method:
void Gtk::Label::set_text(const string &str);
where &str
is the new string.
The space needed for the new string will be automatically adjusted if needed. You can produce multi-line labels by putting line breaks in the label string.
To retrieve the current string, use:
string Gtk::Label::get_text();
The label text can be justified using:
void Gtk::Label::set_justify(GtkJustification jtype);
Values for jtype
are:
GTK_JUSTIFY_LEFT
GTK_JUSTIFY_RIGHT
GTK_JUSTIFY_CENTER
(the default)GTK_JUSTIFY_FILL
The label widget is also capable of word-wrapping the text automatically. This can be activated using:
void Gtk::Label::set_line_wrap (bool wrap);
If you want your label underlined, then you can set a pattern on the label:
void Gtk::Label::set_pattern (const nstring &pattern);
The pattern argument indicates how the underlining should look. It consists of a string of underscore and space characters. An underscore indicates that the corresponding character in the label should be underlined. For example, the string
"__ __"would underline the first two characters, and the eigth and ninth characters.
Below is a short example to illustrate these functions. This example makes use of the Frame widget to better demonstrate the label styles. It also gives some indication of what GTK-- developers do in their off-hours. (The Frame widget is explained in the Frame section.)
Source location: examples/label/label.cc
#include <gtk--/box.h>
#include <gtk--/frame.h>
#include <gtk--/label.h>
#include <gtk--/window.h>
#include <gtk--/main.h>
class AppWindow : Gtk::Window
{
public:
AppWindow();
~AppWindow();
/* It's a good idea to do this for all application windows. */
gint delete_event_impl (GdkEventAny*)
{
Gtk::Main::quit();
return 0;
}
};
AppWindow::AppWindow()
: Gtk::Window (GTK_WINDOW_TOPLEVEL)
{
Gtk::Box *hbox;
Gtk::Box *vbox;
Gtk::Frame* frame;
Gtk::Label* label;
/* Set some window properties */
set_title("Label Example");
set_border_width (5);
/* Here we connect the "destroy" event to a signal handler */
destroy.connect (Gtk::Main::quit.slot());
vbox = manage( new Gtk::VBox (false, 5) );
hbox = manage( new Gtk::HBox (false, 5) );
add (*hbox);
hbox->pack_start (*vbox, false, false);
frame = manage( new Gtk::Frame ("Normal Label") );
label = manage( new Gtk::Label ("This is a Normal label") );
frame->add (*label);
vbox->pack_start (*frame, false, false);
frame = manage( new Gtk::Frame ("Multi-line Label") );
label = manage( new Gtk::Label ("This is a Multi-line label.\nSecond line\n" \
"Third line"));
frame->add (*label);
vbox->pack_start (*frame, false, false);
frame = manage( new Gtk::Frame ("Left Justified Label") );
label = manage( new Gtk::Label ("This is a Left-Justified\n" \
"Multi-line label.\nThird line"));
label->set_justify (GTK_JUSTIFY_LEFT);
frame->add (*label);
vbox->pack_start (*frame, false, false);
frame = manage( new Gtk::Frame ("Right Justified Label"));
label = manage( new Gtk::Label ("This is a Right-Justified\nMulti-line label.\n" \
"Fourth line, (j/k)"));
label->set_justify (GTK_JUSTIFY_RIGHT);
frame->add (*label);
vbox->pack_start (*frame, false, false);
vbox = manage( new Gtk::VBox (false, 5) );
hbox->pack_start (*vbox, false, false);
frame = manage( new Gtk::Frame ("Line wrapped label"));
label = manage( new Gtk::Label ("This is an example of a line-wrapped label. It " \
"should not be taking up the entire " /* big space to test spacing */\
"width allocated to it, but automatically " \
"wraps the words to fit. " \
"The time has come, for all good men, to come to " \
"the aid of their party. " \
"The sixth sheik's six sheep's sick.\n" \
" It supports multiple paragraphs correctly, " \
"and correctly adds "\
"many extra spaces. "));
label->set_line_wrap (true);
frame->add (*label);
vbox->pack_start (*frame, false, false);
frame = manage( new Gtk::Frame("Filled, wrapped label") );
label = manage( new Gtk::Label("This is an example of a line-wrapped, filled label. " \
"It should be taking "\
"up the entire width allocated to it. " \
"Here is a seneance to prove "\
"my point. Here is another sentence. "\
"Here comes the sun, do de do de do.\n"\
" This is a new paragraph.\n"\
" This is another newer, longer, better " \
"paragraph. It is coming to an end, "\
"unfortunately.") );
label->set_justify (GTK_JUSTIFY_FILL);
label->set_line_wrap (true);
frame->add (*label);
vbox->pack_start (*frame, false, false);
frame = manage( new Gtk::Frame("Underlined label") );
label = manage( new Gtk::Label("This label is underlined!\n"
"This one is underlined in quite a funky fashion") );
label->set_justify (GTK_JUSTIFY_LEFT);
label->set_pattern ("_________________________ _ _________ _ ______ __ _______ ___");
frame->add (*label);
vbox->pack_start (*frame, false, false);
show_all ();
}
AppWindow::~AppWindow() {}
int main( int argc,
char *argv[] )
{
/* Initialise GTK */
Gtk::Main kit(&argc, &argv);
/* Create a new window */
AppWindow app;
/* Enter the event loop */
Gtk::Main::run ();
return(0);
}
The Arrow widget draws an arrowhead, facing in a number of possible directions and having a number of possible styles. It can be very useful when placed on a button in many applications.
The constructor for Gtk::Arrow
is
Gtk::Arrow( GtkArrowType arrow_type,
GtkShadowType shadow_type );
and you can manipulate it with
void Gtk::Arrow::set(GtkArrowType arrow_type,
GtkShadowType shadow_type );
The arrow_type
argument may take one of the following values:
GTK_ARROW_UP
GTK_ARROW_DOWN
GTK_ARROW_LEFT
GTK_ARROW_RIGHT
These values indicate the direction in which the arrow will
point. The shadow_type
argument may take one of these values:
GTK_SHADOW_IN
GTK_SHADOW_OUT
(the default)GTK_SHADOW_ETCHED_IN
GTK_SHADOW_ETCHED_OUT
Here's a brief example illustrating the use of arrows:
Source location: examples/arrow/arrow.cc
#include <gtk--/arrow.h>
#include <gtk--/box.h>
#include <gtk--/button.h>
#include <gtk--/window.h>
#include <gtk--/main.h>
class ArrowButton : public Gtk::Button
{
public:
ArrowButton(GtkArrowType,GtkShadowType);
~ArrowButton();
};
/* Create an Arrow widget with the specified parameters
* and pack it into a button */
ArrowButton::ArrowButton(GtkArrowType arrow_type,GtkShadowType shadow_type)
: Gtk::Button()
{
Gtk::Arrow* arrow = manage (new Gtk::Arrow (arrow_type, shadow_type));
add (*arrow);
}
ArrowButton::~ArrowButton() {};
/* We will derive our new application window from window */
class AppWindow : public Gtk::Window
{
public:
AppWindow();
~AppWindow();
/* It's a good idea to do this for all application windows. */
gint delete_event_impl (GdkEventAny*)
{
Gtk::Main::quit();
return 0;
}
};
AppWindow::AppWindow()
/* Create a new window */
: Gtk::Window(GTK_WINDOW_TOPLEVEL)
{
ArrowButton *button;
Gtk::HBox *box;
set_title ("Arrow Buttons");
/* Sets the border width of the window. */
set_border_width (10);
/* Create a box to hold the arrows/buttons */
box=manage (new Gtk::HBox (false, 0));
box->set_border_width (2);
/* Pack and show all our widgets */
button = manage (new ArrowButton (GTK_ARROW_LEFT, GTK_SHADOW_ETCHED_IN));
box->pack_start (*button, false, false, 3);
button = manage(new ArrowButton (GTK_ARROW_RIGHT, GTK_SHADOW_ETCHED_IN));
box->pack_start(*button, false, false, 3);
button = manage (new ArrowButton (GTK_ARROW_LEFT, GTK_SHADOW_ETCHED_OUT));
box->pack_start (*button, false, false, 3);
button = manage (new ArrowButton (GTK_ARROW_RIGHT, GTK_SHADOW_ETCHED_OUT));
box->pack_start (*button, false, false, 3);
add (*box);
show_all ();
}
AppWindow::~AppWindow() {};
int main (int argc, char *argv[])
{
Gtk::Main kit(argc, argv);
AppWindow arrows;
kit.run ();
return 0;
}
These are the little text strings that pop up when you leave your
pointer over a button or other widget for a few seconds. They are easy
to use, so we will just explain them without giving a full example; if you
want to see them in action, take a look at the eventbox.cc
example.
Widgets that do not receieve events (widgets that do not have their own window) will not work with tooltips.
The constructor is extremely simple:
Gtk::Tooltips();
Once you have created a new tooltip, and the widget you wish to use it on, simply use this call to set it:
void Gtk::Tooltips::set_tip(const Gtk::Widget &widget,
const nstring &tip_text,
const nstring &tip_private );
The first argument is the widget you wish to have this tooltip pop up
for, and the next is the text you want to display. The last argument is a text
string that can be used as an identifier when using Gtk::TipsQuery
to
implement context sensitive help; it should, for the present, be set to 0.
Here's a short example:
Gtk::Tooltips tooltips;
Gtk::Widget button("button1");
.
.
.
tooltips.set_tip (button, "This is button 1", 0);
There are other calls that can be used with tooltips:
void Gtk::Tooltips::enable();
Enables a disabled set of tooltips.
void Gtk::Tooltips::disable();
Disables an enabled set of tooltips.
void Gtk::Tooltips::set_delay(gint delay);
Sets how many milliseconds you have to hold your pointer over the widget before the tooltip will pop up. The default is 500 milliseconds (half a second).
void gtk_tooltips::set_colors(const Gdk_Color &background,
const Gdk_Color &foreground );
Sets the foreground and background color of the tooltips.
Progress bars are used to show the status of an operation. There
are two ways to create a progress bar: with or without an associated
Gtk::Adjustment
. If you don't provide an adjustment, one will be
created for you:
Gtk::ProgressBar();
Gtk::ProgressBar(GtkAdjustment &adjustment);
The second method has the advantage that we can use the adjustment object to specify our own range parameters for the progress bar.
The adjustment object of a progress bar can be changed using:
void Gtk::Progress::set_adjustment(GtkAdjustment &adjustment);
(Gtk::ProgressBar
derives from Gtk::Progress
).
After creating the progress bar, you can set its value using:
void Gtk::Progress::bar_update(gfloat percentage);
where percentage
is a number, from 0 to 1, indicating what
fraction of the bar should be filled up.
A progress bar may be set to one of four orientations using the method
void Gtk::ProgressBar::set_orientation( GtkProgressBarOrientation orientation );
where the orientation
argument may take one of the following
values to indicate the direction in which the progress bar should move:
GTK_PROGRESS_LEFT_TO_RIGHT
GTK_PROGRESS_RIGHT_TO_LEFT
GTK_PROGRESS_BOTTOM_TO_TOP
GTK_PROGRESS_TOP_TO_BOTTOM
When used as a measure of how far a process has progressed, the
Gtk::ProgressBar
can be set to display its value in either a continuous
or discrete mode. In continuous mode, the progress bar is updated for
each value. In discrete mode, the progress bar is updated in a number
of discrete blocks. The number of blocks is also configurable.
The style of a progress bar can be set using the following method:
void Gtk::ProgressBar::set_bar_style( GtkProgressBarStyle style );
The style
parameter can take one of two values:
GTK_PROGRESS_CONTINUOUS
GTK_PROGRESS_DISCRETE
The number of discrete blocks can be set by calling
void Gtk::ProgressBar::set_discrete_blocks(guint blocks);
Besides indicating the amount of progress that has occured, the progress bar can also be used to indicate that there is some activity; this is done by placing the progress bar in activity mode. In this mode, the progress bar displays a small rectangle which moves back and forth. Activity mode is useful in situations where the progress of an operation cannot be calculated as a value range (e.g., receiving a file of unknown length).
Activity mode is selected by passing a non-zero value to the following method:
void Gtk::Progress::set_activity_mode(guint activity_mode);
The step size of the activity indicator, and the number of blocks, are set using the following methods:
void Gtk::ProgressBar::set_activity_step(guint step);
void Gtk::ProgressBar::set_activity_blocks(guint blocks);
When in continuous mode, the progress bar can also display a configurable text string within its trough, using the following method:
void Gtk::Progress::set_format_string(const string &format);
The format
argument is similiar to one that would be used in a C
printf
statement. The following directives may be used within the
format string:
You can select whether or not to display this string using this method:
void Gtk::Progress::set_show_text(bool show_text);
The show_text
argument is a boolean true/false value. The
appearance of the text can be modified further using:
void Gtk::Progress::set_text_alignment(gfloat x_align,
gfloat y_align);
The x_align
and y_align
arguments take a value between 0.0
and 1.0. Their value indicates the position of the text string within
the trough. Values of 0.0 for both place the string in the top
left hand corner; values of 0.5 (the default) centres the text, and
values of 1.0 place the text in the lower right hand corner.
The current text setting of a progress object can be retrieved using the current or a specified adjustment value using the following two methods. They return the formatted string that would be displayed within the trough:
string Gtk::Progress::get_current_text();
string Gtk::Progress::get_text_from_value(gfloat value);
There is also another way to change the range and value of a progress object using the following method:
void Gtk::Progress::configure(gfloat value,
gfloat min,
gfloat max );
This function provides a convenient way to set the range and value of a progress object.
The remaining functions can be used to get and set the current value of a progess object in various types and formats:
void Gtk::Progress::set_percentage(gfloat percentage);
void Gtk::Progress::set_value(gfloat value);
gfloat Gtk::Progress::get_value();
gfloat Gtk::Progress::get_current_percentage();
gfloat Gtk::Progress::get_percentage_from_value(gfloat value);
The last of these takes a number falling between the minimum and
maximum values of the progress object's adjustment, and returns the
percentage to pass to set_percentage
.
Progress bars are often used with idle timeouts, described in the section Timeouts, I/O and Idle Functions, to give the illusion of multitasking.
Here is an example using a progress bar, updated using timeouts. This code also shows you how to reset the progress bar.
Source location: examples/progressbar/progressbar.cc
#include <gtk--/progressbar.h>
#include <gtk--/table.h>
#include <gtk--/label.h>
#include <gtk--/button.h>
#include <gtk--/main.h>
#include <gtk--/window.h>
// Gtk-- version of the "progress bar" example from the gtk+ tutorial
class ProgressBar : public Gtk::Window
{
bool m_pstat;
Gtk::Button m_bReset, m_bCancel;
Gtk::Label m_label;
Gtk::ProgressBar m_pbar;
Gtk::Table m_table;
gint delete_event_impl(GdkEventAny*) {
Gtk::Main::quit(); return 0;
}
public:
int progress();
void progress_r() { m_pstat = false; }
ProgressBar();
};
ProgressBar::ProgressBar() :
m_pstat(true),
m_bReset("Reset"), m_bCancel("Cancel"),
m_label("Progress Bar Example"),
m_table(3,2, true)
{
set_border_width(10);
add(m_table);
// You don't need attach_default(), Gtk::Table::attach() already has
// default args
m_table.attach(m_label, 0,2,0,1);
m_table.attach(m_pbar, 0,2,0,2);
// Set the timeout to handle automatic updating of the progress bar
Gtk::Main::timeout.connect(slot(this, &ProgressBar::progress),50);
m_bReset.clicked.connect(slot(this, &ProgressBar::progress_r));
m_table.attach(m_bReset, 0,1,2,3);
m_bCancel.clicked.connect(Gtk::Main::quit.slot());
m_table.attach(m_bCancel, 1,2,2,3);
show_all();
}
int
ProgressBar::progress()
{
gfloat pvalue = m_pbar.get_current_percentage();
pvalue += 0.01;
if ((pvalue >= 1.0) || (m_pstat == false)) {
pvalue = 0.0;
m_pstat = true;
}
m_pbar.set_percentage(pvalue);
return true;
}
int main (int argc, char *argv[])
{
Gtk::Main myapp(argc, argv);
ProgressBar progressbar;
myapp.run();
return 0;
}
The Dialog widget is a window with a few widgets pre-packed into it for you. It consists of a VBox, a horizontal separator, and an HBox, stacked on top of each other. The HBox is at the bottom and comprises the action area, which generally contains buttons such as "OK", "Cancel", etc. The Dialog widget is useful for displaying pop-up messages and other similar tasks. There is only one constructor for it:
Gtk::Dialog();
You can pack a button in the action area by doing something like this:
Gtk::Dialog dialog;
Gtk::Button button("click me");
Gtk::HBox *dialogHBox = dialog.get_action_area();
dialogHBox->pack_start (button, true, true, 0);
button.show();
You can add to the VBox area by packing, for instance, a label into it:
Gtk::Label label("Dialogs are groovy");
Gtk::VBox *vbox = dialog.get_vbox();
vbox->pack_start (label, true, true, 0);
label.show();
If the simple functionality provided by the default vertical and horizontal boxes in the two areas does't give you enough control for your application, then you can simply pack another layout widget into the boxes provided. For example, you could pack a table into the vertical box.
Pixmaps are data structures that contain pictures. These pictures can be used in various places; they're often used as icons on the X-Windows desktop, or as cursors. A pixmap which only has 2 colours is called a bitmap; there are a few additional routines for handling this common special case.
To understand pixmaps, it might help to understand a bit about how X-windows works. Under X-windows, applications do not need to be running on the same computer that is interacting with the user. Instead, the various applications, called clients, all communicate with a program which displays the graphics and handles the keyboard and mouse. This program which interacts directly with the user is called a display server or X server. Since the communication might take place over a network, it's important to keep some information within the X server. Pixmaps, for example, are stored in the memory of the X server. This means that once pixmap values are set, they don't need to be re-transmitted over the network; instead, a command is sent to the X server which says something like "display pixmap number XYZ here."
Note that even if you're using GTK-- on a non-X-windows platform, you still need to understand pixmaps; using them will keep your code portable, and they're used in many places in GTK--.
There are several ways to create pixmaps in GTK--. Most simply, you can use one of the following constructors:
Gtk::Pixmap(Gtk::Widget &w, const nstring &xpmfilename);
Gtk::Pixmap(Gtk::Widget &w, const gchar *const *data);
In both cases, the Gtk::Widget
passed as the first argument
should be the one in which the pixmap will eventually be displayed
(e.g. a container, like a Gtk::Window
or Gtk::Button
); it's
called the reference widget.
The first constructor builds a pixmap from an XPM file. XPM
format is a human-readable representation of a pixmap; it is widely
used for storing pixmap data on X-windows systems. The
xpmfilename
parameter of the first constructor is a path to an
XPM file.
The second constructor builds the pixmap from raw XPM-format data;
the data
parameter of the second constructor is a pointer to the
data. This data must not be freed until the reference widget is
realised (i.e., displayed).
Another, slightly more complicated, way to construct a
Gtk::Pixmap
is to first build a Gdk_Pixmap
structure using
routines from GDK--. As with the first two constructors we showed
you, you can do this either with in-memory data, or from data read
from a file. Here is how to create a pixmap from data in memory:
Gdk_Bitmap( Gdk_Window &window,
gchar *data,
gint width,
gint height );
This routine is used to create a single-plane pixmap (2 colours). Each
bit of the data represents whether that pixel is off or on. Width and
height are in pixels. Gdk_Window
is the current window;
pixmap resources are meaningful only in the context of the screen
where they are to be displayed.
Gdk_Pixmap ( GdkWindow *window,
gchar *data,
gint width,
gint height,
gint depth,
const Gdk_Color &fg,
const Gdk_Color &bg );
This is used to create a pixmap of the given depth (number of colours)
from the bitmap data specified. fg
and bg
are the foreground
and background colours to use.
Gdk_Pixmap( Gdk_Window &window,
Gdk_Bitmap &mask,
const Gdk_Color &transparent_color,
const string &filename );
As before, filename
is a path to an XPM file, which will be
loaded into the new pixmap structure. The mask specifies which bits of
the pixmap are to be opaque; all other bits are coloured using the
colour specified by transparent_color
. We'll give an example of
this technique later on.
Gdk_Pixmap::create_from_xpm_d( const Gdk_Drawable &drawable,
Gdk_Bitmap &mask,
const Gdk_Color &transparent_color,
gchar *const *data );
This constructor is used to create a pixmap from XPM data incorporated into the program's code. An example:
/* XPM */
static const char *const xpm_data[] = {
"16 16 3 1",
" c None",
". c #000000000000",
"X c #FFFFFFFFFFFF",
" ",
" ...... ",
" .XXX.X. ",
" .XXX.XX. ",
" .XXX.XXX. ",
" .XXX..... ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" ......... ",
" ",
" "};
If you've got a keen eye, you'll recognise the famous 'document' icon (a dog-eared sheet of paper) in the above code.
When you're done using a pixmap and not likely to reuse it again soon, it is a good idea to delete it. Pixmaps should be considered a precious resource.
Once you've created a pixmap, you can display it as a GTK-- widget. The appropriate constructor is
Gtk::Pixmap(const Gdk_Pixmap &pixmap,
const Gdk_Bitmap &mask);
The other pixmap widget calls are:
void Gtk::Pixmap::set(const Gdk_Pixmap &newpixmap,
const Gdk_Bitmap &mask );
void Gtk::Pixmap::get(Gdk_Pixmap &pixmap,
Gdk_Bitmap &mask);
Gtk::Pixmap::set
is used to change the pixmap that the widget is
currently managing; newpixmap
is the pixmap created using GDK.
In the following example, we make a button which is marked with a pixmap:
Source location: examples/pixmap/pixmap.cc
#include <iostream>
#include <gtk--/window.h>
#include <gtk--/main.h>
#include <gtk--/pixmap.h>
#include <gtk--/button.h>
// Gtk-- version of the "pixmap" example from the gtk+ tutorial
/* XPM data of Open-File icon */
static const char * xpm_data[] = {
"16 16 3 1",
" c None",
". c #000000000000",
"X c #FFFFFFFFFFFF",
" ",
" ...... ",
" .XXX.X. ",
" .XXX.XX. ",
" .XXX.XXX. ",
" .XXX..... ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" ......... ",
" ",
" "
};
class Pixmap : public Gtk::Window
{
Gtk::Button m_button;
Gtk::Pixmap m_pixmap;
gint delete_event_impl(GdkEventAny*) {
Gtk::Main::quit(); return 0;
}
public:
Pixmap();
void button_clicked() { cout << "button clicked" << endl; }
};
Pixmap::Pixmap() :
m_pixmap(xpm_data)
{
add(m_button);
m_button.add(m_pixmap);
m_button.clicked.connect(slot(this, &Pixmap::button_clicked));
show_all();
}
int main (int argc, char *argv[])
{
Gtk::Main myapp(argc, argv);
Pixmap pixmap;
myapp.run();
return 0;
}
We could, in the example above, have loaded the pixmap data from a
file instead. For example, to load the pixmap
from an XPM data file called icon0.xpm
in the current
directory, we would have created the pixmap using:
Gtk::Pixmap pixmap(window, "./icon0.xpm" );
window.add(pixmap);
One disadvantage of using pixmaps is that the displayed object is always rectangular, regardless of the image; sometimes you might want to use icons that have other shapes. This can be done using shaped windows. A shaped window is a pixmap where the background pixels are transparent. This way, when the background image is multi-coloured, we don't overwrite it with a rectangular, non-matching border around our icon. The following example displays a picture of a wheelbarrow on the screen:
Source location: examples/wheelbarrow/wheelbarrow.cc
#include <iostream>
#include <gtk--/window.h>
#include <gtk--/pixmap.h>
#include <gtk--/fixed.h>
#include <gtk--/main.h>
//From <iostream>
using std::cout;
using std::endl;
// Gtk-- version of the "wheelbarrow" example from the gtk+ tutorial
// XPM
static char * WheelbarrowFull_xpm[] = {
"48 48 64 1",
" c None",
". c #DF7DCF3CC71B",
"X c #965875D669A6",
"o c #71C671C671C6",
"O c #A699A289A699",
"+ c #965892489658",
"@ c #8E38410330C2",
"# c #D75C7DF769A6",
"$ c #F7DECF3CC71B",
"% c #96588A288E38",
"& c #A69992489E79",
"* c #8E3886178E38",
"= c #104008200820",
"- c #596510401040",
"; c #C71B30C230C2",
": c #C71B9A699658",
"> c #618561856185",
", c #20811C712081",
"< c #104000000000",
"1 c #861720812081",
"2 c #DF7D4D344103",
"3 c #79E769A671C6",
"4 c #861782078617",
"5 c #41033CF34103",
"6 c #000000000000",
"7 c #49241C711040",
"8 c #492445144924",
"9 c #082008200820",
"0 c #69A618611861",
"q c #B6DA71C65144",
"w c #410330C238E3",
"e c #CF3CBAEAB6DA",
"r c #71C6451430C2",
"t c #EFBEDB6CD75C",
"y c #28A208200820",
"u c #186110401040",
"i c #596528A21861",
"p c #71C661855965",
"a c #A69996589658",
"s c #30C228A230C2",
"d c #BEFBA289AEBA",
"f c #596545145144",
"g c #30C230C230C2",
"h c #8E3882078617",
"j c #208118612081",
"k c #38E30C300820",
"l c #30C2208128A2",
"z c #38E328A238E3",
"x c #514438E34924",
"c c #618555555965",
"v c #30C2208130C2",
"b c #38E328A230C2",
"n c #28A228A228A2",
"m c #41032CB228A2",
"M c #104010401040",
"N c #492438E34103",
"B c #28A2208128A2",
"V c #A699596538E3",
"C c #30C21C711040",
"Z c #30C218611040",
"A c #965865955965",
"S c #618534D32081",
"D c #38E31C711040",
"F c #082000000820",
" ",
" .XoO ",
" +@#$%o& ",
" *=-;#::o+ ",
" >,<12#:34 ",
" 45671#:X3 ",
" +89<02qwo ",
"e* >,67;ro ",
"ty> 459@>+&& ",
"$2u+ ><ipas8* ",
"%$;=* *3:.Xa.dfg> ",
"Oh$;ya *3d.a8j,Xe.d3g8+ ",
" Oh$;ka *3d$a8lz,,xxc:.e3g54 ",
" Oh$;kO *pd$%svbzz,sxxxxfX..&wn> ",
" Oh$@mO *3dthwlsslszjzxxxxxxx3:td8M4 ",
" Oh$@g& *3d$XNlvvvlllm,mNwxxxxxxxfa.:,B* ",
" Oh$@,Od.czlllllzlmmqV@V#V@fxxxxxxxf:%j5& ",
" Oh$1hd5lllslllCCZrV#r#:#2AxxxxxxxxxcdwM* ",
" OXq6c.%8vvvllZZiqqApA:mq:Xxcpcxxxxxfdc9* ",
" 2r<6gde3bllZZrVi7S@SV77A::qApxxxxxxfdcM ",
" :,q-6MN.dfmZZrrSS:#riirDSAX@Af5xxxxxfevo",
" +A26jguXtAZZZC7iDiCCrVVii7Cmmmxxxxxx%3g",
" *#16jszN..3DZZZZrCVSA2rZrV7Dmmwxxxx&en",
" p2yFvzssXe:fCZZCiiD7iiZDiDSSZwwxx8e*>",
" OA1<jzxwwc:$d%NDZZZZCCCZCCZZCmxxfd.B ",
" 3206Bwxxszx%et.eaAp77m77mmmf3&eeeg* ",
" @26MvzxNzvlbwfpdettttttttttt.c,n& ",
" *;16=lsNwwNwgsvslbwwvccc3pcfu<o ",
" p;<69BvwwsszslllbBlllllllu<5+ ",
" OS0y6FBlvvvzvzss,u=Blllj=54 ",
" c1-699Blvlllllu7k96MMMg4 ",
" *10y8n6FjvllllB<166668 ",
" S-kg+>666<M<996-y6n<8* ",
" p71=4 m69996kD8Z-66698&& ",
" &i0ycm6n4 ogk17,0<6666g ",
" N-k-<> >=01-kuu666> ",
" ,6ky& &46-10ul,66, ",
" Ou0<> o66y<ulw<66& ",
" *kk5 >66By7=xu664 ",
" <<M4 466lj<Mxu66o ",
" *>> +66uv,zN666* ",
" 566,xxj669 ",
" 4666FF666> ",
" >966666M ",
" oM6668+ ",
" *4 ",
" ",
" "
};
class Wheelbarrow : public Gtk::Window
{
Gtk::Fixed m_fixed;
Gtk::Pixmap m_pixmap;
gint delete_event_impl(GdkEventAny*) {
Gtk::Main::quit(); return 0;
}
public:
Wheelbarrow();
void button_clicked() { cout << "button clicked" << endl; }
};
Wheelbarrow::Wheelbarrow() :
Gtk::Window(GTK_WINDOW_POPUP),
m_pixmap(WheelbarrowFull_xpm)
{
Gdk_Pixmap pixmap;
Gdk_Bitmap mask;
m_fixed.set_usize(200, 200);
m_fixed.put(m_pixmap, 0, 0);
add(m_fixed);
set_uposition(20, 400);
show_all(); // first show everything : this is needed for the Pixmap
// to be actually instantiated
m_pixmap.get(pixmap, mask);
shape_combine_mask(mask, 0, 0);
show();
}
int main (int argc, char *argv[])
{
Gtk::Main myapp(&argc, &argv);
Wheelbarrow wheelbarrow;
myapp.run();
return 0;
}
To make the wheelbarrow image sensitive to mouse-clicks, we can
attach a callback to the button_press_event
signal to make it do
something. The following code will make the picture sensitive to a
mouse button being pressed, which makes the application terminate:
window.set_events(window.get_events() | GDK_BUTTON_PRESS_MASK );
window.button_press_event.connect( slot(&close_application) );
Ruler widgets are used to indicate the location of the mouse pointer in a given window; they're often found in drawing programs. A window can have a vertical ruler spanning across the width and a horizontal ruler spanning down the height. A small triangular indicator on the ruler shows the exact location of the pointer relative to the ruler.
Horizontal and vertical rulers have one constructor each:
Gtk::HRuler(); // horizontal ruler
Gtk::VRuler(); // vertical ruler
Once a ruler is created, you can define the unit of measurement. Units
of measure for rulers can be GTK_PIXELS
, GTK_INCHES
or
GTK_CENTIMETERS
. This is set using
void Gtk::Ruler::set_metric(GtkMetricType metric);
The default measurement is GTK_PIXELS
(note that this avoids
showing favouritism for other systems of measurement!).
ruler.set_metric(GTK_PIXELS);
Other important characteristics of a ruler are how to mark the units of scale, and where the position indicator is initially placed. These are set for a ruler using
void Gtk::Ruler::set_range(gfloat lower,
gfloat upper,
gfloat position,
gfloat max_size );
The arguments lower
and upper
define the extent of the
ruler, and max_size
is the largest possible number that will be
displayed. position
defines the initial position of the pointer
indicator within the ruler.
A vertical ruler can be made to span an 800 pixel wide window using:
vruler.set_range(0, 800, 0, 800);
The markings displayed on the ruler will be from 0 to 800, with a number for every 100 pixels. If instead we wanted the ruler to range from 7 to 16, we could write
vruler.set_range(7, 16, 0, 20);
The indicator on the ruler is a small triangular mark that indicates
the position of the pointer relative to the ruler. If you want the
indicator to follow the mouse pointer, you need to connect the ruler's
motion_notify_event()
callback to the motion_notify_event
signal. For example:
m_area.motion_notify_event.connect(m_hrule.motion_notify_event.slot());
This statement appears in the example below.
The following example creates a drawing area with a horizontal ruler above it and a vertical ruler to the left of it. The size of the drawing area is 600 pixels wide by 400 pixels high. The horizontal ruler spans from 7 to 13 with a mark every 100 pixels, while the vertical ruler spans from 0 to 400 with a mark every 100 pixels. Placement of the drawing area and the rulers is done using a table.
Source location: examples/rulers/rulers.cc
#include <gtk--/main.h>
#include <gtk--/table.h>
#include <gtk--/window.h>
#include <gtk--/ruler.h>
#include <gtk--/drawingarea.h>
// Gtk-- version of the "rulers" example from the gtk+ tutorial
class Rulers : public Gtk::Window
{
Gtk::Table m_table;
Gtk::DrawingArea m_area;
Gtk::HRuler m_hrule;
Gtk::VRuler m_vrule;
gint delete_event_impl(GdkEventAny*) {
Gtk::Main::quit(); return 0;
}
static const int XSIZE = 600,
YSIZE = 400;
public:
Rulers();
};
Rulers::Rulers() :
m_table(3, 2, false)
{
set_border_width(10);
add(m_table);
m_area.size(XSIZE, YSIZE);
m_table.attach(m_area, 1,2,1,2,
GtkAttachOptions(GTK_EXPAND|GTK_FILL), GTK_FILL, 0, 0);
m_area.set_events(GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK );
// The horizontal ruler goes on top. As the mouse moves across the
// drawing area, a motion_notify_event is passed to the appropriate
// event handler for the ruler.
m_hrule.set_metric(GTK_PIXELS);
m_hrule.set_range(7, 13, 0, 20 );
m_area.motion_notify_event.connect(m_hrule.motion_notify_event.slot());
m_table.attach(m_hrule, 1,2,0,1,
GTK_EXPAND|GTK_SHRINK|GTK_FILL, GTK_FILL,
0, 0);
m_vrule.set_metric(GTK_PIXELS);
m_vrule.set_range(0, YSIZE, 10, YSIZE );
m_area.motion_notify_event.connect(m_vrule.motion_notify_event.slot());
m_table.attach(m_vrule, 0, 1, 1, 2,
GTK_FILL, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0 );
show_all();
}
int main (int argc, char *argv[])
{
Gtk::Main myapp(argc, argv);
Rulers rulers;
myapp.run();
return 0;
}
Statusbars are used to display status messages. They keep a stack of the messages pushed onto them, so that popping the current message will redisplay the previous text message.
To make it easier for different parts of an application to use the same statusbar to display messages, the statusbar widget issues context identifiers which are used to identify different 'users'. These context identifiers are then be used to manipulate individual messages on the stack. The use of context identifiers is not optional; you have to obtain one to display messages on a statusbar.
Gtk::Statusbar has a very simple constructor:
Gtk::StatusBar();
A new context identifier is requested using a call to the following
method. context_description
is a short textual description of
the context:
guint Gtk::StatusBar::get_context_id(const nstring &context_description);
There are three methods that can operate on statusbars:
guint Gtk::StatusBar::push(guint context_id,
const nstring &text );
void Gtk::StatusBar::pop(guint context_id );
void Gtk::StatusBar::remove(guint context_id,
guint message_id );
The first, Gtk::StatusBar::push()
, is used to add a new message to the
statusbar. It returns a message identifier
, which can be passed later
to the function Gtk::StatusBar::remove
to remove the message with the
given message and context identifiers from the statusbar's stack.
Gtk::StatusBar::pop()
removes the message highest in the
stack having the given context identifier.
This may seem like an awfully complicated mechanism for such a seemingly
simple task, but if you've done much GUI programming, you'll quickly
appreciate what this does for you. GUI interfaces often have multiple
things going on at once (whether they're multi-threaded or not), and
it can sometimes be more trouble than it's worth to give each task a
way to display messages to the user. Gtk::StatusBar
makes it
easy (well, easier, at any rate).
The following example creates a statusbar and two buttons: one for pushing items onto the statusbar, and one for popping the last item back off.
Source location: examples/statusbar/statusbar.cc
#include <gtk--/box.h>
#include <gtk--/button.h>
#include <gtk--/main.h>
#include <gtk--/window.h>
#include <gtk--/statusbar.h>
// Gtk-- version of the "statusbar" example from the gtk+ tutorial
class StatusBar : public Gtk::Window
{
Gtk::VBox m_vbox;
Gtk::Button m_bPush, m_bPop;
Gtk::Statusbar m_status_bar;
// Note : m_context_id has to be declared *after* m_status_bar to be
// initialized in the constructor's init list
unsigned int m_context_id,
m_count;
void push_item(unsigned int context_id);
void pop_item(unsigned int context_id) { m_status_bar.pop(context_id); }
public:
StatusBar();
/* It's a good idea to do this for all application windows. */
gint delete_event_impl (GdkEventAny*)
{
Gtk::Main::quit();
return 0;
}
};
StatusBar::StatusBar() :
m_vbox(false, 1),
m_bPush("push item"),
m_bPop("pop last item"),
m_context_id(m_status_bar.get_context_id("Statusbar example")),
m_count(1)
{
set_usize(200, 100);
set_title("Gtk-- Statusbar Example");
add(m_vbox);
m_vbox.pack_start(m_status_bar);
m_bPush.clicked.connect(bind(slot(this, &StatusBar::push_item), m_context_id));
m_vbox.pack_start(m_bPush);
m_bPop.clicked.connect(bind(slot(this, &StatusBar::pop_item), m_context_id));
m_vbox.pack_start(m_bPop);
show_all();
}
void
StatusBar::push_item(unsigned int context_id)
{
char buff[20];
g_snprintf(buff, 20, "Item %d", m_count++);
m_status_bar.push(context_id, buff);
}
int main (int argc, char *argv[])
{
Gtk::Main myapp(argc, argv);
StatusBar statusbar;
myapp.run();
return 0;
}
Text-entry widgets allow the user to enter text (surprisingly
enough); they're called Gtk::Entry
in GTK--. They have two
constructors:
Gtk::Entry();
Gtk::Entry(guint16 max);
The first creates an empty text-entry widget; the second creates an empty text-entry widget with a fixed limit on the length of its text.
There are several functions for altering the text in a Gtk::Entry
widget:
void Gtk::Entry::set_text(const string &text);
void Gtk::Entry::append_text(const string &text);
void Gtk::Entry::prepend_text(const string &text);
Gtk::Entry::set_text()
replaces the current text in the entry
widget with the string in text
; Gtk::Entry::append_text()
and Gtk::Entry::prepend_text()
add the contents of text
to
the end and beginning of the current text, respectively.
You can change the position of the insertion point using
void Gtk::Entry::set_position(gint position);
The way the position
argument is interpreted is as follows. If
the current contents of the widget are
hello world
and you call set_position()
with an argument of 5, and then type
the letter X, the contents will be
helloX world
You can retrieve the current contents of a text-entry widget using
string Gtk::Entry::get_text();
Occasionally you might want to make a text-entry widget read-only.
This can be done by passing false
to the following method:
void Gtk::Entry::set_editable(bool editable);
A text-entry widget whose editable
flag is turned off won't
respond to keypresses; however, the text in it can still be selected.
Another fairly common use for text-entry widgets is for the input of
passwords, passphrases and other information you don't want echoed
on the screen. Gtk::Entry
provides the visibility
flag to
handle these cases:
void Gtk::Entry::set_visibility(bool visible);
When the visibility
flag is set to false
, the letters typed
into the text-entry widget show up as asterisks. (This can be changed
on the fly, as you'll see in the example below.)
Gtk::Entry
supports a selection region for copying text, and
other purposes. You can change the selection region using
void Gtk::Entry::select_region(gint start,
gint end );
start
and end
are interpreted just as position
is for
set_position()
(see above).
You might want to be notified whenever the user types in a text entry
widget. Gtk::Entry
provides two signals, activate
and
changed
, for just this purpose. activate
is emitted when
the user presses the enter key in a text-entry widget; changed
is
emitted when the text in the widget changes. You can use these to
validate or filter the text the user types, among other things.
Here is an example using Gtk::Entry
. It provides, besides a
Gtk::Entry
widget, two checkboxes, with which you can toggle the
editable and visible flags.
Source location: examples/entry/entry.cc
#include <iostream>
#include <gtk--/box.h>
#include <gtk--/button.h>
#include <gtk--/checkbutton.h>
#include <gtk--/entry.h>
#include <gtk--/main.h>
#include <gtk--/window.h>
// Gtk-- version of the "entry" example from the gtk+ tutorial
class Entry : public Gtk::Window
{
Gtk::HBox m_hbox;
Gtk::VBox m_vbox;
Gtk::Entry m_entry;
Gtk::Button m_bClose;
Gtk::CheckButton m_cbEditable, m_cbVisible;
void toggleEditable() { m_entry.set_editable(m_cbEditable.get_active()); }
void toggleVisibility() { m_entry.set_visibility(m_cbVisible.get_active()); }
void enterCallback();
gint delete_event_impl(GdkEventAny*) {
Gtk::Main::quit(); return 0;
}
public:
Entry();
};
Entry::Entry() :
m_hbox(false, 0),
m_vbox(false, 0),
m_entry(50),
m_bClose("Close"),
m_cbEditable("Editable"),
m_cbVisible("Visible")
{
set_usize(200, 100);
set_title("Gtk-- Entry");
add(m_vbox);
m_entry.activate.connect(slot(this, &Entry::enterCallback));
m_entry.set_text("hello");
m_entry.append_text(" world");
m_entry.select_region(0, m_entry.get_text_length());
m_vbox.pack_start(m_entry);
// Note that add() can also be used instead of pack_xxx()
m_vbox.add(m_hbox);
m_hbox.pack_start(m_cbEditable);
m_cbEditable.toggled.connect(slot(this, &Entry::toggleEditable));
m_cbEditable.set_active(true);
m_hbox.pack_start(m_cbVisible);
m_cbVisible.toggled.connect(slot(this,&Entry::toggleVisibility));
m_cbVisible.set_active(true);
m_bClose.clicked.connect(Gtk::Main::quit.slot());
m_vbox.pack_start(m_bClose);
m_bClose.set_flags(GTK_CAN_DEFAULT);
m_bClose.grab_default();
show_all();
}
void
Entry::enterCallback()
{
cout << "Entry contents : " << m_entry.get_text() << endl;
}
int main (int argc, char *argv[])
{
Gtk::Main myapp(&argc, &argv);
Entry entry;
myapp.run();
return 0;
}
Spinbuttons allow the user to select a value from a range of numeric values. It consists of a text entry box with up and down arrow buttons attached to the side. Selecting one of the buttons causes the value to 'spin' up and down across the range of possible values. The entry box may also be used to enter a value directly.
A spinbutton's value can have an adjustable number of decimal places, and the step size is configurable. Spinbuttons have an 'auto-repeat' feature as well: holding down one of the arrows can optionally cause the value to change more quickly the longer the arrow is held down.
Spinbuttons use an Adjustment object to hold information about the range of values they can have. Recall that an adjustment widget is created with the following constructor:
Gtk::Adjustment( gfloat value,
gfloat lower,
gfloat upper,
gfloat step_increment,
gfloat page_increment,
gfloat page_size );
These attributes of an Adjustment are used by the Spin Button in the following way:
value
: initial value for the Spin Buttonlower
: lower range valueupper
: upper range valuestep_increment
: value to increment/decrement when pressing
mouse button 1 on a buttonpage_increment
: value to increment/decrement when pressing
mouse button 2 on a buttonpage_size
: unusedAdditionally, mouse button 3 can be used to jump directly to the
upper
or lower
values.
Here is the Gtk::SpinButton
constructor:
Gtk::SpinButton( GtkAdjustment &adjustment,
gfloat climb_rate,
guint digits );
adjustment
is the adjustment object that this spinbutton will
use. The climb_rate
argument is an acceleration factor for when
the arrows are held down; a value of 0.0 turns acceleration off, and
1.0 is the maximum. The digits
argument specifies the number of
decimal places in the spinbutton's value.
The adjustment object can be set and retrieved using the following functions:
void Gtk::SpinButton::set_adjustment(Gtk::Adjustment& adjustment);
Gtk::Adjustment* Gtk::SpinButton::get_adjustment() const;
The number of decimal places can be altered using:
void Gtk::SpinButton::set_digits(guint digits) ;
You can set the spinbutton's value using:
void Gtk::SpinButton::set_value(gfloat value);
The value can be retrieved as either a floating point or integer value with the following functions:
gfloat Gtk::SpinButton::get_value_as_float();
gint Gtk::SpinButton::get_value_as_int();
The spin()
method allows you to 'spin' the spinbutton, just as
though its arrows had been clicked. Its prototype is
void Gtk::SpinButton::spin( GtkSpinType direction,
gfloat increment );
where the direction
parameter can take one of the following values:
GTK_SPIN_STEP_FORWARD
, GTK_SPIN_STEP_BACKWARD
Move the value up or down, respectively, by increment
. If
increment
is 0, change the value by the value of
step_increment
in the adjustment object.
GTK_SPIN_PAGE_FORWARD
, GTK_SPIN_PAGE_BACKWARD
Change the value by increment
.
GTK_SPIN_HOME
Set the value to the minimum value specified in the adjustment.
GTK_SPIN_END
Set the value to the maximum value specified in the adjustment.
GTK_SPIN_USER_DEFINED
Change the value by increment
.
To prevent the user from typing non-numeric characters into the entry
box, pass true
to
void Gtk::SpinButton::set_numeric(bool numeric);
You can cause the spinbutton to 'wrap' between its upper and lower bounds using
void Gtk::SpinButton::set_wrap(bool wrap);
To force the spinbutton's value to be 'snapped' to the nearest
step_increment
in the adjustment, use
void Gtk::SpinButton::set_snap_to_ticks(bool snap_to_ticks);
You can modify the update policy of a spinbutton using
void Gtk::SpinButton::set_update_policy(GtkSpinButtonUpdatePolicy policy);
where policy
is one of GTK_UPDATE_ALWAYS
or
GTK_UPDATE_IF_VALID
. GTK_UPDATE_ALWAYS
causes the
spinbutton to ignore errors encountered while converting the text in
the entry box to a numeric value. You can use this setting to allow
the spinbutton to accept non-numeric values. GTK_UPDATE_IF_VALID
causes the spinbutton to reject values that do not parse correctly, or
that are outside the valid numeric range specified in the adjustment
object.
You can change the spinbutton's shadow style using
void Gtk::SpinButton::set_shadow_type(GtkShadowType shadow_type);
where shadow_type
is one of
GTK_SHADOW_IN
GTK_SHADOW_OUT
GTK_SHADOW_ETCHED_IN
GTK_SHADOW_ETCHED_OUT
You can force an immediate update using
void Gtk::SpinButton::update();
Here's an example of a spinbutton in action:
Source location: examples/spinbutton/spinbutton.cc
#include <stdio.h>
#include <gtk--/checkbutton.h>
#include <gtk--/window.h>
#include <gtk--/frame.h>
#include <gtk--/box.h>
#include <gtk--/main.h>
#include <gtk--/spinbutton.h>
#include <gtk--/label.h>
#include <gtk--/adjustment.h>
class ToggleSnap: public Gtk::CheckButton
{
Gtk::SpinButton* spin_;
public:
ToggleSnap(Gtk::SpinButton *spin,const Gtk::string& s)
: Gtk::CheckButton(s), spin_(spin)
{}
void clicked_impl()
{
Gtk::CheckButton::clicked_impl();
spin_->set_snap_to_ticks(get_active());
}
};
class ToggleNumeric: public Gtk::CheckButton
{
Gtk::SpinButton* spin_;
public:
ToggleNumeric(Gtk::SpinButton *spin,const Gtk::string& s)
: Gtk::CheckButton(s), spin_(spin)
{}
void clicked_impl()
{
Gtk::CheckButton::clicked_impl();
spin_->set_numeric(get_active());
}
};
class AppWindow : public Gtk::Window
{
Gtk::SpinButton *spinner1;
Gtk::Label *val_label;
public:
AppWindow();
~AppWindow();
/* It's a good idea to do this for all application windows. */
gint delete_event_impl (GdkEventAny*)
{
Gtk::Main::quit();
return 0;
}
void change_digits( Gtk::SpinButton *spin );
void get_value(int display );
};
void AppWindow::change_digits( Gtk::SpinButton *spin )
{
spinner1->set_digits ( spin->get_value_as_int ());
}
void AppWindow::get_value(int display )
{
gchar buf[32];
if (display == 1)
sprintf (buf, "%d", spinner1->get_value_as_int ());
else
sprintf (buf, "%0.*f", spinner1->gtkobj()->digits,
spinner1->get_value_as_float ());
val_label->set_text (buf);
}
AppWindow::AppWindow()
: Gtk::Window (GTK_WINDOW_TOPLEVEL)
{
Gtk::Frame *frame;
Gtk::Box *hbox;
Gtk::Box *main_vbox;
Gtk::Box *vbox;
Gtk::Box *vbox2;
Gtk::SpinButton *spinner2;
Gtk::SpinButton *spinner;
Gtk::Button *button;
Gtk::CheckButton *checkbutton;
Gtk::Label *label;
Gtk::Adjustment *adj;
set_title ("Spin Button");
main_vbox = manage( new Gtk::VBox (false, 5) );
main_vbox->set_border_width (10);
add (*main_vbox);
frame = manage( new Gtk::Frame ("Not accelerated") );
main_vbox->pack_start (*frame, true, true, 0);
vbox = manage( new Gtk::VBox (false, 0) );
vbox->set_border_width (5);
frame->add (*vbox);
/* Day, month, year spinners */
hbox = manage( new Gtk::HBox (false, 0) );
vbox->pack_start (*hbox, true, true, 5);
vbox2 = manage( new Gtk::VBox (false, 0) );
hbox->pack_start (*vbox2, true, true, 5);
label = manage( new Gtk::Label ("Day :", 0, 0.5) );
vbox2->pack_start (*label, false, true, 0);
adj = manage( new Gtk::Adjustment (1.0, 1.0, 31.0, 1.0, 5.0, 0.0) );
spinner = manage( new Gtk::SpinButton (*adj, 0, 0) );
spinner->set_wrap (true);
spinner->set_shadow_type (GTK_SHADOW_OUT);
vbox2->pack_start (*spinner, false, true, 0);
vbox2 = manage( new Gtk::VBox (false, 0) );
hbox->pack_start (*vbox2, true, true, 5);
label = manage( new Gtk::Label ("Month :", 0, 0.5) );
vbox2->pack_start (*label, false, true, 0);
adj = manage( new Gtk::Adjustment (1.0, 1.0, 12.0, 1.0, 5.0, 0.0) );
spinner = manage( new Gtk::SpinButton (*adj, 0, 0) );
spinner->set_wrap (true);
spinner->set_shadow_type (GTK_SHADOW_ETCHED_IN);
vbox2->pack_start (*spinner, false, true, 0);
vbox2 = manage( new Gtk::VBox (false, 0) );
hbox->pack_start (*vbox2, true, true, 5);
label = manage( new Gtk::Label ("Year :", 0, 0.5) );
vbox2->pack_start (*label, false, true, 0);
adj = manage( new Gtk::Adjustment (1998.0, 0.0, 2100.0, 1.0, 100.0, 0.0) );
spinner = manage( new Gtk::SpinButton (*adj, 0, 0) );
spinner->set_wrap (false);
spinner->set_shadow_type (GTK_SHADOW_IN);
spinner->set_usize (55, 0);
vbox2->pack_start (*spinner, false, true, 0);
frame = manage( new Gtk::Frame ("Accelerated") );
main_vbox->pack_start (*frame, true, true, 0);
vbox = manage( new Gtk::VBox(false, 0) );
vbox->set_border_width (5);
frame->add (*vbox);
hbox = manage( new Gtk::HBox (false, 0) );
vbox->pack_start (*hbox, false, true, 5);
vbox2 = manage( new Gtk::VBox (false, 0) );
hbox->pack_start (*vbox2, true, true, 5);
label = manage( new Gtk::Label ("Value :", 0, 0.5) );
vbox2->pack_start (*label, false, true, 0);
adj = manage( new Gtk::Adjustment (0.0, -10000.0, 10000.0,
0.5, 100.0, 0.0) );
spinner1 = manage( new Gtk::SpinButton (*adj, 1.0, 2) );
spinner1->set_wrap (true);
spinner1->set_usize (100, 0);
vbox2->pack_start (*spinner1, false, true, 0);
vbox2 = manage( new Gtk::VBox (false, 0) );
hbox->pack_start (*vbox2, true, true, 5);
label = manage( new Gtk::Label ("Digits :", 0, 0.5) );
vbox2->pack_start (*label, false, true, 0);
adj = manage( new Gtk::Adjustment (2, 1, 5, 1, 1, 0) );
spinner2 = manage( new Gtk::SpinButton (*adj, 0.0, 0) );
spinner2->set_wrap (true);
adj->value_changed.connect(bind(slot(this, &AppWindow::change_digits),spinner2));
vbox2->pack_start (*spinner2, false, true, 0);
hbox = manage( new Gtk::HBox (false, 0) );
vbox->pack_start (*hbox, false, true, 5);
checkbutton = manage( new ToggleSnap (spinner, "Snap to 0.5-ticks"));
vbox->pack_start (*checkbutton, true, true, 0);
checkbutton->set_active (true);
checkbutton = manage( new ToggleNumeric (spinner, "Numeric only input mode") );
vbox->pack_start ( *checkbutton, true, true, 0);
checkbutton->set_active (true);
val_label = manage( new Gtk::Label ("") );
hbox = manage( new Gtk::HBox (false, 0) );
vbox->pack_start (*hbox, false, true, 5);
button = manage( new Gtk::Button ("Value as Int") );
button->clicked.connect(bind(slot(this,&AppWindow::get_value),1));
hbox->pack_start (*button, true, true, 5);
button = manage( new Gtk::Button ("Value as Float") );
button->clicked.connect(bind(slot(this,&AppWindow::get_value),2));
hbox->pack_start (*button, true, true, 5);
vbox->pack_start (*val_label, true, true, 0);
val_label->set_text ("0");
hbox = manage( new Gtk::HBox (false, 0));
main_vbox->pack_start (*hbox, false, true, 0);
button = manage( new Gtk::Button ("Close") );
button->clicked.connect(Gtk::Main::quit.slot());
hbox->pack_start (*button, true, true, 5);
show_all ();
}
AppWindow::~AppWindow() {}
int main( int argc,
char *argv[] )
{
/* Initialise GTK */
Gtk::Main kit(&argc, &argv);
/* Create a new window */
AppWindow app;
/* Enter the event loop */
Gtk::Main::run ();
return(0);
}
A combo box is like a cross between a flip-menu and a text-entry widget. It consists of a text-entry box with an arrow on the side; clicking the arrow reveals a menu of entries, and clicking on one of the entries enters it into the entry box. The entry box otherwise works just like a regular text-entry widget.
The constructor for the combo box is
Gtk::Combo()
A Gtk::Combo
contains a Gtk::Entry
widget, which is used to
implement the entry box. You can obtain the Gtk::Entry
using the
member function
Gtk::Entry* Gtk::Combo::get_entry() const;
To set the values in the flip-menu, use
void Gtk::Combo::set_popdown_strings(const Gtk::SArray& strings);
where strings
is a list of the strings you want to appear in the
list. A Gtk::SArray
is a converter object which can take any
kind of STL vector container; this means that you can pass vectors or
lists to this function, and things will work as you expect. For
example, the following is legal:
list<string> gl;
gl.push_back("String 1");
gl.push_back("String 2");
gl.push_back("String 3");
gl.push_back("String 4");
combo.set_popdown_strings(gl);
Gtk::Combo
has a number of key-bindings which make the widget a
bit easier to use. You can allow the values in the list to be
selected using the up-arrow and down-arrow keys by passing true
to
void Gtk::Combo::set_use_arrows(bool val);
Normally, when you press (for example) the down-arrow in the
entry-box, but you're on the last item in the flip-menu, the focus
will change. You can make the value wrap around instead by passing
true
to
void Gtk::Combo::set_use_arrows_always(bool val);
Gtk::Combo
also features completion; hitting ALT-TAB in the entry
box will cause the widget to attempt to complete the text in it using
the values in the flip-menu. You can set whether the completion
search is case-sensitive or not by calling
void Gtk::Combo::set_case_sensitive(gint val);
The colour selection widget is used for interactively selecting colours. This composite widget lets the user select a colour by manipulating RGB (Red, Green, Blue) and HSV (Hue, Saturation, Value) triples. This is done either by adjusting single values with sliders or entries, or by picking the desired colour from a hue-saturation wheel/value bar. Optionally, the opacity of the colour can also be set.
The colour selection widget currently emits only one signal,
color_changed
, which is emitted whenever the current colour in the
widget changes, either when the user changes it, or if it's set
explicitly through Gtk::ColorSelection::set_color()
.
The colour selection widget can be used on its own, as part of a
dialog, for example, or you can use the
Gtk::ColorSelectionDialog
, which is a complete colour-selection
dialog using Gtk::ColorSelection
.
The constructor for Gtk::ColorSelection
looks like this:
Gtk::ColorSelection();
You'll probably not be using this constructor directly. It creates an
orphan Gtk::ColorSelection
widget which you'll have to parent
yourself.
Gtk::ColorSelectionDialog
has the following constructor:
Gtk::ColorSelectionDialog(const nstring &title);
Gtk::ColorSelectionDialog
inherits from Gtk::Dialog
. It
consists of a Gtk::Frame
containing a Gtk::ColorSelection
widget, a Gtk::HSeparator
, and a Gtk::HBox
with three
buttons in it, marked "Ok", "Cancel" and "Help". (You can obtain the
button widgets using the get_ok_button()
,
get_cancel_button()
and get_help_button()
methods.)
Gtk::ColorSelection
has an adjustable update policy, which can be
set using
void Gtk::ColorSelection::set_update_policy(GtkUpdateType policy);
where policy
is one of GTK_UPDATE_CONTINUOUS
,
GTK_UPDATE_DISCONTINUOUS
, or GTK_UPDATE_DELAYED
. The
default policy is GTK_UPDATE_CONTINUOUS
, which means that the
current colour is updated continuously when the user drags the sliders
or presses the mouse and drags in the hue-saturation wheel or value
bar. If you experience performance problems, you may want to set the
policy to GTK_UPDATE_DISCONTINUOUS
or GTK_UPDATE_DELAYED
.
The colour selection widget supports the adjustment of the opacity of
a colour (also known as the colour's alpha channel). This is
disabled by default; to activate this feature, pass true
to
void Gtk::ColorSelection::set_opacity(gint use_opacity);
You can set the colour using
void Gtk::ColorSelection::set_color(gdouble *color);
where color
is an array of gdouble
s. The array should
contain four doubles, representing the red, green, blue, and alpha
channels, in that order. (If opacity is not enabled, the alpha
component is ignored.) The values of each channel must be between 0
and 1.
You can get the currently selected colour using
void Gtk::ColorSelection::get_color(gdouble *color);
color
should be a pointer to an array of gdouble
; the function
will fill in this array with the currently selected colour.
The file selection widget is a complete file-selection dialog. Its constructor is:
Gtk::FileSelection(const nstring &title);
The title
will be used in the window's title bar.
To set the selected file, use
void Gtk::FileSelection::set_filename(const string &filename);
This is useful for bringing the user to a specific directory, or to set a default filename.
To get the currently selected filename, call
string Gtk::FileSelection::get_filename();
There are also accessor functions for the widgets contained within the file selection widget. These are:
Gtk::HBox* get_action_area();
Gtk::Entry* get_selection_entry();
Gtk::Label* get_selection_text();
Gtk::Button* get_ok_button();
Gtk::Button* get_cancel_button();
You'll primarily use these for connecting signals; usually you'll connect something to at least the OK and Cancel buttons.
Here is an example of using the file selection widget:
Source location: examples/filesel/filesel.cc
/* example-start filesel filesel.cc */
#include <iostream>
#include <gtk--/fileselection.h>
#include <gtk--/main.h>
//From <iostream>
using std::cout;
using std::endl;
using SigC::slot;
class filesel: public Gtk::FileSelection
{
public:
filesel();
private:
/* Get the selected filename and print it to the console */
void file_ok_sel() {
cout << "file_ok_sel: " << get_filename() << endl;
}
gint delete_event_impl(GdkEventAny*) {
Gtk::Main::quit(); return 0;
}
};
filesel::filesel():
Gtk::FileSelection("File selection")
{
/* Connect the ok_button_ to file_ok_sel function */
get_ok_button()->clicked.connect(slot(this, &filesel::file_ok_sel));
/* Connect the cancel_button_ to hiding the window */
get_cancel_button()->clicked.connect(hide.slot());
/* Connect hiding the window to exit the program */
hide.connect(Gtk::Main::quit.slot());
}
int main (int argc, char *argv[])
{
/* Initialize GTK-- */
Gtk::Main m(&argc, &argv);
/* Create a new file selection widget */
filesel filew;
/* Lets set the filename, as if this were a save dialog, and we are giving
a default filename */
filew.set_filename("penguin.png");
filew.show();
m.run();
return 0;
}
/* example-end */