701aba3e4a
svn path=/trunk/gtk-sharp/; revision=9185
569 lines
No EOL
15 KiB
HTML
569 lines
No EOL
15 KiB
HTML
<html>
|
|
<title>GTK#</title>
|
|
<body>
|
|
|
|
<link rel="stylesheet" type="text/css" href="../../style.css" />
|
|
|
|
<h1>GTK#</h1>
|
|
by Johannes Roith (<a href="mailto:johannes@jroith.de">johannes@jroith.de</a>) [if you contribute to this chapter please add your name here]<br>
|
|
This chapter does use some content from the GTK+ Tutorial by Tony Gale, Ian Main, & the GTK team
|
|
|
|
<h2>Introduction</h2>
|
|
|
|
GTK (GIMP Toolkit) is a library for creating graphical user interfaces. It is licensed using the LGPL license, so you can develop open software, free software, or even commercial non-free software using GTK without having to spend anything for licenses or royalties.
|
|
<br><br>
|
|
It's called the GIMP toolkit because it was originally written for developing the GNU Image Manipulation Program (GIMP), but GTK has now been used in a large number of software projects, including the GNU Network Object Model Environment (GNOME) project. GTK is built on top of GDK (GIMP Drawing Kit) which is basically a wrapper around the low-level functions for accessing the underlying windowing functions (Xlib in the case of the X windows system), and gdk-pixbuf, a library for client-side image manipulation.
|
|
|
|
<h2>HelloWorld, first try</h2>
|
|
|
|
HelloWorld in Gtk#:
|
|
|
|
|
|
|
|
<table cellpadding=5 border=0>
|
|
<tr>
|
|
<td valign=top>
|
|
<pre class="code">
|
|
using Gtk;
|
|
using GtkSharp;
|
|
using System;
|
|
|
|
class Hello {
|
|
|
|
static void Main()
|
|
{
|
|
Application.Init ();
|
|
|
|
Window window = new Window ("helloworld");
|
|
window.Show();
|
|
|
|
Application.Run ();
|
|
|
|
}
|
|
|
|
|
|
}
|
|
</pre>
|
|
</td>
|
|
<td valign=top><img src=base.png border=0></td>
|
|
</tr></table>
|
|
|
|
|
|
[compile: mcs helloworld.cs -r gtk-sharp.dll -r glib-sharp.dll]<br><br>
|
|
It's a bit longer than console hello world and needs some explanation.<br><br>
|
|
Before we jump in the Main method, every GTK# Application will have to import the namespaces:
|
|
<pre class="code">
|
|
using Gtk;
|
|
using GtkSharp;
|
|
</pre>
|
|
If you don't do so, each Class from one of these namespaces needs the namespace mentioned as prefix.<br>
|
|
<br>
|
|
In Main() at first you see:
|
|
<pre class="code">Application.Init()</pre>
|
|
This initializes GTK and is needed in every GTK# Application.<br>
|
|
The next line create a new window. GTK# can set the title in the constructor and saves one line compared to C.<br>
|
|
<pre class="code">
|
|
Window window = new Window ("helloworld");
|
|
</pre>
|
|
<pre class="code">Application.Run()</pre> shows the application and most importantly keeps it open, waiting for events, until Quit() is called.
|
|
<h2>HelloWorld, second try</h2>
|
|
While the above program compiles and runs, it's doesn't quit, properly. You've to exit with CRTL+C.<br><br>
|
|
|
|
<pre class="code">
|
|
|
|
using Gtk;
|
|
using GtkSharp;
|
|
using System;
|
|
|
|
class Hello {
|
|
|
|
static void Main()
|
|
{
|
|
Application.Init ();
|
|
|
|
Window window = new Window ("helloworld");
|
|
window.DeleteEvent += new DeleteEventHandler (delete_event);
|
|
window.ShowAll ();
|
|
|
|
Button btn = new Button ("Hello World");
|
|
btn.Clicked += new EventHandler (hello);
|
|
|
|
Application.Run ();
|
|
|
|
}
|
|
|
|
|
|
static void delete_event (object obj, DeleteEventArgs args)
|
|
{
|
|
Application.Quit ();
|
|
}
|
|
|
|
static void hello (object obj, EventArgs args)
|
|
{
|
|
Console.WriteLine("Hello World");
|
|
Application.Quit ();
|
|
}
|
|
}
|
|
|
|
</pre>
|
|
This sample quits correctly.<br>
|
|
|
|
GTK is an event driven toolkit, which means it will sleep in Application.Run() until an event occurs and control is passed to the appropriate function. GTK# can make use of the type "event". When you close HelloWorld, the DeleteEvent is thrown, by the window.
|
|
To enable your application to react on the DeleteEvent, you must connect it to an event handler.
|
|
<pre class="code">
|
|
window.DeleteEvent += new DeleteEventHandler (delete_event);
|
|
</pre>
|
|
An event handler is passed an object, the object that fired the event, here window, and EventArgs. The EventArgs here have the special type DeleteEventArgs).
|
|
<pre class="code">
|
|
static void delete_event (object obj, DeleteEventArgs args)
|
|
{
|
|
Application.Quit ();
|
|
}
|
|
</pre>
|
|
This sample also adds a button to the window and connects the clicked event to "hello".
|
|
<h2>Packing Widgets (Boxes)</h2>
|
|
|
|
When creating an application, you'll want to put more than one widget inside a window. Our first helloworld example only used one widget so we could simply use a window.Add() call to "pack" the widget into the window. But when you want to put more than one widget into a window, how do you control where that widget is positioned? This is where packing comes in.<br><br>
|
|
If you come from Windows, you're probably used to position several widgets using coordinates. Also possible, that's not the way it's done in GTK#. Most packing is done by creating boxes. These are invisible widget containers that we can pack our widgets into which come in two forms, a horizontal box, and a vertical box. While this is more difficult for a newcomer it has some advantages:
|
|
<ul>
|
|
<li>Independent of screesize</li>
|
|
<li>Easier Internationalization</li>
|
|
</ul>
|
|
|
|
When packing widgets into a horizontal box, the objects are inserted horizontally from left to right or right to left depending on the call used. In a vertical box, widgets are packed from top to bottom or vice versa. You may use any combination of boxes inside or beside other boxes to create the desired effect.<br><br>
|
|
An object may be another container or a widget. In fact, many widgets are actually containers themselves, including the button, but we usually only use a label inside a button.<br><br>
|
|
|
|
By using these calls, GTK knows where you want to place your widgets so it can do automatic resizing and other nifty things. There are also a number of options as to how your widgets should be packed. As you can imagine, this method gives us a quite a bit of flexibility when placing and creating widgets.<br><br>
|
|
<br>
|
|
[TODO]
|
|
|
|
<h2>A closer look at Buttons</h2>
|
|
GTK# offers not just the normal button, but some other types, derived from it.
|
|
<h3>Using Stock Icons</h3>
|
|
Up to now, we only created Buttons containing a label. It's possible to create a
|
|
Button from Stock Icon, which is very good for consistency in Gnome apps:<br>
|
|
<br>
|
|
Common look & feel: Toolbar with 4 Stock Icons.<br>
|
|
<img src="stockicons.png" border=0>
|
|
<br>
|
|
<pre class="code">
|
|
Button stockbutton = Button.FromStock(<b>stocktype</b>);
|
|
</pre>
|
|
Gtk# offers a wide range of good-looking, well designed and accessible icons.
|
|
Anopther benfit of Stock Icons is, that they are available in many languages,
|
|
and there is no need, to translate them.
|
|
<b>stocktype</b> must be one of these values:
|
|
<pre class="code">
|
|
Gtk.Stock.Add
|
|
Gtk.Stock.Apply
|
|
Gtk.Stock.Bold
|
|
Gtk.Stock.Cancel
|
|
Gtk.Stock.Cdrom
|
|
Gtk.Stock.Clear
|
|
Gtk.Stock.Close
|
|
Gtk.Stock.Convert
|
|
Gtk.Stock.Copy
|
|
Gtk.Stock.Cut
|
|
Gtk.Stock.Delete
|
|
Gtk.Stock.DialogError
|
|
Gtk.Stock.DialogInfo
|
|
Gtk.Stock.DialogQuestion
|
|
Gtk.Stock.DialogWarning
|
|
Gtk.Stock.StockDnd
|
|
Gtk.Stock.DndMultiple
|
|
Gtk.Stock.Execute
|
|
Gtk.Stock.FIND
|
|
Gtk.Stock.FIND_AND_REPLACE
|
|
Gtk.Stock.FLOPPY
|
|
Gtk.Stock.GOTO_BOTTOM
|
|
Gtk.Stock.GOTO_FIRST
|
|
Gtk.Stock.GOTO_LAST
|
|
Gtk.Stock.GOTO_TOP
|
|
Gtk.Stock.GO_BACK
|
|
Gtk.Stock.GO_DOWN
|
|
Gtk.Stock.GO_FORWARD
|
|
Gtk.Stock.GO_UP
|
|
Gtk.Stock.HELP
|
|
Gtk.Stock.HOME
|
|
Gtk.Stock.INDEX
|
|
Gtk.Stock.ITALIC
|
|
Gtk.Stock.JUMP_TO
|
|
Gtk.Stock.JUSTIFY_CENTER
|
|
Gtk.Stock.JUSTIFY_FILL
|
|
Gtk.Stock.JUSTIFY_LEFT
|
|
Gtk.Stock.JUSTIFY_RIGHT
|
|
Gtk.Stock.MISSING_IMAGE
|
|
Gtk.Stock.NEW
|
|
Gtk.Stock.NO
|
|
Gtk.Stock.OK
|
|
Gtk.Stock.OPEN
|
|
Gtk.Stock.PASTE
|
|
Gtk.Stock.PREFERENCES
|
|
Gtk.Stock.PRINT
|
|
Gtk.Stock.PRINT_PREVIEW
|
|
Gtk.Stock.PROPERTIES
|
|
Gtk.Stock.QUIT
|
|
Gtk.Stock.REDO
|
|
Gtk.Stock.REFRESH
|
|
Gtk.Stock.REMOVE
|
|
Gtk.Stock.REVERT_TO_SAVED
|
|
Gtk.Stock.SAVE
|
|
Gtk.Stock.SAVE_AS
|
|
Gtk.Stock.SELECT_COLOR
|
|
Gtk.Stock.SELECT_FONT
|
|
Gtk.Stock.SORT_ASCENDING
|
|
Gtk.Stock.SORT_DESCENDING
|
|
Gtk.Stock.SPELL_CHECK
|
|
Gtk.Stock.STOP
|
|
Gtk.Stock.STRIKETHROUGH
|
|
Gtk.Stock.UNDELETE
|
|
Gtk.Stock.UNDERLINE
|
|
Gtk.Stock.UNDO
|
|
Gtk.Stock.YES
|
|
Gtk.Stock.ZOOM_100
|
|
Gtk.Stock.ZOOM_FIT
|
|
Gtk.Stock.ZOOM_IN
|
|
Gtk.Stock.ZOOM_OUT
|
|
|
|
|
|
|
|
</pre>
|
|
<h3>Custom Buttons</h3>
|
|
You can put pretty much everything in the button. A often used example is a button with icon and label.
|
|
<br>
|
|
[TODO]
|
|
<h3>Toggle Buttons</h3>
|
|
|
|
ToggleButtons are similiar to the normal button, but when clicked, may be depressed, and when you click again,
|
|
they will pop back up. Click again, and they will pop back down. When popped down, the Property Active has the value "true".
|
|
|
|
<pre class="code">
|
|
using Gtk;
|
|
using GtkSharp;
|
|
using System;
|
|
using System.Drawing;
|
|
|
|
public class checkbuttons
|
|
{
|
|
|
|
|
|
public static void Main(string[] args)
|
|
{
|
|
|
|
Application.Init();
|
|
|
|
|
|
Window window = new Window("toggle buttons");
|
|
|
|
window.DeleteEvent += new DeleteEventHandler (delete_event);
|
|
|
|
<b>/* Creating a new ToggleButton*/
|
|
|
|
ToggleButton togglebutton = new ToggleButton ("button1");</b>
|
|
togglebutton.Clicked += new EventHandler (clickedCallback);
|
|
|
|
|
|
window.Add(togglebutton);
|
|
window.ShowAll();
|
|
|
|
Application.Run();
|
|
|
|
}
|
|
|
|
static void delete_event (object obj, DeleteEventArgs args)
|
|
{
|
|
|
|
Application.Quit();
|
|
}
|
|
|
|
static void clickedCallback (object obj, EventArgs args)
|
|
{
|
|
<b>/* Check Active Property */</b>
|
|
|
|
if (((ToggleButton) obj).<b>Active</b>)
|
|
Console.WriteLine ("ToggleButton clicked, I'm activating");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
</pre>
|
|
|
|
|
|
<h3>Check Buttons</h3>
|
|
Check Buttons are squares with text besides them. From a programmers point of view, they work like ToggleButtons.
|
|
|
|
<pre class="code">
|
|
CheckButton cb1 = new CheckButton ("CheckButton 1");
|
|
</pre>
|
|
<h3>Radio Buttons</h3>
|
|
<br>
|
|
[TODO]: Sample needs explanation.
|
|
|
|
<pre class="code">
|
|
|
|
using Gtk;
|
|
using GtkSharp;
|
|
using System;
|
|
using System.Drawing;
|
|
|
|
|
|
public class radiobuttons
|
|
{
|
|
|
|
static GLib.SList group = null;
|
|
|
|
static void delete_event (object obj, DeleteEventArgs args)
|
|
{
|
|
Application.Quit();
|
|
}
|
|
|
|
static void exitbutton_event (object obj, EventArgs args)
|
|
{
|
|
Application.Quit();
|
|
}
|
|
|
|
public static void Main(string[] args)
|
|
{
|
|
|
|
Application.Init();
|
|
|
|
|
|
Window window = new Window("radio buttons");
|
|
|
|
window.DeleteEvent += new DeleteEventHandler (delete_event);
|
|
|
|
window.BorderWidth = 0;
|
|
|
|
VBox box1 = new VBox (false, 0);
|
|
window.Add(box1);
|
|
box1.Show();
|
|
|
|
VBox box2 = new VBox (false, 10);
|
|
box2.BorderWidth = 10;
|
|
box1.PackStart(box2, true, true, 0);
|
|
box2.Show();
|
|
|
|
RadioButton radiobutton = new RadioButton (null, "button1");
|
|
box2.PackStart(radiobutton, true, true, 0);
|
|
radiobutton.Show();
|
|
group = radiobutton.Group;
|
|
RadioButton radiobutton2 = new RadioButton(group, "button2");
|
|
radiobutton2.Active = true;
|
|
box2.PackStart(radiobutton2, true, true, 0);
|
|
radiobutton2.Show();
|
|
|
|
RadioButton radiobutton3 = RadioButton.NewWithLabelFromWidget(radiobutton, "button3");
|
|
box2.PackStart(radiobutton3, true, true, 0);
|
|
radiobutton3.Show();
|
|
|
|
HSeparator separator = new HSeparator ();
|
|
box1.PackStart (separator,false, true, 0);
|
|
separator.Show();
|
|
|
|
VBox box3 = new VBox(false, 10);
|
|
box3.BorderWidth = 10;
|
|
box1.PackStart(box3,false, true, 0);
|
|
box3.Show();
|
|
|
|
Button button = new Button ("close");
|
|
button.Clicked += new EventHandler (exitbutton_event);
|
|
|
|
box3.PackStart(button, true, true, 0);
|
|
button.CanDefault = true;
|
|
button.GrabDefault();
|
|
button.Show();
|
|
|
|
window.ShowAll();
|
|
|
|
Application.Run();
|
|
|
|
}
|
|
}
|
|
</pre>
|
|
|
|
<h2>Container Widgets</h2>
|
|
[TODO]
|
|
<h2>Miscellaneous Widgets</h2>
|
|
This section describes some often used widgets, but is not a complete reference. A more complete
|
|
listing will be available in the GTK# port of the GTK+ 2.0 tutorial or the GTK# documentation.
|
|
<h3>Labels</h3>
|
|
Creating a new Label...
|
|
<pre class="code">
|
|
Label label1 = new Label("Caption");
|
|
</pre>
|
|
A new feature makes it possible, to use simple styles in label captions. It's called GMarkup and is similiar to HTML:
|
|
<pre class="code">
|
|
Label label1 = new Label("A <span color=\"blue\">blue</span> <big>and</big> <b>bold</b> label");
|
|
</pre>
|
|
This line is rendered like that:<br><br>
|
|
<img src=label.png border=0><br><br>
|
|
The feature is possible, thanks to pango, that is discussed later.
|
|
<br><br>
|
|
The label text can be justified using:
|
|
<pre class="code">
|
|
label1.Justify = jtype;
|
|
</pre>
|
|
jtype must be a value of the Justification enumeration:
|
|
<pre class="code">
|
|
Justification.Left
|
|
Justification.Right
|
|
Justification.Center
|
|
Justification.Fill
|
|
</pre>
|
|
The label widget is also capable of line wrapping the text automatically. This can be activated using:
|
|
<pre class="code">
|
|
label1.LineWrap = true;
|
|
</pre>
|
|
The wrap argument takes a true or false value.
|
|
<br>
|
|
The text can be underlined:
|
|
<pre class="code">
|
|
label1.Pattern = "_________________________ _ _________ _ ______ __ _______ ___";
|
|
</pre>
|
|
|
|
An example application, using labels can be viewed here: <a href="label.cs">label.cs</a>
|
|
<h3>Using Tooltips</h3>
|
|
Tooltips are boxes with some text, that can be shown, when the mouse moves over a widget.
|
|
<br>
|
|
|
|
<pre class="code">
|
|
Tooltips tooltip1 = new Tooltips();
|
|
tooltip1.SetTip(button1, "Click on this button to exit", null)
|
|
</pre>
|
|
|
|
You can use the same tooltip object for all widgets. This makes sense, because you can then enable/disable all tooltips easily:
|
|
<pre class="code">
|
|
tooltip1.Enable();
|
|
tooltip1.Disable();
|
|
</pre>
|
|
<h3>Progress Bars</h3>
|
|
<br>
|
|
[TODO]
|
|
<h3>Statusbar</h3>
|
|
<br>
|
|
[TODO]
|
|
<h3>Color Selection</h3>
|
|
<br>
|
|
[TODO]
|
|
<h3>File Selection</h3>
|
|
The Gnome FileOpen/Close Dialog.
|
|
[TODO]
|
|
<h3>Font Selection</h3>
|
|
<br>
|
|
[TODO]
|
|
<h3>Message Dialog</h3>
|
|
<br>
|
|
[TODO]
|
|
<h3>Tree View</h3>
|
|
<br>
|
|
[TODO]
|
|
<h3>Text View</h3>
|
|
<br>
|
|
[TODO]
|
|
<h2>Using Drag & Drop</h2>
|
|
|
|
|
|
|
|
<h2>Widget Overview</h2>
|
|
|
|
|
|
<h3>Widget Hierarchy</h3>
|
|
Here is the class hierarchy tree used to implement widgets:
|
|
<pre class="code">
|
|
GObject
|
|
|
|
|
GtkObject
|
|
+GtkWidget
|
|
| +GtkMisc
|
|
| | +GtkLabel
|
|
| | | `GtkAccelLabel
|
|
| | +GtkArrow
|
|
| | `GtkImage
|
|
| +GtkContainer
|
|
| | +GtkBin
|
|
| | | +GtkAlignment
|
|
| | | +GtkFrame
|
|
| | | | `GtkAspectFrame
|
|
| | | +GtkButton
|
|
| | | | +GtkToggleButton
|
|
| | | | | `GtkCheckButton
|
|
| | | | | `GtkRadioButton
|
|
| | | | `GtkOptionMenu
|
|
| | | +GtkItem
|
|
| | | | +GtkMenuItem
|
|
| | | | +GtkCheckMenuItem
|
|
| | | | | `GtkRadioMenuItem
|
|
| | | | +GtkImageMenuItem
|
|
| | | | +GtkSeparatorMenuItem
|
|
| | | | `GtkTearoffMenuItem
|
|
| | | +GtkWindow
|
|
| | | | +GtkDialog
|
|
| | | | | +GtkColorSelectionDialog
|
|
| | | | | +GtkFileSelection
|
|
| | | | | +GtkFontSelectionDialog
|
|
| | | | | +GtkInputDialog
|
|
| | | | | `GtkMessageDialog
|
|
| | | | `GtkPlug
|
|
| | | +GtkEventBox
|
|
| | | +GtkHandleBox
|
|
| | | +GtkScrolledWindow
|
|
| | | `GtkViewport
|
|
| | +GtkBox
|
|
| | | +GtkButtonBox
|
|
| | | | +GtkHButtonBox
|
|
| | | | `GtkVButtonBox
|
|
| | | +GtkVBox
|
|
| | | | +GtkColorSelection
|
|
| | | | +GtkFontSelection
|
|
| | | | `GtkGammaCurve
|
|
| | | `GtkHBox
|
|
| | | +GtkCombo
|
|
| | | `GtkStatusbar
|
|
| | +GtkFixed
|
|
| | +GtkPaned
|
|
| | | +GtkHPaned
|
|
| | | `GtkVPaned
|
|
| | +GtkLayout
|
|
| | +GtkMenuShell
|
|
| | | +GtkMenuBar
|
|
| | | `GtkMenu
|
|
| | +GtkNotebook
|
|
| | +GtkSocket
|
|
| | +GtkTable
|
|
| | +GtkTextView
|
|
| | +GtkToolbar
|
|
| | `GtkTreeView
|
|
| +GtkCalendar
|
|
| +GtkDrawingArea
|
|
| | `GtkCurve
|
|
| +GtkEditable
|
|
| | +GtkEntry
|
|
| | `GtkSpinButton
|
|
| +GtkRuler
|
|
| | +GtkHRuler
|
|
| | `GtkVRuler
|
|
| +GtkRange
|
|
| | +GtkScale
|
|
| | | +GtkHScale
|
|
| | | `GtkVScale
|
|
| | `GtkScrollbar
|
|
| | +GtkHScrollbar
|
|
| | `GtkVScrollbar
|
|
| +GtkSeparator
|
|
| | +GtkHSeparator
|
|
| | `GtkVSeparator
|
|
| +GtkInvisible
|
|
| +GtkPreview
|
|
| `GtkProgressBar
|
|
+GtkAdjustment
|
|
+GtkCellRenderer
|
|
| +GtkCellRendererPixbuf
|
|
| +GtkCellRendererText
|
|
| +GtkCellRendererToggle
|
|
+GtkItemFactory
|
|
+GtkTooltips
|
|
`GtkTreeViewColumn
|
|
</pre>
|
|
</body>
|
|
</html> |