Python GTK 3 Tutorial

May 29, 2018 | Author: Warren Griffin | Category: Character Encoding, Hyperlink, String (Computer Science), Code, Callback (Computer Programming)


Comments



Description

The Python GTK+ 3 TutorialRelease 3.4 Sebastian Pölsterl February 01, 2015 Contents 1 Installation 1.1 Dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Prebuilt Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Installing From Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3 3 3 2 Getting Started 2.1 Simple Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Extended Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 5 6 3 Basics 3.1 Main loop and Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 9 10 4 How to Deal With Strings 4.1 Definitions . . . . . 4.2 Python 2 . . . . . . 4.3 Python 3 . . . . . . 4.4 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 11 11 13 13 Layout Containers 5.1 Boxes . . . . . . . . . . 5.2 Grid . . . . . . . . . . . 5.3 Table . . . . . . . . . . 5.4 ListBox . . . . . . . . . 5.5 Stack and StackSwitcher 5.6 HeaderBar . . . . . . . 5.7 FlowBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 15 16 17 18 20 21 23 6 Label 6.1 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 28 7 Entry 7.1 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 31 8 Button Widgets 8.1 Button . . . 8.2 ToggleButton 8.3 CheckButton 8.4 RadioButton 35 35 36 37 37 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . i . . . . . . . . . . .3 The Selection . . . . . . . . . . . . . . . . . . . . . . .2 The View . . . . . . 55 55 57 58 60 61 63 13 ComboBox 13. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6 8. . . . . . . 11. . . . . . . . . . . . . . . . . . . . . 43 43 10 Spinner 10. . . . . . .2 UI Manager . . . 87 87 89 91 18 Clipboard 18. . . . . . .4 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 Actions . . . . . . . . . . . . . . . . . . . . . .8. . . 17. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 CellRendererToggle . . 47 47 11 Tree and List Widgets 11. . . . . . . . . . . . . . . . . . . . . 12. . . . . . . . . . . . . . . . . . . 17. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 97 98 98 98 ii . . Switch . . . . . . . . . . . . . . . . . . . . . . .3 Tags . . . . . . . . . .4 CellRendererCombo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.1 Example . . . . . . . . . . 15. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 71 15 Multiline Text Editor 15. . . . . . . . . . . . . . . . . . . . . . . SpinButton . . . . . .3 Drag Destination Signals 19. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15. . . . . . .5 CellRendererProgress 12. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 Custom Dialogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 CellRendererText . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7 LinkButton . . .1 Target Entries . . . . . . . . . 67 67 14 IconView 14.1 The View . . . . .3 Example . . . . . . . . . . . .1 Example . . . . . . . . . 81 81 82 82 17 Dialogs 17. . . . . . . . . . .6 CellRendererSpin . . . . . . . . . . . . . . . . . . . . . . . . . 11. . . . . . . . . . . . . . . . . . . . .1 The Model . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 Sorting . . . . . . . . . . . . . . . . . . 11. . . . . . .3 CellRendererPixbuf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 The Model . . . . . . . . . . 12. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5 8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 49 51 51 52 12 CellRenderers 12. . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16. . . . . . . . . . . . . . . . . . . . . . 16. . . . . .1 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 39 40 ProgressBar 9. . . . . . . . . . . . . . . . 19. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12. . . . . . . . . . . . . . . . 19. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 73 73 74 75 16 Menus 16. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12. . . . . . .1 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 MessageDialog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 FileChooserDialog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 . .2 Drag Source Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 95 19 Drag and Drop 19. . . . . . . . . . . . . . . . . . . .1 Inherit from GObject. . . . . . . . . 101 101 102 102 103 21 Objects 21.1 Creating and loading the . . . . . . . . . . . . . . . . . . . . . .3 Properties . . . . . . . . . . . .2 Accessing widgets . . . . . . . . . .GObject 21. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 Connecting Signals . . . . . . . . . . . . . 20. .glade file 20. . . . . . . . . . . . . . . . . . . . .20 Glade and Gtk. . . . . . . . . . . . . .4 API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Builder 20. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.4 Example . . . . . . . . .2 Signals . . . . . . . . . . . . . . 22 Stock Items 111 23 Indices and tables 121 iii . 21. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 105 105 106 108 . . . . . . . . . . iv . it is not supposed to serve as an API reference. 2015 Copyright GNU Free Documentation License 1. it is recommended that you have a reasonable grasp of the Python programming language. It is necessary for you to know how to create and run Python files. Contents: Contents 1 . and work with strings. floats and Boolean values. Prior to working through this tutorial.The Python GTK+ 3 Tutorial. integers. and no Back-Cover Texts This tutorial gives an introduction to writing GTK+ 3 applications in Python. Release 3. For the more advanced widgets in this tutorial. Please refer to the GTK+ 3 Reference Manual for a detailed description of the API.4 Release 3. Although this tutorial describes the most important classes and methods within GTK+ 3. good knowledge of lists and tuples will be needed. no Front-Cover Texts.3 with no Invariant Sections.4 Date February 01. understand basic interpreter errors. GUI programming introduces new problems compared to interacting with the standard output (console / terminal). 4 2 Contents .The Python GTK+ 3 Tutorial. Release 3. Executing the following command will build PyGObject and all its dependencies: 1 http://download. download the latest configuration from 1 . Once you have installed JHBuild successfully. If you have not done it before.6 or later) or Python 3 (3. It is designed to easily build source packages and discover what dependencies need to be build and in what order. You should install those using your distribution’s package repository.modules to JHBuild’s module directory and the file sample-tarball.org/teams/releng/ 3 . if you use Linux. Run the command above again to ensure the required tools are present. you can probably get started by installing the package from the official repository for your distribution.2 Prebuilt Packages Recent versions of PyGObject and its dependencies are packaged by nearly all major Linux distributions. It exclusively supports GTK+ version 3 or later.jhbuildrc to ~/.jhbuildrc.gnome. To setup JHBuild. verify that your build environment is setup correctly by running: $ jhbuild sanitycheck It will print any applications and libraries that are currently missing on your system but required for building.CHAPTER 1 Installation The first step before we start with actual coding consists of setting up PyGObject and its dependencies. 1. PyGObject is a Python module that enables developers to access GObject-based libraries such as GTK+ within Python.3 Installing From Source The easiest way to install PyGObject from source is using JHBuild.1 or later) • gobject-introspection 1. 1. use PyGTK.1 Dependencies • GTK+3 • Python 2 (2. please follow the JHBuild manual. A list of package names for different distributions is maintained on the GNOME wiki. So. instead. If you want to use GTK+ 2 in your application. Copy files with the suffix . Installation . you might want to install GTK+ from source as well: $ jhbuild build gtk+ To start a shell with the same environment as used by JHBuild.The Python GTK+ 3 Tutorial. run: $ jhbuild shell 4 Chapter 1.4 $ jhbuild build pygobject Finally. Release 3. 5 .repository import Gtk 3 4 5 6 7 win = Gtk.show_all() Gtk.main() We will now explain each line of the example.Window() win. #!/usr/bin/python The first line of all Python programs should start with #! followed by the path to the Python interpreter you want to invoke. 1 2 #!/usr/bin/python from gi. Gtk.1 Simple Example To start with our tutorial we create the simplest program possible.connect("delete-event".CHAPTER 2 Getting Started 2.main_quit) win. This program will create an empty 200 x 200 pixel window. Button(label="Click Here") self.Window to define our own MyWindow class.connect("delete-event". title="Hello World") 6 7 8 self. self. 1 2 #!/usr/bin/python from gi. Gtk.py 2.main() To run the program. Gtk.Window() Followed by connecting to the window’s delete event to ensure that the application is terminated if we click on the x to close the window. widget): print("Hello World") 13 14 15 16 17 18 19 win = MyWindow() win. Getting Started .show_all() Finally. open a terminal. and enter: python simple_example. Release 3. change to the directory of the file. 6 Chapter 2.main_quit) win. Gtk.show_all() Gtk.repository import Gtk In order to access GTK+ classes and functions we first must import the Gtk module.button) 9 10 11 12 def on_button_clicked(self.button.repository import Gtk 3 4 class MyWindow(Gtk. The next line creates an empty window.__init__(self.Window. win.on_button_clicked) self.button = Gtk. win = Gtk.add(self. here’s the PyGObject version of the classic “Hello World” program. win.2 Extended Example For something a little more useful.connect("delete-event".main_quit) In the next step we display the window.connect("clicked".4 from gi.Window): 5 def __init__(self): Gtk.main() This example differs from the simple example as we sub-class Gtk.The Python GTK+ 3 Tutorial. we start the GTK+ processing loop which we quit when the window is closed (see line 5). Window): In the class’s constructor we have to call the constructor of the super class. self.add(self.on_button_clicked) self. we create an instance of MyWindow. is very similar to the simple example above. outside of the class.Window class.4 class MyWindow(Gtk.2.connect("clicked".button) Accordingly. In addition. def on_button_clicked(self. Release 3. self. Gtk. widget): print("Hello World") The last block.Button(label="Click Here") self. but instead of creating an instance of the generic Gtk.button = Gtk.__init__(self. connect to its clicked signal and add it as child to the top-level window.The Python GTK+ 3 Tutorial.button. 2.Window. Extended Example 7 . title="Hello World") The next three lines are used to create a button widget. the method on_button_clicked() will be called if you click on the button. we tell it to set the value of the property title to Hello World. The Python GTK+ 3 Tutorial.4 8 Chapter 2. Release 3. Getting Started . widget. After a callback finishes. if you have a button you usually want to connect to the “clicked” event.say. It is emitted if a user requests that a toplevel window is closed. The default handler for this signal destroys the window. this argument is completely optional and can be left out if not required. callback. When your callbacks are invoked.main_quit() will result in the desired behaviour.disconnect_by_func(callback) Almost all applications will connect to the “delete-event” signal of the top-level window. The function returns a number that identifies this particular signal-callback pair. you can still disconnect a specific callback using the function disconnect_by_func(): widget. Such functions are commonly known as callbacks. Connecting the “delete-event” signal to the function Gtk. when an Open button is clicked you might display a file chooser dialog. This means that when the button is clicked. the data argument includes any data which should be passed when the signal is issued. widget is an instance of a widget we created earlier. you would typically take some action . data) Firstly. 3. Each widget has its own particular events which can occur. the event we are interested in. GTK+ sits in the main loop and waits for input. Thirdly. When the user is doing nothing.for example. GTK+ will return to the main loop and await more user input. 9 . For instance.CHAPTER 3 Basics This section will introduce some of the most important aspects of GTK+.connect_signals()). Signals notify your program that “something interesting happened” by invoking functions you’ve connected to the signal.1 Main loop and Signals Like most GUI toolkits. It is required to disconnect from a signal such that the callback function will not be called during any future or currently ongoing emissions of the signal it has been connected to. the callback argument is the name of the callback function. the signal is issued. If the user performs some action . Next.Builder. but does not terminate the application.connect("event". a mouse click . GTK+ uses an event-driven programming model. It contains the code which runs when signals of the specified type are issued.then the main loop “wakes up” and delivers an event to GTK+. However.disconnect(handler_id) If you have lost the “handler_id” for some reason (for example the handlers were installed using Gtk. Finally. When widgets receive an event. A generic example is: handler_id = widget. they frequently emit one or more signals. get_property("prop-name") respectively.set_property("prop-name". 10 Chapter 3.4 window. each widget has its own particular set of properties.main_quit) Calling Gtk. To see which properties are available for a widget in the running version of GTK you can “dir” the “props” property: widget = Gtk. 3. Release 3. As for signals. value). To create a label aligned to the right with the text “Hello World” and an angle of 25 degrees. You can specify the name and value of any number of properties as keyword arguments when creating an instance of a widget.set_halign(Gtk.connect("delete-event". Basics .Align.END) which is equivalent to label = Gtk. For example.main_quit() makes the main loop inside of Gtk. halign=Gtk. a button has the property “label” which contains the text of the label widget inside the button. angle=25. use: label = Gtk.Box() print(dir(widget.set_angle(25) label.END) Instead of using getters and setters widget.main() return. Gtk.set_label("Hello World") label.The Python GTK+ 3 Tutorial.Label() label.2 Properties Properties describe the configuration and state of widgets.Box has.props)) This will print in the console the list of properties a Gtk.Label(label="Hello World".Align. you and can also get and set the properties with widget. Instances of the latter are used to express Unicode strings. If the code point is < 128. code points are numbers in the range from 0 to 0x10FFFF. each byte is the same as the value of the code point. Characters are abstract representations and their meaning depends on the language and context they are used in. If the code point is 128 or greater.x and GTK+ and discusses common errors that arise when working with strings. and the ‘8’ means that 8-bit numbers are used in the encoding.or 32-bit integers. The Unicode standard describes how characters are represented by code points.2.2 Python 2 4. One of the most commonly used encodings that addresses this problem is UTF-8 (it can handle any Unicode code point). For example the characters above are represented with the code points U+0041. Under the hood. a string is a list of characters such as ‘A’. UTF stands for “Unicode Transformation Format”. 4. As mentioned earlier. the Unicode string can’t be represented in this encoding.CHAPTER 4 How to Deal With Strings This section explains how strings are represented in Python 2. whereas instances of the str type are byte representations (the encoded string). 2.1 Python 2. ‘B’. depending on how the Python interpreter was compiled. and U+00C9. 4. In order to convert this abstract representation into a sequence of bytes the Unicode string must be encoded. Python represents Unicode strings as either 16. Python 3. U+0042. ‘C’ or ‘É’.) Although ASCII encoding is simple to apply it can only encode for 128 different characters which is hardly enough.1 Definitions Conceptionally. U+0043. (Python raises a UnicodeEncodeError exception in this case. The simplest from of encoding is ASCII and is performed as follows: 1.x. Unicode strings can be converted to 8-bit strings with unicode. str and unicode.x’s Unicode Support Python 2 comes with two different kinds of objects that can be used to represent strings. Basically.encode(): >>> unicode_string = u"Fu\u00dfb\u00e4lle" >>> print unicode_string Fußbälle >>> type(unicode_string) <type ’unicode’> 11 . respectively. the representation of a string as a list of code points is abstract. Release 3.get_text() will always return a str instance. This means that if you call a method that returns a string you will always obtain an instance of the str type.2 Unicode in GTK+ GTK+ uses UTF-8 encoded strings for all text. Although we called Gtk. txt and unicode_string are not equal.set_text() with a unicode instance as argument. However. in <module> UnicodeDecodeError: ’ascii’ codec can’t decode byte 0xc3 in position 2: 4. line 1.encode("utf-8") >>> type(utf8_string) <type ’str’> >>> u2 = utf8_string. Gtk.encode("utf-8") ’Fu\xc3\x9fb\xc3\xa4lle’ Python’s 8-bit strings have a str. The same applies to methods that expect one or more strings as parameter.4 >>> unicode_string.Label. they must be UTF-8 encoded.x allows you to mix unicode and str if the 8-bit string happened to contain only 7-bit (ASCII) bytes. for convenience PyGObject will automatically convert any unicode instance to str if supplied as argument: >>> from gi. In general it is recommended to not use unicode objects in GTK+ applications at all and only use UTF-8 encoded str objects since GTK+ does not fully integrate with unicode objects.2. txt (<type ’str’>.Label. How to Deal With Strings .Label() >>> unicode_string = u"Fu\u00dfb\u00e4lle" >>> label. Otherwise. Python 2.repository import Gtk >>> label = Gtk.set_text(unicode_string) >>> txt = label.decode("utf-8") >>> unicode_string == u2 True Unfortunately. but would get UnicodeDecodeError if it contained non-ASCII values: >>> utf8_string = " sind rund" >>> unicode_string + utf8_string u’Fu\xdfb\xe4lle sind rund’ >>> utf8_string = " k\xc3\xb6nnten rund sein" >>> print utf8_string könnten rund sein >>> unicode_string + utf8_string Traceback (most recent call last): File "<stdin>". ’Fu\xc3\x9fb\xc3\xa4lle’) >>> txt == unicode_string __main__:1: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode . in <module> UnicodeDecodeError: ’ascii’ codec can’t decode byte 0xc3 in position 2: ordinal not in range(128) Traceback (most recent call last): File "<stdin>". Accordingly. You have to make sure that gettext will return UTF-8 encoded 8-bit strings for all languages.The Python GTK+ 3 Tutorial.get_text() >>> type(txt).decode() method that interprets the string using the given encoding: >>> utf8_string = unicode_string. you would have to decode the return values to Unicode strings each time you call a GTK+ method: 12 Chapter 4.interpreting them as being unequal False Note the warning at the end. This is especially important if you want to internationalize your program using gettext. line 1. 3.0.set_text(text) >>> txt = label. str refers to text.decode("utf-8") >>> txt == unicode_string True 4.encode() to go from str to bytes. in <module> TypeError: Can’t convert ’bytes’ object to str implicitly >>> text + data. line 1.get_text() >>> type(txt). because it will result in a TypeError: >>> text = "Fu\u00dfb\u00e4lle" >>> data = b" sind rund" >>> text + data Traceback (most recent call last): File "<stdin>".4 >>> txt = label. Encoded strings on the other hand are represented as binary data in the form of instances of the bytes type.get_text(). all strings are stored as Unicode in an instance of the str type. txt (<class ’str’>. things are much cleaner and consistent with Python 3. because PyGObject will automatically encode/decode to/from UTF-8 if you pass a string to a method or a method returns a string.x’s Unicode support Since Python 3. and explains various problems that people commonly encounter when trying to work with Unicode. Use str. 4.3.1 Python 3.Label() >>> text = "Fu\u00dfb\u00e4lle" >>> label.x’s support for Unicode. or text. Python 3 13 .repository import Gtk >>> label = Gtk.2 Unicode in GTK+ As a consequence.The Python GTK+ 3 Tutorial.0 describes the new concepts that clearly distinguish between text and data. whereas bytes refers to data. Strings. The Unicode HOWTO discusses Python 2.3. ’Fußbälle’) >>> txt == text True 4.encode("utf-8") + data b’Fu\xc3\x9fb\xc3\xa4lle sind rund’ Traceback (most recent call last): File "<stdin>". Release 3.decode("utf-8") ’Fußbälle sind rund’ >>> text.x. in <module> TypeError: Can’t convert ’bytes’ object to str implicitly 4.3 Python 3 4. Conceptionally.decode() to go from bytes to str. it is no longer possible to mix Unicode strings with encoded strings. In addition. line 1.4 References What’s new in Python 3. and bytes. will always be represented as instances of str only: >>> from gi. x.4 The Unicode HOWTO for Python 3. How to Deal With Strings . 14 Chapter 4. Release 3. UTF-8 encoding table and Unicode characters contains a list of Unicode code points and their respective UTF-8 encoding.x discusses Unicode support in Python 3.The Python GTK+ 3 Tutorial. the objects are inserted horizontally from left to right or right to left depending on whether Gtk.CHAPTER 5 Layout Containers While many GUI toolkits require you to precisely place widgets in a window. The most commonly used are vertical or horizontal boxes (Gtk. columns. You may use any combination of boxes inside or beside other boxes to create the desired effect. Rather than specifying the position and size of each widget in the window. 1 from gi. or placed within each other to layout components. 5.Box. They are invisible to the end user and are inserted into a window. which are descendants of Gtk. When packing widgets into a horizontal box. in turn.Container. There are two flavours of containers: single-child containers.Box.Window): 4 5 6 def __init__(self): Gtk. and/or how you have requested that the available space should be shared between sets of widgets. which are all descendants of Gtk. determined by the amount of text they contain. GTK+ arranges widgets hierarchically. You can perfect your layout by specifying padding distance and centering values for each of your widgets. The size of your window can be determined automatically.pack_end() is used.__init__(self.Window.1 Example Let’s take a look at a slightly modified version of the extended example with two buttons.1 Boxes Boxes are invisible containers into which we can pack our widgets. using absolute positioning. or the minimum and maximum sizes that you specify.pack_start() or Gtk. title="Hello World") 15 .1.Box).Table) and grids (Gtk. widgets are packed from top to bottom or vice versa. using containers. you can arrange your widgets in rows. In a vertical box. And the sizes of the widgets are. 5.Grid). based on the sizes of the widgets it contains. and/or tables.repository import Gtk 2 3 class MyWindow(Gtk.Bin. GTK+ uses a different approach. GTK+ then uses all this information to resize and reposition everything sensibly and smoothly when the user manipulates the window. and multiple-child containers. tables (Gtk. attach().Grid.button1 = Gtk.add(self. self. Release 3. 5. we add two different buttons to the box container. using Gtk. 0) self. 16 Chapter 5.button1.box = Gtk.main() First. True.box = Gtk. self.Button(label="Goodbye") self. True.pack_start(self.Box(spacing=6) self.box.on_button2_clicked) self.Grid. Gtk.Box by just using Gtk.button2. True. They can span multiple rows or columns. self.The Python GTK+ 3 Tutorial.button2.Box(spacing=6) self. Children are added using Gtk.attach_next_to().on_button1_clicked) self.Orientation. Gtk.box.on_button1_clicked) self. 0) 15 16 17 18 def on_button1_clicked(self.HORIZONTAL).Button(label="Hello") self.box) 8 9 10 self.button1. This box becomes the child of the top-level window.pack_start() widgets are positioned from left to right.Grid can be used like a Gtk. 0) While with Gtk.box) Subsequently.add(self.2 Grid Gtk.Button(label="Hello") self.button1. but you do not need to specify the dimensions in the constructor.pack_end() positions them from right to left. Gtk.4 7 self.button2 = Gtk.pack_start(self.box.button2 = Gtk.connect("clicked".add().button2. self.button1.pack_start(self. widget): print("Hello") 19 20 21 def on_button2_clicked(self. True. True.button1 = Gtk. we create a horizontally orientated box container where 6 pixels are placed between children.box. It is also possible to add a child next to an existing child. widget): print("Goodbye") 22 23 24 25 26 27 28 win = MyWindow() win.connect("delete-event". True. 0) 11 12 13 14 self. True. self. Layout Containers .Box. self.Grid is a container which arranges its child widgets in rows and columns.pack_start(self.on_button2_clicked) self. True.connect("clicked".connect("clicked".Box.connect("clicked".main_quit) win.show_all() Gtk. which will place children next to each other in the direction determined by the “orientation” property (defaults to Gtk.Button(label="Goodbye") self.button2.Grid. add(grid) 10 11 12 13 14 15 16 button1 button2 button3 button4 button5 button6 = = = = = = Gtk.1 Example 1 from gi.3.RIGHT. button3.PositionType.Button(label="Button Gtk. 1) grid.4 5.attach(button5.Window): 4 5 6 def __init__(self): Gtk.repository import Gtk 2 3 class GridWindow(Gtk. You can also set a consistent spacing for all rows and/or columns with Gtk.__init__(self. use Gtk. Gtk.2.Button(label="Button 1") 2") 3") 4") 5") 6") 17 18 19 20 21 22 23 grid. 2) grid. Gtk.set_row_spacings() and 5. button1.main_quit) win. Note that for columns. the space goes below the row. 2. and for rows.set_row_spacing() and Gtk. 1.Button(label="Button Gtk.Table constructor. The grid’s dimensions need to be specified in the Gtk.Table.Button(label="Button Gtk.Table.main() 5.attach_next_to(button6. Release 3.add(button1) grid. 1. 1. button5.connect("delete-event". Gtk.Button(label="Button Gtk.attach(button2. 1) 24 25 26 27 28 win = GridWindow() win.attach().attach_next_to(button4.Grid. Table 17 .PositionType. title="Grid Example") 7 8 9 grid = Gtk.RIGHT.Window.Table.set_col_spacing() set the spacing between the rows at the specified row or column.BOTTOM.attach_next_to(button3.Table. 1. 1) grid.3 Table Tables allows us to place widgets in a grid similar to Gtk. Gtk.show_all() Gtk. Gtk. the space goes to the right of the column.Button(label="Button Gtk. 2.Grid() self. 1. 2.The Python GTK+ 3 Tutorial. 1) grid. To place a widget into a box. 0.PositionType. 0.4 ListBox A Gtk. Release 3.attach(button5.show_all() Gtk.3. table.main() 5. True) self.Button(label="Button 1") 2") 3") 4") 5") 6") 17 table. Layout Containers .ListBoxRow children.set_col_spacings(). 1.connect("delete-event".1 Example 1 from gi. Gtk. 2. the last row and last column do not get any spacing. 1.attach(button4. 1. 1) 1) 3) 2) 3) 3) 24 25 26 27 28 win = TableWindow() win.main_quit) win.Window): 4 def __init__(self): Gtk. 1.Button(label="Button Gtk. 0.Button(label="Button Gtk. 1.4 Gtk. 1. It also allows keyboard and mouse navigation and selection like a typical list.The Python GTK+ 3 Tutorial. 0. 5.add(table) 8 9 10 button1 button2 button3 button4 button5 button6 11 12 13 14 15 16 = = = = = = Gtk. 2.attach(button3. table.repository import Gtk 2 3 class TableWindow(Gtk. 2.Table.attach(button1.attach(button2. table.attach(button6.Button(label="Button Gtk.ListBox is a vertical container that contains Gtk.Button(label="Button Gtk. 1. table. title="Table Example") 5 6 7 table = Gtk. Note that with these calls.Button(label="Button Gtk.Table(3. table. 18 Chapter 5.Window. 3. 2. 3. These rows can by dynamically sorted and filtered. 3. and headers can be added dynamically depending on the row content. 3.__init__(self. 18 19 20 21 22 23 0. Window): 4 5 6 7 def __init__(self): Gtk.Window.VERTICAL) hbox. 0) 26 27 28 29 switch = Gtk.The Python GTK+ 3 Tutorial.Container.pack_start(listbox.pack_start(switch. ListBox 19 .add(hbox) vbox = Gtk.ListBox() listbox.SelectionMode. True.Box(orientation=Gtk. 0) 15 16 17 18 19 20 row = Gtk. 0) 21 22 23 24 25 label1 = Gtk.CENTER hbox.ListBox is often an alternative to Gtk. True. spacing=50) row. True. or when the contents is interactive (i.pack_start(label1. and a Gtk. Although a Gtk. True. xalign=0) vbox.NONE) hbox.4 Using Gtk.CellRenderer.HORIZONTAL.Label("Automatic Date & Time". True. 0) vbox.Box(spacing=6) self. xalign=0) label2 = Gtk.Orientation.add(hbox) 11 12 13 14 listbox = Gtk.repository import Gtk 2 3 class ListBoxWindow(Gtk.Switch() switch. Release 3. especially when the list contents has a more complicated layout than what is allowed by a Gtk.pack_start(vbox. 0) 30 31 listbox.Orientation.__init__(self.valign = Gtk.add(row) 32 5.props.ListBoxRow() hbox = Gtk.add().4. True. True.set_selection_mode(Gtk.4. title="ListBox Demo") self.ListBox must have only Gtk. has a button in it). 5. False. True.Align.pack_start(label2.set_border_width(10) 8 9 10 hbox = Gtk. True.Label("Requires internet access".Box(orientation=Gtk.e.ListBoxRow children you can add any kind of widget to it via Gtk.ListBoxRow widget will automatically be inserted between the list and the widget.TreeView.1 Example 1 from gi. ListBoxRow() hbox = Gtk.Orientation.add(row) 41 42 row = Gtk.Label("Enable Automatic Update". False. Instead. "24-hour") combo.Box(orientation=Gtk. In contrast to Gtk. It is possible to associate multiple Gtk. 20 Chapter 5.The Python GTK+ 3 Tutorial. True.pack_start(label. True.Label("Date Format".pack_start(combo.main() 5.Stack is a container which only shows one of its children at a time. spacing=50) row. 0) 43 44 45 46 47 48 49 50 51 52 listbox. "0".add(hbox) label = Gtk. 0) hbox. Layout Containers .pack_start(label. Transition speed can be adjusted with Gtk. 0) 33 34 35 36 37 38 39 40 listbox. xalign=0) combo = Gtk.HORIZONTAL. Gtk. True.Stack to provide this functionality.connect("delete-event".Stack.CheckButton() hbox.set_transition_duration() The Gtk.pack_start(check.Stack.Stack does not provide a means for users to change the visible child.Stack widget. 0) hbox. the Gtk. spacing=50) row.4 row = Gtk. This can be controlled with Gtk.show_all() Gtk. True. Gtk. True. False.main_quit) win.insert(0. it shows a row of buttons to switch between the various pages of the associated stack widget.insert(1.ComboBoxText() combo.StackSwitcher widgets with the same Gtk.set_transition_type(). These animations respect the “gtk-enable-animations” setting. True.add(hbox) label = Gtk. All the content for the buttons comes from the child properties of the Gtk.Stack.5 Stack and StackSwitcher A Gtk. "AM/PM") hbox.Notebook.ListBoxRow() hbox = Gtk. "1".Orientation.Stack.StackSwitcher widget acts as a controller for a Gtk. Release 3. Transitions between pages can be animated as slides or fades.Box(orientation=Gtk.StackSwitcher widget can be used with Gtk. xalign=0) check = Gtk.HORIZONTAL.add(row) 53 54 55 56 57 58 59 win = ListBoxWindow() win. spacing=6) self.5. 0) 27 28 29 30 31 win = StackWindow() win.main() 5.1 Example 1 from gi. it allows a title to be displayed. title="Stack Demo") self.Box(orientation=Gtk. The title will be centered with respect to the width of the box.Window): 4 5 6 7 def __init__(self): Gtk.StackSwitcher() stack_switcher.StackTransitionType. True.Box.set_markup("<big>A fancy label</big>") stack.CheckButton("Click me!") stack.6 HeaderBar A Gtk. In addition.connect("delete-event".Orientation. Gtk.show_all() Gtk.SLIDE_LEFT_RIGHT) stack. 0) vbox. A Gtk. True. a Gtk.add(vbox) 11 12 13 14 stack = Gtk.main_quit) win. "check".pack_start(stack_switcher.Label() label. Release 3.set_transition_duration(1000) 15 16 17 checkbutton = Gtk.HeaderBar is usually located across the top of a window and should contain commonly used controls which 5. HeaderBar 21 . True.Stack() stack. even if the children at either side take up different amounts of space. it allows to place children at the start or the end. "Check Button") 18 19 20 21 label = Gtk. Since GTK+ now supports Client Side Decoration.add_titled(label.set_stack(stack) vbox.4 5. "label".6.HeaderBar can be used in place of the title bar (which is rendered by the Window Manager).add_titled(checkbutton.set_transition_type(Gtk. True. "A label") 22 23 24 25 26 stack_switcher = Gtk.The Python GTK+ 3 Tutorial.repository import Gtk 2 3 class StackWindow(Gtk.__init__(self.pack_start(stack.VERTICAL.HeaderBar is similar to a horizontal Gtk.set_border_width(10) 8 9 10 vbox = Gtk.Window. 5.1 Example 1 from gi. title="Stack Demo") self.TextView()) 34 35 22 Chapter 5.add(Gtk. including the close window button and window menu. Release 3.Button() button.add(Gtk.Arrow(Gtk.set_titlebar(hb) 10 11 12 13 14 button = Gtk.pack_start(box) 32 33 self. Gtk.repository import Gtk.HORIZONTAL) Gtk.pack_end(button) 15 16 17 18 19 20 box = Gtk.add(button) 28 29 30 31 hb.Orientation.6.StyleContext.Arrow(Gtk.ShadowType.__init__(self.IconSize.ArrowType.NONE)) box.Image.The Python GTK+ 3 Tutorial. Gtk. Gio 2 3 class HeaderBarWindow(Gtk.add(image) hb. 200) 5 6 7 8 9 hb = Gtk.Box(orientation=Gtk.set_default_size(400.HeaderBar() hb.Button() button.set_show_close_button(True) hb.set_border_width(10) self.Window): 4 def __init__(self): Gtk.add_class(box.title = "HeaderBar example" self.add(Gtk.add(button) 24 25 26 27 button = Gtk.new_from_gicon(icon.RIGHT.LEFT.ArrowType.ThemedIcon(name="mail-send-receive-symbolic") image = Gtk. Layout Containers .ShadowType.props.BUTTON) button. Gtk.Button() icon = Gio.4 affect the content below. They also provide access to window controls.get_style_context().Window.NONE)) box. "linked") 21 22 23 button = Gtk. Although a Gtk. the widgets will be arranged from top to bottom.FlowBoxChild children.Window. Reducing the height will require more columns. FlowBox 23 . Gdk 2 3 class FlowBoxWindow(Gtk. with the horizontal orientation. starting a new row under the previous row when necessary.show_all() Gtk.7 FlowBox A Gtk. so a larger width will be requested.4 36 37 38 39 win = HeaderBarWindow() win.FlowBox must have only Gtk. The children of a Gtk.main() 5.props. so a larger height will be requested. Release 3.show_close_button = True 5.add(). you can add any kind of widget to it via Gtk. Reducing the width in this case will require more rows. the widgets will be arranged from left to right.FlowBox is a container that positions child widgets in sequence according to its orientation. Likewise.set_subtitle("Sample FlowBox app") header. 250) 9 10 11 12 header = Gtk. starting a new column to the right when necessary.repository import Gtk.FlowBox can be dynamically sorted and filtered.The Python GTK+ 3 Tutorial.set_default_size(300. and a Gtk.FlowBoxChild widget will automatically be inserted between the box and the widget.connect("delete-event".__init__(self.set_border_width(10) self.7. title="ListBox Demo") self. Gtk. with the vertical orientation.Window): 4 5 6 7 8 def __init__(self): Gtk. For instance.7.1 Example 1 from gi.HeaderBar(title="Flow Box") header.main_quit) win.Container. 5. ’AntiqueWhite’.add(area) 41 42 return button 43 44 def create_flowbox(self.RGBA.set_selection_mode(Gtk. ’AntiqueWhite4’.set_max_children_per_line(30) flowbox. 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 24 Chapter 5.add(flowbox) 26 27 self. ’AntiqueWhite1’.from_color(color) button = Gtk. str_color): color = Gdk.show_all() 28 29 30 def color_swatch_new(self. ’aquamarine2’.NONE) 19 20 21 22 23 self. ’aquamarine4’. ’azure’. ’aqua’.FlowBox() flowbox. ’aquamarine1’.color_parse(str_color) 31 32 33 rgba = Gdk.ScrolledWindow() scrolled. ’aquamarine’.override_background_color(0. ’AntiqueWhite2’.PolicyType. Release 3. ’black’. ’azure4’.set_policy(Gtk.add(scrolled) self.DrawingArea() area.PolicyType. ’AntiqueWhite3’.AUTOMATIC) 16 17 18 flowbox = Gtk.set_titlebar(header) 14 15 scrolled = Gtk. ’azure3’. ’azure1’. rgba) 37 38 39 40 button.Align.The Python GTK+ 3 Tutorial. ’bisque2’.SelectionMode.set_size_request(24.4 13 self. ’bisque’.Button() 34 35 36 area = Gtk. ’bisque1’. Gtk. Layout Containers . 24) area. ’azure2’.set_valign(Gtk. ’bisque4’.create_flowbox(flowbox) 24 25 scrolled. flowbox): colors = [ ’AliceBlue’. ’aquamarine3’.NEVER. ’bisque3’.START) flowbox. ’beige’. ’chocolate’. ’BlueViolet’. ’chartreuse1’.7.connect("delete-event". ’blue3’. ’burlywood1’. ’chartreuse2’. ’brown2’. ’CadetBlue3’. ’burlywood’. ’coral3’. ’chocolate3’. ’coral1’.4 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 ’BlanchedAlmond’. FlowBox 25 . ’burlywood3’. ’chocolate4’.main() 5. ’CadetBlue1’. Gtk. ’coral2’. ’brown3’. ’burlywood2’. ’blue’. ’brown’. ’chocolate1’.color_swatch_new(color) flowbox. ’brown4’. ’CadetBlue’. ’chartreuse4’. ’coral’. ’burlywood4’.add(button) 113 114 115 116 117 118 win = FlowBoxWindow() win. ’blue4’. Release 3.The Python GTK+ 3 Tutorial. ’coral4’ ] 109 110 111 112 for color in colors: button = self. ’blue1’. ’CadetBlue2’. ’chocolate2’.show_all() Gtk. ’CadetBlue4’. ’blue2’. ’chartreuse3’. ’brown1’.main_quit) win. ’chartreuse’. Layout Containers .The Python GTK+ 3 Tutorial. Release 3.4 26 Chapter 5. set_markup() methods. such as a Gtk.Label.Label. or larger. The title attribute is displayed as a tooltip on the link. You can produce multi-line labels by putting line breaks (“\n”) in the label string.set_markup("Go to <a href=\"http://www. such as “_File”. Mnemonics automatically activate any activatable widget the label is inside. for instance allowing you to make some text bold.set_line_wrap().Label.Label.set_selectable().set_markup(). For instance. Labels can be made selectable with Gtk. which can be activated with Gtk.set_text_with_mnemonic().Label. GTK+ renders links similar to the way they appear in web browsers. 1 Pango Markup Syntax.new_with_mnemonic() or Gtk. You can do this by providing a string to Gtk. underlined text. Gtk. The widget is also capable of word-wrapping. or later with the Gtk.html 27 .org\" " "title=\"Our website\">GTK+ website</a> for more") Labels may contain mnemonics.Entry widget. if the label is not inside the mnemonic’s target widget. label.CHAPTER 6 Label Labels are the main method of placing non-editable text in windows.Label.Label. colored. <b>bold text</b> and <s>strikethrough text</s>. The width of the label will be adjusted automatically.Label supports clickable hyperlinks. to the functions Gtk. using the a with href and title attributes. http://developer.gtk.set_mnemonic_widget().set_justify() method. used for keyboard navigation. Only labels that contain useful-to-copy information — such as error messages — should be made selectable.org/pango/stable/PangoMarkupFormat. In addition. you have to tell the label about the target using Gtk. The markup for links is borrowed from HTML.Label.set_text() or Gtk. with colored. You can specify the text in the constructor.Label. for instance to place a title next to a Gtk. The label text can be justified using the Gtk. Mnemonics are underlined characters in the label. using the Pango Markup syntax 1 .Button. Mnemonics are created by providing a string with an underscore before the mnemonic character. Selectable labels allow the user to copy the label contents to the clipboard.gnome.Label support some simple formatting. Gtk. Release 3.Box(spacing=10) 8 28 Chapter 6.Window): 4 def __init__(self): Gtk.repository import Gtk 2 3 class LabelWindow(Gtk.__init__(self.1 Example 1 from gi.Window. title="Label Example") 5 6 7 hbox = Gtk.The Python GTK+ 3 Tutorial. Label .4 6. pack_start(vbox_right. 0) label. filled label. True.set_justify(Gtk.Label() label. True.set_homogeneous(False) 14 15 16 hbox.pack_start(label. better " "paragraph. True. It is coming to an end.4 9 10 11 12 13 hbox.VERTICAL. It " "should not be taking up the entire " "width allocated to it.\n" " This is a new paragraph. " "<b>bold</b>. True. True. 0) hbox.Justification.pack_start(vbox_left. Example 29 .") label.set_selectable(True) 6.pack_start(label.") label.new_with_mnemonic( "_Press Alt + P to select button to the right") vbox_left. True. ") label.\nWith multiple lines.The Python GTK+ 3 Tutorial. <big>big</big>. 0) 62 63 64 65 66 label = Gtk. " "and correctly adds " "many extra spaces.LEFT) vbox_left. 0) 54 55 56 57 58 59 60 61 label = Gtk. Release 3.Label( "This is a right-justified label.set_homogeneous(False) vbox_left = Gtk.Label() label. True.Label("This is an example of a line-wrapped. True. " "It should be taking " "up the entire width allocated to it. True.Box(orientation=Gtk.pack_start(label. True. True. spacing=10) vbox_left. True.FILL) vbox_right. <i>italic</i> and even point to " "somewhere in the <a href=\"http://www.pack_start(label.\n" " This is another newer.Label("This is an example of a line-wrapped label.") label. 0) 25 26 27 28 29 label = Gtk.Justification.RIGHT) vbox_left.\n" " It supports multiple paragraphs correctly. but automatically " "wraps the words to fit. Here is another sentence.Box(orientation=Gtk. 0) 40 41 42 43 44 45 46 47 48 49 50 51 52 53 label = Gtk.set_markup("Text can be <small>small</small>. True.Label("This is a normal label") vbox_left.pack_start(label.set_line_wrap(True) label. " "unfortunately.\nWith multiple lines.set_line_wrap(True) vbox_left. True. True.set_homogeneous(False) vbox_right = Gtk.set_text("This is a left-justified label. 0) 17 18 19 label = Gtk. True. " "Here comes the sun.set_justify(Gtk.VERTICAL.set_line_wrap(True) vbox_right.pack_start(label. True. longer.org\" " "title=\"Click to find out more\">internets</a>.Orientation. do de do de do.") label.Justification. True.pack_start(label. 0) 30 31 32 33 34 35 36 37 38 39 label = Gtk.set_justify(Gtk. " "Here is a sentence to prove " "my point.Orientation. spacing=10) vbox_right.gtk. 0) 20 21 22 23 24 label = Gtk.Label.1. 4 67 button = Gtk. 0) 68 69 70 71 self.show_all() Gtk.main_quit) window.set_mnemonic_widget(button) vbox_right. True.connect("delete-event". Gtk.main() 30 Chapter 6.Button(label="Click at your own risk") label. Release 3.pack_start(button.The Python GTK+ 3 Tutorial. True. Label .add(hbox) 72 73 74 75 76 77 window = LabelWindow() window. Entry. Calling Gtk. This is similar to Gtk. You can change the contents with the Gtk. To make an entry display such information. or icon theme. use Gtk.get_text() method.progress_pulse().set_icon_tooltip_text() or the corresponding function for markup.1 Example 1 from gi. Additionally. This can be done by passing False to the Gtk.ProgressBar widget and is commonly found in web browsers to indicate how much of a page download has been completed.Entry.set_text() method.Entry. can be set up as drag source and can have tooltips. use Gtk.Entry has the ability to display progress or activity information behind the text. Occasionally you might want to make an Entry widget read-only.Entry. You can also limit the number of characters the Entry can take by calling Gtk.set_max_length().Entry.repository import Gtk.Window): 31 .Entry. Gtk.set_progress_fraction().set_icon_from_stock() or one of the various other functions that set an icon from an icon name. Entry widgets can also be used to retrieve passwords from the user.Entry. 7.set_progress_pulse_step(). GObject 2 3 class EntryWindow(Gtk. a pixbuf. or Gtk. an Entry can show icons at either side of the entry. To set a tooltip on an icon.Entry.Entry.set_editable() method.Entry.CHAPTER 7 Entry Entry widgets allow the user to enter text. use Gtk.set_visibility() with False will cause the text to be hidden. These icons can be activatable by clicking. It is common practice to hide the characters typed into the entry to prevent revealing the password to a third party. To add an icon. Gtk. and read the current contents with the Gtk. entry.set_active(False) hbox.check_visible. 0) 14 15 16 17 hbox = Gtk.on_pulse_toggled) self.source_remove(self.connect("toggled". 0) 36 37 38 39 40 def on_editable_toggled(self.entry. 0) 26 27 28 29 30 self.pulse.Orientation.icon.entry. True.set_progress_pulse_step(0.4 4 def __init__(self): Gtk.Box(orientation=Gtk.pack_start(self.connect("toggled".2) # Call self.icon = Gtk. True.pack_start(self. True. 100) 5 6 7 8 self.do_pulse anymore GObject.set_visibility(value) 45 46 47 48 def on_pulse_toggled(self.set_text("Hello World") vbox. user_data): self.entry.check_editable.timeout_id = GObject. 0) 18 19 20 self.pack_start(self.get_active(): self.check_editable.check_visible.timeout_id = None self. True.connect("toggled".check_editable = Gtk.progress_pulse() 60 61 32 Chapter 7. self. button): value = button.entry. title="Entry Demo") self.entry = Gtk.on_icon_toggled) self. button): if button.timeout_id = None 9 10 vbox = Gtk.on_editable_toggled) self. 0) 21 22 23 24 25 self.CheckButton("Editable") self.entry.set_editable(value) 41 42 43 44 def on_visible_toggled(self.check_visible = Gtk.pulse.get_active() self. True. True. Release 3. True.The Python GTK+ 3 Tutorial. None) else: # Don’t call self. Entry .add(vbox) 11 12 13 self.timeout_add(100.pack_start(self.set_active(True) hbox. self.CheckButton("Pulse") self.VERTICAL.pulse.__init__(self.set_active(True) hbox. True. 0) 31 32 33 34 35 self.set_active(False) hbox.Window. True.do_pulse. True.pulse = Gtk.entry.icon.on_visible_toggled) self.Box(spacing=6) vbox.set_size_request(200.set_progress_pulse_step(0) 49 50 51 52 53 54 55 56 57 58 59 def do_pulse(self. self. spacing=6) self.check_visible.Entry() self.get_active() self. button): value = button.connect("toggled".pack_start(self. self.pack_start(hbox. self. True.check_editable.CheckButton("Visible") self. True.CheckButton("Icon") self.do_pulse every 100 ms self.icon.timeout_id) self. Gtk. Release 3.The Python GTK+ 3 Tutorial. stock_id) 71 72 73 74 75 win = EntryWindow() win.set_icon_from_stock(Gtk.entry.1.connect("delete-event". Example 33 .show_all() Gtk. button): if button.get_active(): stock_id = Gtk.main() 7.STOCK_FIND else: stock_id = None self.EntryIconPosition.main_quit) win.PRIMARY.4 62 return True 63 64 65 66 67 68 69 70 def on_icon_toggled(self. Release 3.4 34 Chapter 7.The Python GTK+ 3 Tutorial. Entry . on_open_clicked) 35 .Button("Click Me") button. title="Button Demo") self. 8. True.Box(spacing=6) self.add(hbox) 11 12 13 14 button = Gtk. 0) 15 16 17 button = Gtk. That is it can hold most any other standard Gtk.Window.pack_start(button.set_border_width(10) 8 9 10 hbox = Gtk. The most commonly used child is the Gtk. True. you want to connect to the button’s “clicked” signal which is emitted when the button has been pressed and released.1 Example 1 from gi.__init__(self.CHAPTER 8 Button Widgets 8.Button(stock=Gtk.Label. self.connect("clicked".repository import Gtk 2 3 class ButtonWindow(Gtk.connect("clicked".1.on_click_me_clicked) hbox.STOCK_OPEN) button.1 Button The Button widget is another commonly used widget.Window): 4 5 6 7 def __init__(self): Gtk. self. Usually.Widget.Button widget can hold any valid child widget. It is generally used to attach a function that is called when the button is pressed. The Gtk. ToggleButton. Gtk.__init__(self. True.set_border_width(10) 5 6 7 8 hbox = Gtk. button): print("Closing application") Gtk.main_quit) win. When the state of the button is changed. Note that. title="ToggleButton Demo") self. until clicked again.Button("_Close". button): print("\"Open\" button was clicked") 27 28 29 def on_close_clicked(self. you can use the Gtk. 8. 0) 18 19 button = Gtk. True.1 Example 1 from gi.pack_start(button.connect("delete-event". and the state actually changes.ToggleButton. self.add(hbox) 9 10 11 36 Chapter 8. True.main_quit() 30 31 32 33 34 35 36 37 win = ButtonWindow() win.main() 8. if you do this. or pressed.on_close_clicked) hbox. Release 3. True.Box(spacing=6) self. but when clicked they remain activated.Button. To retrieve the state of the Gtk. Button Widgets .ToggleButton is very similar to a normal Gtk.Window): 4 def __init__(self): Gtk. use_underline=True) button. You can also set the toggle button’s state.connect("clicked".2 ToggleButton A Gtk.The Python GTK+ 3 Tutorial. it causes the “toggled” signal to be emitted.set_active().ToggleButton. 0) 20 21 22 23 def on_click_me_clicked(self. with Gtk.show_all() Gtk.Window.2. the “toggled” signal is emitted.4 hbox.repository import Gtk 2 3 class ToggleButtonWindow(Gtk.pack_start(button. This returns True if the button is “down”.get_active() method. button): print("\"Click me\" button was clicked") 24 25 26 def on_open_clicked(self. set_active() and Gtk.4 RadioButton Like checkboxes. but these work in groups. True. 0) 15 16 17 18 19 button = Gtk.on_button_toggled.RadioButton. Gtk. 8. The “toggled” signal.main_quit) win. 8. True.main() 8.ToggleButton("B_utton 2". 0) 20 21 22 23 24 25 26 def on_button_toggled(self. self.4 12 13 14 button = Gtk. Gtk.get_active() are inherited.pack_start(button.RadioButton. the group you wish to add this button to should be passed as an argument. "2") hbox.ToggleButton("Button 1") button. radio buttons also inherit from Gtk.show_all() Gtk.new_with_label_from_widget() or Gtk. the first radio button in the group will be active.3 CheckButton Gtk. "was turned".3.connect("delete-event".RadioButton.CheckButton inherits from Gtk. self. a Gtk. (usually a Gtk.new_with_mnemonic_from_widget The first radio button in a group will be created passing None as the group argument. Release 3.ToggleButton.connect("toggled".pack_start(button. name. Therefore.CheckButton places a discrete Gtk. Gtk.set_active() with True as first argument. name): if button.new_from_widget(). "1") hbox.get_active(): state = "on" else: state = "off" print("Button". and only one Gtk.RadioButton‘s widget Gtk.ToggleButton. CheckButton group after its creation This can be changed by calling can be achieved by calling 37 .The Python GTK+ 3 Tutorial. True.ToggleButton.RadioButton is one way of giving the user a choice from many options.ToggleButton.RadioButton. use_underline=True) button. Changing a Gtk.Label). In subsequent calls. A Gtk. The only real difference between the two is Gtk.ToggleButton.RadioButton in a group can be selected at any one time. When first run.CheckButton‘s appearance. Radio buttons can be created with one of the static methods Gtk. button. Gtk.join_group(). state) 27 28 29 30 31 win = ToggleButtonWindow() win. True.connect("toggled".ToggleButton next to a widget.on_button_toggled.set_active(True) button. The Python GTK+ 3 Tutorial, Release 3.4 8.4.1 Example 1 from gi.repository import Gtk 2 3 class RadioButtonWindow(Gtk.Window): 4 def __init__(self): Gtk.Window.__init__(self, title="RadioButton Demo") self.set_border_width(10) 5 6 7 8 hbox = Gtk.Box(spacing=6) self.add(hbox) 9 10 11 button1 = Gtk.RadioButton.new_with_label_from_widget(None, "Button 1") button1.connect("toggled", self.on_button_toggled, "1") hbox.pack_start(button1, False, False, 0) 12 13 14 15 button2 = Gtk.RadioButton.new_from_widget(button1) button2.set_label("Button 2") button2.connect("toggled", self.on_button_toggled, "2") hbox.pack_start(button2, False, False, 0) 16 17 18 19 20 button3 = Gtk.RadioButton.new_with_mnemonic_from_widget(button1, "B_utton 3") button3.connect("toggled", self.on_button_toggled, "3") hbox.pack_start(button3, False, False, 0) 21 22 23 24 25 def on_button_toggled(self, button, name): if button.get_active(): state = "on" else: state = "off" print("Button", name, "was turned", state) 26 27 28 29 30 31 32 33 34 35 36 win = RadioButtonWindow() win.connect("delete-event", Gtk.main_quit) win.show_all() Gtk.main() 8.5 LinkButton A Gtk.LinkButton is a Gtk.Button with a hyperlink, similar to the one used by web browsers, which triggers an action when clicked. It is useful to show quick links to resources. The URI bound to a Gtk.LinkButton can be set specifically using Gtk.LinkButton.set_uri(), and retrieved using Gtk.LinkButton.get_uri(). 38 Chapter 8. Button Widgets The Python GTK+ 3 Tutorial, Release 3.4 8.5.1 Example 1 from gi.repository import Gtk 2 3 class LinkButtonWindow(Gtk.Window): 4 5 6 7 def __init__(self): Gtk.Window.__init__(self, title="LinkButton Demo") self.set_border_width(10) 8 9 10 button = Gtk.LinkButton("http://www.gtk.org", "Visit GTK+ Homepage") self.add(button) 11 12 13 14 15 win = LinkButtonWindow() win.connect("delete-event", Gtk.main_quit) win.show_all() Gtk.main() 8.6 SpinButton A Gtk.SpinButton is an ideal way to allow the user to set the value of some attribute. Rather than having to directly type a number into a Gtk.Entry, Gtk.SpinButton allows the user to click on one of two arrows to increment or decrement the displayed value. A value can still be typed in, with the bonus that it can be checked to ensure it is in a given range. The main properties of a Gtk.SpinButton are set through Gtk.Adjustment. To change the value that Gtk.SpinButton is showing, use Gtk.SpinButton.set_value(). The value entered can either be an integer or float, depending on your requirements, use Gtk.SpinButton.get_value() or Gtk.SpinButton.get_value_as_int(), respectively. When you allow the displaying of float values in the spin button, you may wish to adjust the number of decimal spaces displayed by calling Gtk.SpinButton.set_digits(). By default, Gtk.SpinButton accepts textual data. If you wish to limit this to numerical values only, call Gtk.SpinButton.set_numeric() with True as argument. We can also adjust the update policy of Gtk.SpinButton. There are two options here; by default the spin button updates the value even if the data entered is invalid. Alternatively, we can set the policy to only update when the value entered is valid by calling Gtk.SpinButton.set_update_policy(). 8.6. SpinButton 39 The Python GTK+ 3 Tutorial, Release 3.4 8.6.1 Example 1 from gi.repository import Gtk 2 3 class SpinButtonWindow(Gtk.Window): 4 def __init__(self): Gtk.Window.__init__(self, title="SpinButton Demo") self.set_border_width(10) 5 6 7 8 hbox = Gtk.Box(spacing=6) self.add(hbox) 9 10 11 adjustment = Gtk.Adjustment(0, 0, 100, 1, 10, 0) self.spinbutton = Gtk.SpinButton() self.spinbutton.set_adjustment(adjustment) hbox.pack_start(self.spinbutton, False, False, 0) 12 13 14 15 16 check_numeric = Gtk.CheckButton("Numeric") check_numeric.connect("toggled", self.on_numeric_toggled) hbox.pack_start(check_numeric, False, False, 0) 17 18 19 20 check_ifvalid = Gtk.CheckButton("If Valid") check_ifvalid.connect("toggled", self.on_ifvalid_toggled) hbox.pack_start(check_ifvalid, False, False, 0) 21 22 23 24 def on_numeric_toggled(self, button): self.spinbutton.set_numeric(button.get_active()) 25 26 27 def on_ifvalid_toggled(self, button): if button.get_active(): policy = Gtk.SpinButtonUpdatePolicy.IF_VALID else: policy = Gtk.SpinButtonUpdatePolicy.ALWAYS self.spinbutton.set_update_policy(policy) 28 29 30 31 32 33 34 35 36 37 38 win = SpinButtonWindow() win.connect("delete-event", Gtk.main_quit) win.show_all() Gtk.main() 8.7 Switch A Gtk.Switch is a widget that has two states: on or off. The user can control which state should be active by clicking the empty area, or by dragging the handle. 40 Chapter 8. Button Widgets set_active(True) hbox. state) 28 29 30 31 32 win = SwitcherWindow() win.The Python GTK+ 3 Tutorial. but use the “notify::active” signal.__init__(self. see the example here below.Switch which is an action signal and emitting it causes the switch to animate.7.main() 8. 8.pack_start(switch. gparam): if switch.main_quit) win. True. 0) 16 17 18 19 20 switch = Gtk.Window): 4 5 6 7 def __init__(self): Gtk. Gtk.set_active(False) hbox.4 You shouldn’t use the “activate” signal on the Gtk.add(hbox) 11 12 13 14 15 switch = Gtk.set_border_width(10) 8 9 10 hbox = Gtk.pack_start(switch.Box(spacing=6) self.on_switch_activated) switch. Release 3. title="Switch Demo") self.Switch() switch. True. self.connect("notify::active". Switch 41 . 0) 21 22 23 24 25 26 27 def on_switch_activated(self.connect("notify::active".Window. True.Switch() switch.get_active(): state = "on" else: state = "off" print("Switch was turned".on_switch_activated) switch.repository import Gtk 2 3 class SwitcherWindow(Gtk.connect("delete-event". Applications should never connect to this signal. self. switch.7.1 Example 1 from gi.show_all() Gtk. True. Button Widgets .4 42 Chapter 8.The Python GTK+ 3 Tutorial. Release 3. In this mode.g.pulse() periodically to update the progress bar.set_show_text().ProgressBar in percentage mode and the user sees a growing bar indicating the percentage of the work that has been completed. it can use the Gtk.ProgressBar is horizontal and left-to-right.CHAPTER 9 ProgressBar The Gtk. Gtk.ProgressBar.ProgressBar. with the Gtk.ProgressBar. Gtk. You can also choose the step size. It provides a visual clue that processing is underway.set_pulse_step() method. By default.ProgressBar is typically used to display the progress of a long running operation.set_fraction() periodically to update the progress bar.ProgressBar. In this mode.ProgressBar can be used in two different modes: percentage mode and activity mode.set_inverted().1 Example 43 . but you can change it to a vertical progress bar by using the Gtk.set_text() and Gtk. the application is required to call Gtk.set_orientation() method. Changing the direction the progress bar grows can be done using Gtk. The Gtk. the application is required to call Gtk.ProgressBar. passing a float between 0 and 1 to provide the new percentage value. 9. which shows activity by a block moving back and forth within the progress area.ProgressBar can also contain text which can be set by calling Gtk. it can use activity mode.ProgressBar.ProgressBar. When an application has no accurate way of knowing the amount of work to do. read a fixed number of bytes from a file) and can monitor its progress. When an application can determine how much work needs to take place (e. spacing=6) self. None) self.pack_start(self. 0) 12 13 14 button = Gtk. True.The Python GTK+ 3 Tutorial. ProgressBar .pulse() else: new_value = self. user_data): """ Update value on the progress bar """ if self.timeout_id = GObject.progressbar.activity_mode: self.connect("toggled".timeout_add(50. button): self. True. title="ProgressBar Demo") self.CheckButton("Show text") button.VERTICAL.progressbar = Gtk.CheckButton("Right to Left") button.progressbar.on_show_text_toggled) vbox.on_timeout.set_show_text(show_text) 30 31 32 33 34 35 36 37 38 def on_activity_mode_toggled(self. GObject 2 3 class ProgressBarWindow(Gtk. True.Box(orientation=Gtk.get_active() if self.on_right_to_left_toggled) vbox. self.pack_start(button.pack_start(button.get_active() if show_text: text = "some text" else: text = None self.Window.progressbar. button): value = button. True. Release 3.progressbar.01 50 51 52 53 54 55 56 57 58 44 Chapter 9.activity_mode = False 27 28 29 def on_show_text_toggled(self. 0) 23 24 25 26 self. self.CheckButton("Activity mode") button.progressbar.set_inverted(value) 46 47 48 49 def on_timeout(self.__init__(self.get_fraction() + 0.pulse() else: self.set_text(text) self.0) 39 40 41 42 43 44 45 def on_right_to_left_toggled(self. self. True.repository import Gtk. button): show_text = button. True.pack_start(button.progressbar. 0) 15 16 17 18 button = Gtk.activity_mode: self. self. True.connect("toggled".connect("toggled".ProgressBar() vbox.set_fraction(0.activity_mode = button.progressbar.4 1 from gi.on_activity_mode_toggled) vbox. 0) 19 20 21 22 button = Gtk.Orientation.progressbar. True.Window): 4 def __init__(self): Gtk.add(vbox) 9 10 11 self.set_border_width(10) 5 6 7 8 vbox = Gtk.get_active() self. return True so that it # continues to get called return True 67 68 69 70 71 win = ProgressBarWindow() win. Release 3.show_all() Gtk.main() 9.progressbar.4 if new_value > 1: new_value = 0 59 60 61 self. Gtk.1.main_quit) win.The Python GTK+ 3 Tutorial.connect("delete-event". Example 45 .set_fraction(new_value) 62 63 64 65 66 # As this is a timeout function. The Python GTK+ 3 Tutorial.4 46 Chapter 9. ProgressBar . Release 3. 0.stop().attach(self. True) self.connect("delete-event".table. 2.start().Table(3.spinner.CHAPTER 10 Spinner The Gtk.Spinner.attach(self. 0. To start the animation.table.ToggleButton("Start Spinning") self.Spinner.Spinner displays an icon-size spinning animation. It is often used as an alternative to a GtkProgressBar for displaying indefinite activity.__init__(self. 10.set_border_width(3) self.1 Example 1 from gi.repository import Gtk 2 3 class SpinnerAnimation(Gtk. self.button.Window): 4 5 def __init__(self): 6 7 8 9 Gtk.table = Gtk.on_button_toggled) self.connect("toggled". 2.button.Spinner() 16 17 18 19 self.set_active(False) 14 15 self.Window. instead of actual progress.spinner = Gtk.main_quit) 10 11 12 13 self. 3) 47 .button = Gtk. 2.button. title="Spinner") self. 1) self. 2. use Gtk. to stop it use Gtk. Gtk. 0. table) self.set_label("Stop Spinning") 26 27 28 29 else: self.main() 48 Chapter 10. button): 24 25 if button.show_all() 21 22 23 def on_button_toggled(self.spinner.stop() self.get_active(): self.button.spinner.The Python GTK+ 3 Tutorial.button. Spinner . Release 3.start() self.add(self.set_label("Start Spinning") 30 31 32 33 34 35 myspinner = SpinnerAnimation() 36 37 Gtk.4 20 self. TreeStore model classes.TreeStore contains rows of data.TreeView has an associated Gtk. str.TreeView.ListStore(str. For instance.1 The Model Each Gtk. Although you can theoretically implement your own Model. progress bars.append() or Gtk. They are used in conjunction with a Gtk. When constructing a model you have to specify the data types for each column the model holds.TreeModel can be used by more than one Gtk. Adding data to the model is done using Gtk. Gtk. depending upon which sort of model was created. float) This creates a list store with three columns.append().TreeStore. Knuth". 25. and a float column.ListStore or Gtk. 11. in the same way that 2 SQL queries (or “views”) might show different fields from the same database table. etc.TreeModel. store = Gtk.ListStore.46]) 49 . and each row may have child rows. removed or edited • Drag and drop support • Sorting of data • Support embedding widgets such as check boxes.ListStore contains simple rows of data.ListStore or Gtk. It is often difficult for beginner developers to be able to utilize correctly due to the number of methods which are required. Or the 2 Views might display different columns from the same Model data. you will normally use either the Gtk.TreeView and its associated widgets are an extremely powerful way of displaying data. treeiter = store.TreeStore and provide a way of displaying and manipulating data in many ways.TreeView comes complexity. including: • Automatically updates when data added.CHAPTER 11 Tree and List Widgets A Gtk. and each row has no children.append(["The Art of Computer Programming". which contains the data displayed by the TreeView. • Reorderable and resizable columns • Filtering of data With the power and flexibility of a Gtk. whereas Gtk. Each Gtk. this allows the same underlying data to be displayed and edited in 2 different ways at the same time. "Donald E. two string columns. iter_children(treeiter) print_rows(store. indent + "\t") treeiter = store.TreePath([2.iter_has_child(treeiter): childiter = store. "") def print_rows(store. To iterate over all rows and its children. # Print number of rows print len(store) # Print all but first column print store[treeiter][1:] # Print last column print store[treeiter][-1] # Set first two columns store[treeiter][:2] = ["Donald Ervin Knuth". that if you use Gtk. 1) In the case of Gtk. Each number refers to the offset at that level. the path “0” refers to the root node and the path “2:4” refers to the fifth child of the third node. 4]) treeiter = treestore.ListStore contains only one level. # Get path pointing to 5th child of 3rd row in tree store path = Gtk. treeiter. i. it is also possible to either use Gtk. which points to the location of the newly inserted row. # Get path pointing to 6th row in list store path = Gtk. childiter. indent): while treeiter != None: print indent + str(store[treeiter][:]) if store. print store[treeiter][2] # Prints value of third column store[treeiter][2] = 42. Release 3.The Python GTK+ 3 Tutorial. As Gtk.get_iter(path) # Get value at 2nd column value = liststore.TreeModel with the list-like method mentioned above. nodes do not have any child nodes.get_iter_first() print_rows(store.TreeStore.TreeModel.get_value(treeiter. def print_tree_store(store): rootiter = store.TreeModel.TreeIter by calling Gtk.get_iter(). Once. Both reference a particular row in a tree model.TreePath(5) treeiter = liststore. for row in store: # Print values of all columns print row[:] Keep in mind. the above code will only iterate over the rows of the top level. data has been inserted you can retrieve or modify data using the tree iter and column index. The string form is a list of numbers separated by a colon. Tree and List Widgets .e.TreePath instances.4 Both methods return a Gtk.get_iter(path) 50 Chapter 11. use the print_tree_store function. but not the children of the nodes.15 As with Python’s built-in list object you can use len() to get the number of rows and use slices to retrieve or set values.TreeIter instance.TreeIter or Gtk.99] Iterating over all rows of a tree model is very simple as well. Thus. a path is essentially the index of the row you want to access. One can convert a path to an iterator by calling Gtk.get_iter(). 41.TreeStore. a path is a list of indexes or a string. rootiter.iter_next(treeiter) Apart from accessing values stored in a Gtk. You can retrieve a Gtk. It works with either the list or the tree store. renderer.append_column(column) To render more than one model column in a view column.add_attribute(author.pack_start(author. column = Gtk.The Python GTK+ 3 Tutorial. There are a number of cell renderers that come with GTK+. 1) Instances of Gtk. it will need to know how to display the model.TreeView is not a difficult matter.CellRendererText() column = Gtk. Gtk. on_tree_selection_changed) Then to retrieve data for the row selected: 11.append_column(column) 11.connect("changed".pack_start(title. The View 51 . simply get a reference to a selection object and connect to the “changed” signal.e. "text".TreeViewColumn.CellRendererToggle.TreeView uses to organize the vertical columns in the tree view. 1) tree.add_attribute(title. In addition. you need to create a Gtk. for instance Gtk. either by passing it to the Gtk. and which piece of data to retrieve from the model for a given row. select = tree. it is relatively easy to write a custom renderer yourself. It needs a Gtk. It needs to know the name of the column to label for the user. A Gtk. "text". len(treepath) returns the depth of the item treepath is pointing to. 11.CellRendererText. renderer = Gtk. Release 3.get_selection() select. i. Setting up a Gtk.TreeViewColumn("Title and Author") title = Gtk. what type of cell renderer to use.CellRendererText() column.get_value(treeiter.CellRendererPixbuf and Gtk.TreePath can be accessed like lists.3 The Selection Most applications will need to not only deal with displaying data. Cell renderers are used to draw the data in the tree model in a way.pack_start() to add the model columns to it.CellRendererText() author = Gtk.TreeModel to know where to retrieve its data from.TreeView constructor.TreeView widget has a model.TreeView(store) Once the Gtk.TreeView.2. True) column.set_model(). and treepath[i] returns the child’s index on the i-th level.TreeViewColumn is the object that Gtk.TreeViewColumn instance and use Gtk.2 The View While there are several different models to choose from. To do this.4 # Get value at 2nd column value = treestore. 0) column. True) column. tree = Gtk. or by calling Gtk. It does this with columns and cell renderers. but also receiving input events from users.TreeViewColumn("Title". there is only one view widget to deal with. text=0) tree. Afterwards the column can be sorted by clicking on its header. column.get_selected() if treeiter != None: print "You selected". Gtk.2 Setting a custom sort function It is also possible to set a custom comparison function in order to change the sorting behaviour. In the example above the sorted list looked like: alfred Alfred benjamin Benjamin charles Charles 52 Chapter 11.TreeStore and Gtk.TreeSelection. Note that the column_id (0 in the example) refers to the column of the model and not to the TreeView’s column. renderer.set_sort_column_id().append(["Charles"]) model. model[treeiter][0] You can control what selections are allowed by calling Gtk. text=0) The next step is to enable sorting. 11.4. As an example we will create a comparison function that sorts case-sensitive.get_selected() does not work if the selection mode is set to Gtk.CellRendererText() column = Gtk.TreeView(model) cellRenderer = Gtk.set_mode().ListStore as a model.SelectionMode.TreeSortable interface.get_selected_rows() instead.4 Sorting Sorting is an important feature for tree views and is supported by the standard tree models (Gtk.TreeSelection.4 def on_tree_selection_changed(selection): model.TreeView and a Gtk.TreeViewColumn("Title".MULTIPLE. use Gtk.The Python GTK+ 3 Tutorial.ListStore(str) model.ListStore).4.TreeViewColumn.append(["alfred"]) model.append(["Alfred"]) model. Tree and List Widgets .TreeSelection.1 Sorting by clicking on columns A column of a Gtk.append(["benjamin"]) treeView = Gtk.append(["David"]) model. 11.TreeView can easily made sortable with a call to Gtk.append(["david"]) model.append(["charles"]) model. treeiter = selection. model = Gtk. which implement the Gtk.append(["Benjamin"]) model. First we need a simple Gtk. Release 3.set_sort_column_id(0) 11. def compare(model. row2. row1. sort_column) if value1 < value2: return -1 elif value1 == value2: return 0 else: return 1 Then the sort function has to be set by Gtk.get_value(row1. _ = model.The Python GTK+ 3 Tutorial. sort_column) value2 = model.4 david David The case-sensitive sorted list will look like: Alfred Benjamin Charles David alfred benjamin charles david First of all a comparison function is needed.get_sort_column_id() value1 = model. zero if they are equal and a positive integer if the second one should come before the second one.set_sort_func(). This function gets two rows and has to return a negative integer if the first one should come before the second one.get_value(row2.4. Sorting 53 . compare.TreeSortable. Release 3. None) 11. user_data): sort_column.set_sort_func(0. model. The Python GTK+ 3 Tutorial. Tree and List Widgets .4 54 Chapter 11. Release 3. ComboBox.CellRendererText widgets is not editable.CellRenderer widgets which can be used for different purposes: • Gtk. There are seven Gtk.CellRendererToggle • Gtk. True) You can then connect to the “edited” signal and update your Gtk. using the font.CellRendererText renders a given text in its cell. By default.CellRendererText • Gtk.1 CellRendererText A Gtk.set_property("editable".CellRendererPixbuf • Gtk. This can be changed by setting the value of the “editable” property to True: cell.CellRenderer widgets are used to display information within widgets such as the Gtk.CellRendererAccel 12. color and style information provided by its properties.CHAPTER 12 CellRenderers Gtk.CellRendererSpin • Gtk. They work closely with the associated widgets and are very powerful. 55 .TreeModel accordingly.CellRendererProgress • Gtk. The text will be ellipsized if it is too long and the “ellipsize” property allows it. text in Gtk.CellRendererSpinner • Gtk. with lots of configuration options for displaying a large amount of data in different ways.TreeView or Gtk.CellRendererCombo • Gtk. self.Window): 4 def __init__(self): Gtk. widget.1 Example 1 from gi.Window.set_property("editable".add(treeview) 30 31 def text_edited(self.org/"]) self. CellRenderers .The Python GTK+ 3 Tutorial.liststore[path][1] = text 32 33 56 Chapter 12.append(["Slackware".liststore = Gtk.liststore. title="CellRendererText Example") 5 6 7 self.liststore. str) self.liststore. "http://fedoraproject. renderer_editabletext. "http://sidux.connect("edited".repository import Gtk 2 3 class CellRendererTextWindow(Gtk.__init__(self. text=0) treeview.append(["Fedora". True) 21 22 23 column_editabletext = Gtk.append_column(column_text) 17 18 19 20 renderer_editabletext = Gtk.set_default_size(200.CellRendererText() column_text = Gtk.4 12. "http://www.com/"]) 10 11 12 13 14 treeview = Gtk.liststore) 15 16 renderer_text = Gtk. 200) 8 9 self. Release 3.append_column(column_editabletext) 24 25 26 27 renderer_editabletext.TreeViewColumn("Editable Text". path.TreeView(model=self.com/"]) self.1. text=1) treeview.TreeViewColumn("Text". text): self. renderer_text.ListStore(str.text_edited) 28 29 self.CellRendererText() renderer_editabletext.slackware.append(["Sidux". bool.2.append(["Fedora".set_default_size(200.liststore. As a Gtk. 12. False]) 14 12. depending on the “radio” property.connect("delete-event".repository import Gtk 2 3 class CellRendererToggleWindow(Gtk.liststore. True]) self.CellRendererToggle renders a toggle button in a cell. False.main() 12. CellRendererToggle 57 . The button is drawn as a radio.2 CellRendererToggle Gtk.or checkbutton. you most likely want to bind the “active” property on the cell renderer to a boolean value in the model.append(["Debian". title="CellRendererToggle Example") 7 8 self.1 Example 1 from gi.2.main_quit) win. True.The Python GTK+ 3 Tutorial.Window.CellRendererToggle can have two states. thus causing the check button to reflect the state of the model. False. When activated.__init__(self. it emits the “toggled” signal. False]) self. 200) 9 10 11 12 13 self.liststore.liststore = Gtk. active and not active. Release 3.ListStore(str.4 34 35 36 37 38 win = CellRendererTextWindow() win. Gtk. bool) self.show_all() Gtk.Window): 4 5 6 def __init__(self): Gtk.append(["OpenSuse". TreeView(model=self.connect("toggled".show_all() Gtk.3 CellRendererPixbuf A Gtk. path): self. widget.path == selected_path) 39 40 41 42 43 44 45 46 47 win = CellRendererToggleWindow() win. self. renderer_text.4 treeview = Gtk. text=0) treeview.CellRendererToggle() renderer_toggle. It allows to render either a given Gdk.connect("toggled".on_cell_toggled) 21 22 23 column_toggle = Gtk.CellRendererToggle() renderer_radio.CellRendererText() column_text = Gtk.append_column(column_toggle) 24 25 26 renderer_radio = Gtk.The Python GTK+ 3 Tutorial. active=2) treeview.on_cell_radio_toggled) 27 28 29 30 column_radio = Gtk. 58 Chapter 12.set_radio(True) renderer_radio.TreeViewColumn("Text".TreeViewColumn("Toggle".main() 12.liststore[path][1] 36 37 38 def on_cell_radio_toggled(self.CellRendererPixbuf can be used to render an image in a cell. renderer_radio.liststore[path][1] = not self.TreeViewColumn("Radio".connect("delete-event". self.append_column(column_radio) 31 32 33 self.liststore) 15 16 renderer_text = Gtk.add(treeview) 34 35 def on_cell_toggled(self. active=1) treeview.TreePath(path) for row in self. Gtk. widget. CellRenderers .liststore: row[2] = (row.Pixbuf (set via the “pixbuf” property) or a stock item (set via the “stock-id” property).append_column(column_text) 17 18 19 20 renderer_toggle = Gtk.main_quit) win. Release 3. path): selected_path = Gtk. renderer_toggle. liststore.The Python GTK+ 3 Tutorial.CellRendererText() column_text = Gtk.connect("delete-event".Window): 4 5 6 def __init__(self): Gtk.3.Window. stock_id=1) treeview.repository import Gtk 2 3 class CellRendererPixbufWindow(Gtk.3.liststore = Gtk.1 Example 1 from gi. renderer_text.liststore.4 12.main() 12. Release 3. text=0) treeview.show_all() Gtk. renderer_pixbuf.add(treeview) 27 28 29 30 31 win = CellRendererPixbufWindow() win.__init__(self.append(["Open".append(["Save".append_column(column_pixbuf) 25 26 self.TreeView(model=self.liststore.TreeViewColumn("Text".ListStore(str.append_column(column_text) 20 21 renderer_pixbuf = Gtk.liststore) 16 17 18 19 renderer_text = Gtk.CellRendererPixbuf() 22 23 24 column_pixbuf = Gtk.STOCK_OPEN]) self.STOCK_NEW]) self. Gtk.TreeViewColumn("Image".STOCK_SAVE]) 14 15 treeview = Gtk. str) self. Gtk. 200) 9 10 11 12 13 self.set_default_size(200. title="CellRendererPixbuf Example") 7 8 self. CellRendererPixbuf 59 . Gtk.append(["New". Gtk.main_quit) win. The values to display in the combo box are taken from the Gtk. str) self. CellRenderers .ComboBox widget to edit the text.The Python GTK+ 3 Tutorial. "Samsung"] for item in manufacturers: liststore_manufacturers. Release 3. "Nokia". "Samsung"]) self.Window.repository import Gtk 2 3 class CellRendererComboWindow(Gtk.TreeModel specified in the “model” property.4. But while the latter offers a simple entry to edit the text.append([item]) 10 11 12 13 14 15 self.Entry widget. "Toshiba".CellRendererCombo offers a Gtk. The combo cell renderer takes care of adding a text cell renderer to the combo box and sets it to display the column specified by its “text-column” property. depending on the value of the “has-entry” property.append(["Television".ListStore(str) manufacturers = ["Sony". "LG"]) 16 17 18 60 Chapter 12.__init__(self. Gtk.CellRendererCombo can operate in two modes. title="CellRendererCombo Example") 5 6 7 self.CellRendererText from which it is derived. It can be used with and without an associated Gtk.4 CellRendererCombo Gtk.append(["Mobile Phone".CellRendererCombo renders text in a cell like Gtk.Window): 4 def __init__(self): Gtk. 12. A Gtk.liststore_hardware. "LG". 200) 8 9 liststore_manufacturers = Gtk.1 Example 1 from gi. "Panasonic".liststore_hardware = Gtk.set_default_size(200.4 12.ListStore(str.liststore_hardware. Release 3. self.set_property("editable". text): self.TreeView(model=self.CellRendererProgress renders a numeric value as a progress bar in a cell.5.liststore_hardware) 22 23 24 25 renderer_text = Gtk.4 19 self. 12. "Sony"]) 20 21 treeview = Gtk.connect("edited". CellRendererProgress 61 . The percentage value of the progress bar can be modified by changing the “value” property. True) renderer_combo.set_property("has-entry". path.ProgressBar.on_combo_changed) 33 34 35 column_combo = Gtk.connect("delete-event".append(["DVD Player". renderer_text.append_column(column_combo) 36 37 self.main_quit) win.TreeViewColumn("Combo". Additionally.set_property("model".CellRendererText() column_text = Gtk.The Python GTK+ 3 Tutorial.main() 12. Gtk.set_property("text-column". text=0) treeview.liststore_hardware. Similar to Gtk. you can enable the activity mode by incrementing the “pulse” property instead of the “value” property. False) renderer_combo.liststore_hardware[path][1] = text 41 42 43 44 45 win = CellRendererComboWindow() win. text=1) treeview.CellRendererCombo() renderer_combo. 0) renderer_combo.TreeViewColumn("Text". renderer_combo.show_all() Gtk. it can display a text on top of the progress bar. widget. liststore_manufacturers) renderer_combo.5 CellRendererProgress Gtk.append_column(column_text) 26 27 28 29 30 31 32 renderer_combo = Gtk.add(treeview) 38 39 40 def on_combo_changed(self. liststore) 15 16 renderer_text = Gtk. bool) self. title="CellRendererProgress Example") 5 6 7 self. Release 3.CellRendererProgress() column_progress = Gtk. False]) 10 11 12 13 14 treeview = Gtk.append(["Sabayon". renderer_toggle.4 12. renderer_text. text=0) treeview.TreeViewColumn("Inverted".append_column(column_toggle) 26 27 28 29 30 31 self.liststore. False]) self. value=1.append_column(column_progress) 21 22 23 24 25 renderer_toggle = Gtk.set_default_size(200.add(treeview) 32 33 62 Chapter 12.on_inverted_toggled) column_toggle = Gtk. renderer_progress. self.The Python GTK+ 3 Tutorial.append(["SimplyMepis".Window. 200) 8 9 self.ListStore(str. False]) self.TreeViewColumn("Progress". CellRenderers . inverted=2) treeview.liststore. active=2) treeview. 0.TreeView(model=self.append(["Zenwalk". GObject 2 3 class CellRendererProgressWindow(Gtk.repository import Gtk.CellRendererText() column_text = Gtk. 0.liststore.connect("toggled". int.liststore = Gtk.append_column(column_text) 17 18 19 20 renderer_progress = Gtk.5.TreeViewColumn("Text".__init__(self.1 Example 1 from gi. 0.CellRendererToggle() renderer_toggle.Window): 4 def __init__(self): Gtk.current_iter = self. current_iter][1] + 1 46 47 48 self.current_iter = self. None) 35 36 37 def on_inverted_toggled(self.4 34 self. path): self.CellRendererText from which it is derived.current_iter = self.liststore[path][2] 38 39 40 41 42 43 44 45 def on_timeout(self.connect("delete-event".reset_model() new_value = self.timeout_add(100.show_all() Gtk.CellRendererSpin renders text in a cell like Gtk. user_data): new_value = self.liststore[self.current_iter][1] + 1 if new_value > 100: self.6 CellRendererSpin Gtk.CellRendererSpin offers a Gtk.get_iter_first() 54 55 56 57 58 win = CellRendererProgressWindow() win.liststore[self. Release 3. Of course. CellRendererSpin 63 .The Python GTK+ 3 Tutorial.liststore[path][2] = not self. Gtk.CellRendererSpin also has properties for the climb rate and the number of digits to display. Gtk. widget. But while the latter offers a simple entry to edit the text.current_iter == None: self.current_iter) if self.main_quit) win.liststore: row[1] = 0 self.current_iter][1] = new_value return True 49 50 51 52 53 def reset_model(self): for row in self. 12. Gtk.liststore. like all properties of cell renders. self. that means that the text has to be parseable as a floating point number.main() 12. which can be set explicitly or mapped to a column in the tree model.iter_next(self.liststore[self.on_timeout. The range of the spinbutton is taken from the adjustment property of the cell renderer.timeout_id = GObject.SpinButton widget.liststore.6. renderer_text.TreeView(model=self.1 Example 1 from gi.append(["Oranges".liststore = Gtk.liststore.set_default_size(200.CellRendererSpin() renderer_spin. widget.ListStore(str. text=1) treeview.liststore) 15 16 renderer_text = Gtk.__init__(self.append_column(column_text) 17 18 19 20 renderer_spin = Gtk. 100. value): 33 64 Chapter 12. CellRenderers . text=0) treeview.CellRendererText() column_text = Gtk. self. int) self.TreeViewColumn("Fruit".The Python GTK+ 3 Tutorial.Adjustment(0.repository import Gtk 2 3 class CellRendererSpinWindow(Gtk. 2]) 10 11 12 13 14 treeview = Gtk. 10. Release 3.6.set_property("editable". path. 5]) self.append(["Apples".add(treeview) 31 32 def on_amount_edited(self. 1. title="CellRendererSpin Example") 5 6 7 self.append_column(column_spin) 28 29 30 self.connect("edited". 0) renderer_spin. adjustment) 25 26 27 column_spin = Gtk.liststore.append(["Bananas".liststore. True) 21 22 23 24 adjustment = Gtk.4 12. 0.Window): 4 def __init__(self): Gtk.Window. 200) 8 9 self.set_property("adjustment". renderer_spin.on_amount_edited) renderer_spin.TreeViewColumn("Amount". 4]) self. connect("delete-event".main_quit) win.6. CellRendererSpin 65 .liststore[path][1] = int(value) 35 36 37 38 39 win = CellRendererSpinWindow() win.main() 12.4 34 self. Gtk. Release 3.show_all() Gtk.The Python GTK+ 3 Tutorial. CellRenderers . Release 3.4 66 Chapter 12.The Python GTK+ 3 Tutorial. new_with_model_and_entry() to create an Gtk. If appropriate.new_with_entry() or Gtk.ComboBox widget usually restricts the user to the available choices.ComboBox. and the display of the choices can be adapted to the data in the model by using cell renderers. or a progress bar. They are preferable to having many radio buttons on screen as they take up less room.Window): 4 67 .ComboBox instance. it may be better to display them in a grid rather than a list. In this case.ComboBox.ComboBoxText offers a simple alternative. allowing the user to enter arbitrary text if none of the available choices are suitable. Both Gtk. the model-view API of Gtk.repository import Gtk 2 3 class ComboBoxWindow(Gtk. For a simple list of textual choices.ComboBox is very similar to Gtk. Gtk. as both use the model-view pattern.ComboBox. This can be done by calling Gtk. 13.ComboBoxText can contain an entry.ComboBox and Gtk. To do this. such as text. but it can optionally have an Gtk.TreeView.ComboBox allows for the selection of an item from a dropdown menu.CHAPTER 13 ComboBox A Gtk. it can show extra information about each item. Gtk.ComboBox can be a bit overwhelming. a checkbox. a picture.set_wrap_width().1 Example 1 from gi.Entry. use one of the static methods Gtk. If the combo box contains a large number of items. The Gtk. the list of valid choices is specified in the form of a tree model. on_currency_combo_changed) for currency in currencies: currency_combo. combo): tree_iter = combo.pack_start(name_combo.get_model() row_id. 0) 47 48 self.ListStore(str) countries = ["Austria". False.get_active_iter() if tree_iter != None: model = combo. "Uruguay"] for country in countries: country_store.append([country]) 25 26 27 28 29 30 31 country_combo = Gtk. self. False.pack_start(country_combo. "Russian Ruble". "British Pound". 0) 20 21 22 23 24 country_store = Gtk. "Sue Bob"]) name_store. False.on_country_combo_changed) renderer_text = Gtk. title="ComboBox Example") 5 6 7 self. str) name_store.get_child() print("Entered: %s" % entry. "Rob McRoberts"]) name_store. "Xavier McRoberts"]) 10 11 12 13 14 15 16 17 vbox = Gtk. self.append([12.set_entry_text_column(1) vbox. "United States of America". ComboBox . False. "Billy Bob Junior"]) name_store. False. name = model[tree_iter][:2] print("Selected: ID=%d.ListStore(int. True) 32 33 34 35 36 37 38 currencies = ["Euro".append([1.append([11. "United Kingdom".Box(orientation=Gtk. "Switzerland". name)) else: entry = combo.new_with_model(country_store) country_combo. name=%s" % (row_id.pack_start(renderer_text.get_active_iter() 61 62 68 Chapter 13.set_entry_text_column(0) currency_combo.add_attribute(renderer_text.Window.append([2.set_border_width(10) 8 9 name_store = Gtk.VERTICAL.on_name_combo_changed) name_combo.append([31. False.connect("changed".append_text(currency) 39 40 41 42 43 44 45 46 vbox. "Brazil". spacing=6) 18 19 name_combo = Gtk.append([3.ComboBox.Orientation.4 def __init__(self): Gtk.The Python GTK+ 3 Tutorial.pack_start(currency_combo. combo): tree_iter = combo.ComboBoxText() currency_combo. "Japanese Yen". "France". "Swiss franc"] currency_combo = Gtk. "Joey Jojo"]) name_store.ComboBox.new_with_model_and_entry(name_store) name_combo.connect("changed". "Billy Bob"]) name_store. "Germany".CellRendererText() country_combo. "Belgium".get_text()) 51 52 53 54 55 56 57 58 59 60 def on_country_combo_changed(self.connect("changed". self. Release 3. True) country_combo. "US Dollars".add(vbox) 49 50 def on_name_combo_changed(self. "text".__init__(self. 0) vbox. "Mexican peso". 1.The Python GTK+ 3 Tutorial.main_quit) win.show_all() Gtk.4 63 64 65 66 if tree_iter != None: model = combo.get_active_text() if text != None: print("Selected: currency=%s" % text) 72 73 74 75 76 win = ComboBoxWindow() win. Release 3. Example 69 .connect("delete-event".main() 13. Gtk. combo): text = combo.get_model() country = model[tree_iter][0] print("Selected: country=%s" % country) 67 68 69 70 71 def on_currency_combo_changed(self. 4 70 Chapter 13.The Python GTK+ 3 Tutorial. Release 3. ComboBox . ListStore contains GdkPixbuf.CHAPTER 14 IconView A Gtk. 14. 64.Pixbuf objects.new() iconview.IconView.load_icon(icon.repository import Gtk from gi.ListStore for its model.ListStore(Pixbuf. Gtk. Gtk.GdkPixbuf import Pixbuf 3 4 icons = ["gtk-cut". the Gtk.append([pixbuf. str) iconview = Gtk.__init__(self) self.IconTheme. Similarly to Gtk. 0) liststore.get_default().set_text_column(1) 17 18 19 20 for icon in icons: pixbuf = Gtk.IconView supports numerous selection modes to allow for either selecting multiple icons at a time.set_default_size(200. "gtk-paste".1 Example 1 2 from gi.connect("delete-event". restricting selections to just one item or disallowing selecting items completely.IconView requires that one of the columns in its Gtk.show_all() Gtk.set_model(liststore) iconview.add(iconview) 23 24 25 26 27 win = IconViewWindow() win.IconView. "gtk-copy"] 5 6 class IconViewWindow(Gtk.set_pixbuf_column(0) iconview. Gtk.main_quit) win. Gtk.main() 71 .repository.SelectionMode selection modes.set_selection_mode() method is used with one of the Gtk. multiple selections and item reordering. 200) 11 12 13 14 15 16 liststore = Gtk.TreeView.Window): 7 8 9 10 def __init__(self): Gtk.Window.IconView uses a Gtk. "Label"]) 21 22 self. Instead of using cell renderers. It supports features such as drag and drop. To specify a selection mode.IconView is a widget that displays a collection of icons in a grid view. 4 72 Chapter 14. Release 3.The Python GTK+ 3 Tutorial. IconView . TextBuffer. Iterators are not valid indefinitely. Because of this.TextBuffer. In this case the Gtk.TextMark. and is used to hold whatever text is being displayed in the Gtk.TextView is the frontend with which the user can add.Justification. You can disable this by calling Gtk. However.set_text() and Gtk. it has a model/view design. Setting and retrieving the contents is possible with Gtk. The text can be displayed at the left edge.set_editable().set_wrap_mode().get_selection_bound().CHAPTER 15 Multiline Text Editor The Gtk.TextBuffer is the model which represents the text being edited.TextBuffer.TextView widget. Another default setting of the Gtk. By default. This can be changed by calling Gtk.TextView widget. Or you could maintain several text buffers and choose to display each one at different times in the same Gtk.TextView widgets to share the same Gtk.TextBuffer is the core of the Gtk. an “insert” mark (which is the position of the cursor) and the “selection_bound” mark. most text manipulation is accomplished with iterators.TextView.TextMark.FILL).LEFT).set_justification(). This allows two or more Gtk.TextView. 73 .get_buffer() method.TextBuffer. To wrap the text and prevent it going off the edges of the screen call Gtk.TextView. text can be added.TextView widget can be used to display and edit large amounts of formatted text. whenever the buffer is modified in a way that affects the contents of the buffer.RIGHT).2 The Model The Gtk.get_text(). the location of a Gtk. use Gtk. Like the Gtk. They are commonly used to edit multiple lines of text.Justification. edited and removed from the Gtk.TextMark is not shown. all outstanding iterators become invalid. represented by a Gtk.TextView.TextView it contains its own default Gtk. An iterator represents a position between two characters in the text buffer.TextBuffer.set_visible().TreeView. If the text is not editable. you usually want to hide the text cursor with Gtk.TextIter. 15. (Gtk. edit and delete textual data.TextView. or distributed across the complete width (Gtk. By default. and allows those text buffers to be displayed slightly differently.TextBuffer. respectively. 15.CENTER). iterators can’t be used to preserve positions across buffer modifications. When creating a Gtk.TextView. centered (Gtk. Both of them can be retrieved using Gtk.get_insert() and Gtk. In some cases it may be useful to set the justification of the text with Gtk.Justification. at the right edge (Gtk. To preserve a position.1 The View The Gtk.Justification.set_cursor_visible() as well. which you can access via the Gtk.TextView. A text buffer contains two built-in marks.TextView widget is long lines of text will continue horizontally until a break is entered. insert().TextBuffer.TextIter can be used to locate textual matches in the buffer using Gtk. Each tag is stored in a Gtk.TextTag can be applied to any number of text ranges in any number of buffers. whereas Gtk. end_iter) The following are some of the common styles applied to text: • Background colour (“foreground” property) • Foreground colour (“background” property) • Underline (“underline” property) • Bold (“weight” property) • Italics (“style” property) • Strikethrough (“strikethrough” property) • Justification (“justification” property) • Size (“size” and “size-points” properties) • Text wrapping (“wrap-mode” property) You can also delete particular tags later using Gtk.TextBuffer. One Gtk. Gtk. only tags from that tag table can be used with the buffer.get_selection_bounds().TextBuffer. Multiline Text Editor . 74 Chapter 15. Another useful method is Gtk.create_tag() and Gtk.TextBuffer. “lock” a range of text so the user can’t edit it. For instance.delete().TextBuffer. To specify that some text in the buffer should have specific formatting. the tag concept is more general than that. Release 3.TextBuffer.3 Tags Text in a buffer can be marked with tags. tags don’t have to affect appearance.4 Many methods exist to retrieve a Gtk.TextTag object.TextBuffer. However. however. They can instead affect the behaviour of mouse and key presses. To insert text at a specific position use Gtk.TextIter. For example.backward_search().create_tag("orange_bg". 15.apply_tag(): tag = textbuffer.TextBuffer. and then apply that tag to the region of text using Gtk.TextBuffer.get_start_iter() returns an iterator pointing to the first position in the text buffer. Gtk.insert_at_cursor() which inserts text wherever the cursor may be currently positioned. To remove portions of the text buffer use Gtk.The Python GTK+ 3 Tutorial.remove_all_tags(). The start and end iters are used as the starting point of the search and move forwards/backwards depending on requirements.forward_search() and Gtk. A tag is an attribute that can be applied to some range of text.get_end_iter() returns an iterator pointing past the last valid character.TextBuffer. you must define a tag to hold that formatting information.remove_tag() or delete all tags in a given region by calling Gtk.TextTagTable. A tag table defines a set of tags that can be used together.apply_tag(tag. A tag is represented by a Gtk. Each buffer has one tag table associated with it. start_iter.TextIter. or countless other things. background="orange") textbuffer. a tag might be called “bold” and make the text inside the tag bold. Retrieving the bounds of the selected text can be achieved by calling Gtk. In addition. A single tag table can be shared between multiple buffers.TextIter. STOCK_FIND. buttons=( Gtk. Gtk. parent.entry = Gtk.repository import Gtk.Dialog. Gtk.Label("Insert text you want to search for:") box.OK.4 Example 1 from gi. Gtk.ResponseType.MODAL.add(label) 15 16 17 self. Example 75 .Entry() box. parent): Gtk.add(self. Pango 2 3 class SearchDialog(Gtk.show_all() 15.entry) 18 19 self. "Search".4.get_content_area() 12 13 14 label = Gtk. Gtk.Dialog): 4 5 6 7 8 9 def __init__(self.STOCK_CANCEL.4 15. Release 3.CANCEL)) 10 11 box = self.__init__(self.DialogFlags.The Python GTK+ 3 Tutorial.ResponseType. insert(radio_justifyright.SeparatorToolItem().Window. 2) 45 46 47 button_bold. self. self. Gtk.set_stock_id(Gtk. Gtk. Gtk.set_default_size(-1.create_toolbar() self.Window): 22 def __init__(self): Gtk.on_button_clicked. Gtk.add(self.STOCK_UNDERLINE) toolbar. 0. 0) 39 40 41 button_italic = Gtk.connect("clicked". 7) 68 69 70 71 radio_justifyleft. self.new_from_stock(Gtk. 1) 42 43 44 button_underline = Gtk.connect("toggled".Justification. 3) 54 55 radio_justifyleft = Gtk. 1) 35 36 37 38 button_bold = Gtk.STOCK_BOLD) toolbar.STOCK_JUSTIFY_LEFT) toolbar.The Python GTK+ 3 Tutorial.Justification.create_textview() self. 350) 26 27 self.new_with_stock_from_widget( radio_justifyleft.grid) 28 29 30 self.STOCK_ITALIC) toolbar.insert(Gtk. 3.Justification.tag_italic) button_underline.Toolbar() self.grid.RadioToolButton.insert(radio_justifyfill.on_button_clicked.new_with_stock_from_widget( radio_justifyleft.LEFT) radio_justifycenter.insert(radio_justifycenter. Gtk.tag_bold) button_italic.connect("toggled".CENTER) radio_justifyright.STOCK_JUSTIFY_FILL) toolbar.RadioToolButton.Grid() self. self.4 20 21 class TextViewWindow(Gtk.new_with_stock_from_widget( radio_justifyleft.ToolButton.insert(button_underline.RIGHT) 72 73 74 75 76 77 76 Chapter 15. 5) 60 61 62 63 radio_justifyright = Gtk.create_buttons() 31 32 33 34 def create_toolbar(self): toolbar = Gtk.on_button_clicked. self.STOCK_JUSTIFY_RIGHT) toolbar.on_justify_toggled.attach(toolbar.insert(radio_justifyleft.insert(button_bold.connect("toggled".ToolButton. 6) 64 65 66 67 radio_justifyfill = Gtk.tag_underline) 48 49 50 51 52 53 toolbar. 0.on_justify_toggled. self. title="TextView Example") 23 24 25 self.RadioToolButton() radio_justifyleft.new_from_stock(Gtk.new_from_stock(Gtk. self. Gtk.connect("clicked". self. self. Multiline Text Editor .connect("clicked".__init__(self.STOCK_JUSTIFY_CENTER) toolbar.insert(button_italic. 4) 56 57 58 59 radio_justifycenter = Gtk. Release 3.ToolButton.RadioToolButton.on_justify_toggled.grid = Gtk. ’italic’. 10) 88 89 90 91 button_search = Gtk. 1. 9) 86 87 toolbar.set_hexpand(True) scrolledwindow.textbuffer. 3.on_search_clicked) toolbar.grid. 11) 92 93 94 95 96 97 def create_textview(self): scrolledwindow = Gtk.BOLD) self.STOCK_CLEAR) button_clear.textbuffer = self.attach(scrolledwindow. self.Style.tag_found = self.insert(button_search. "No Wrapping") self.connect("toggled".on_cursor_toggled) self.create_tag("underline".CheckButton("Cursor Visible") check_cursor.insert(button_clear. 2.attach(check_editable. Example 77 .attach(radio_wrapnone. self.RIGHT.create_tag("found". underline=Pango.ToolButton.textview) 105 106 107 108 109 110 111 112 113 self.textview.The Python GTK+ 3 Tutorial.create_tag("italic".ToolButton.new_with_label_from_widget(None.4. Gtk.RadioButton.set_active(True) check_editable.textbuffer. " + "or ’underline’ to modify the text accordingly. " + "Select text and click one of the buttons ’bold’.new_with_label_from_widget( radio_wrapnone. 1.get_buffer() self.add(self. background="yellow") 114 115 116 117 118 119 def create_buttons(self): check_editable = Gtk.grid.grid.Underline.RadioButton. 1.grid.FILL) 80 81 toolbar. 1) 130 131 132 133 134 radio_wrapchar = Gtk.ScrolledWindow() scrolledwindow.ITALIC) self.tag_bold = self. 3.STOCK_FIND) button_search.connect("toggled".textbuffer. 1. self.PositionType.textbuffer. "Character Wrapping") self.SeparatorToolItem().attach_next_to(radio_wrapchar.SeparatorToolItem().insert(Gtk.on_clear_clicked) toolbar.set_active(True) check_editable.new_from_stock(Gtk.on_justify_toggled.insert(Gtk. 1) 120 121 122 123 124 125 check_cursor = Gtk. Gtk.") scrolledwindow.create_tag("bold".on_editable_toggled) self. 8) 82 83 84 85 button_clear = Gtk. 0. 1) 98 99 100 101 102 103 104 self.textbuffer.CheckButton("Editable") check_editable.new_from_stock(Gtk. check_editable.connect("toggled".TextView.textview = Gtk.grid.tag_italic = self. 1.TextView() self. 0.set_text("This is some text inside of a Gtk. self.Justification.RIGHT. 0.attach_next_to(check_cursor. 1) 135 15.Weight. radio_wrapnone. weight=Pango.4 78 79 radio_justifyfill. 1) 126 127 128 129 radio_wrapnone = Gtk. style=Pango. Gtk.tag_underline = self.SINGLE) self.PositionType. self.connect("clicked".connect("clicked".set_vexpand(True) self. Release 3. textbuffer.tag_found.grid.entry.CHAR) radio_wrapword.textbuffer.search_and_mark(text. self. match_end) self.textbuffer.ResponseType.new_with_label_from_widget( radio_wrapnone.connect("toggled". 1) 136 137 138 139 140 radio_wrapnone.NONE) radio_wrapchar. end) 154 155 156 157 158 def on_editable_toggled(self. Gtk.textview.textview.textbuffer.set_cursor_visible(widget.WrapMode. Release 3. start) 180 181 dialog.RIGHT. Gtk. "Word Wrapping") self.get_insert() start = self.textbuffer.set_wrap_mode(mode) 165 166 167 def on_justify_toggled(self.get_char_count(): start = self.textview. widget.textbuffer. end) 148 149 150 151 152 153 def on_clear_clicked(self.attach_next_to(radio_wrapword.OK: cursor_mark = self.WrapMode.get_iter_at_mark(cursor_mark) if start.textbuffer.The Python GTK+ 3 Tutorial.textbuffer.WrapMode. start): end = self.get_selection_bounds() if len(bounds) != 0: start. 0.set_editable(widget. widget): self.apply_tag(tag. text.on_wrap_toggled. justification): self.destroy() 182 183 def search_and_mark(self. widget. self.textbuffer.get_offset() == self.PositionType. match_start. mode): self. tag): bounds = self. radio_wrapchar.search_and_mark(dialog. Gtk.get_active()) 159 160 161 def on_cursor_toggled(self.connect("toggled".set_justification(justification) 168 169 170 def on_search_clicked(self.get_end_iter() match = start. widget): self. end = bounds self. match_end) 188 189 190 191 192 193 win = TextViewWindow() 78 Chapter 15. widget.forward_search(text.textbuffer.RadioButton.on_wrap_toggled.get_start_iter() end = self.WORD) 141 142 143 144 145 146 147 def on_button_clicked(self. Gtk.run() if response == Gtk. start. end) 184 185 186 187 if match != None: match_start. widget): dialog = SearchDialog(self) response = dialog. self.apply_tag(self.remove_all_tags(start.get_start_iter() 171 172 173 174 175 176 177 178 179 self.get_active()) 162 163 164 def on_wrap_toggled(self.get_text().textview.connect("toggled".on_wrap_toggled.get_end_iter() self. 1.4 radio_wrapword = Gtk. widget): start = self. match_end = match self. Multiline Text Editor .textbuffer. Gtk.4 194 195 196 win. Example 79 . Release 3.show_all() Gtk.main() 15.main_quit) win.connect("delete-event".The Python GTK+ 3 Tutorial.4. The Python GTK+ 3 Tutorial. Release 3.4 80 Chapter 15. Multiline Text Editor . ActionGroup. including its name (not for display). a tooltip.ActionGroup. 81 .ActionGroup is essentially a map from names to Gtk. Gtk. printing a page or undoing an operation. along with some information how it should be presented in the interface.RecentAction: An action of which represents a list of recently used files Actions represent operations that the user can be perform. you should use Gtk. Each window’s menus would be constructed from a combination of two action groups. 16.Toolbar widgets are used for quick accessibility to commonly used functions of an application.Toolbar. save. Examples include creating a new document.MenuItem instances or one of its subclasses. Actions are organised into groups.add_toggle_actions() • Gtk.ActionGroup.add_actions(). Different classes representing different types of actions exist: • Gtk. It contains one or more instances of Gtk. an accelerator. • Gtk. Gtk.ActionGroup. its label (for display). Multiple action groups may be used for a particular user interface.add_action() or Gtk. cut/copy/paste. and one group per document holding actions that act on that document (eg.Action instances. in an application that can edit multiple documents. etc). as well as the callback that is called when the action gets activated. In fact.ToolItem or one of its subclasses.add_radio_actions().g.MenuBar is a standard menu bar which contains one or more Gtk.add_action_with_accel(). quit. new).UIManager and create Gtk. Note that you must specify actions for sub menus as well as menu items. whether a label indicates a stock item.1 Actions Although.Action: An action which can be triggered by a menu or toolbar item • Gtk. All actions that would make sense to use in a particular context should be in a single group. one group holding global actions (e. For example. about. A Gtk.ActionGroup.Action objects. Gtk. there are specific APIs to create menus and toolbars. You can create actions by either calling one of the constructors directly and adding them to a Gtk.ActionGroup by calling Gtk.RadioAction: An action of which only one in a group can be active • Gtk.ToggleAction: An action which can be toggled between two states • Gtk. it is expected that most non-trivial applications will make use of multiple groups.MenuBar and Gtk.CHAPTER 16 Menus GTK+ comes with two different types of menus. or by calling one of the convenience functions: • Gtk. Release 3.The Python GTK+ 3 Tutorial.2 UI Manager Gtk.insert_action_group(). by using Gtk.4 16.get_widget() and add the widget to a container such as Gtk. First of all. They are not the text that the user will see in the menus and toolbars. in which you should mention the names of the actions that you have already created.UIManager provides an easy way of creating menus and toolbars using an XML-like description. Then. Remember that these names are just the identifiers that we used when creating the actions. This “ui string” uses an XML format. Menus .ActionGroup to the UI Manager with Gtk. you can define the actual visible layout of the menus and toolbars.Window.UIManager. 16. Finally. you should add the Gtk. We provided those human-readable names when we created the actions. Gdk 2 3 4 5 6 7 8 9 10 11 12 13 UI_INFO = """ <ui> <menubar name=’MenuBar’> <menu action=’FileMenu’> <menu action=’FileNew’> <menuitem action=’FileNewStandard’ /> <menuitem action=’FileNewFoo’ /> <menuitem action=’FileNewGoo’ /> </menu> <separator /> <menuitem action=’FileQuit’ /> 82 Chapter 16. you retrieve the root widget with Gtk.repository import Gtk.3 Example 1 from gi. At this point is also a good idea to tell the parent window to respond to the specified keyboard shortcuts.add_accel_group(). and add the UI layout.UIManager.get_accel_group() and Gtk.UIManager.Box. ActionGroup("my_actions") 47 48 49 50 self.set_default_size(200.get_widget("/ToolBar") box.Label("Right-click to see the popup menu.Box(orientation=Gtk. False.on_button_press_event) box.The Python GTK+ 3 Tutorial.4 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 </menu> <menu action=’EditMenu’> <menuitem action=’EditCopy’ /> <menuitem action=’EditPaste’ /> <menuitem action=’EditSomething’ /> </menu> <menu action=’ChoicesMenu’> <menuitem action=’ChoiceOne’/> <menuitem action=’ChoiceTwo’/> <separator /> <menuitem action=’ChoiceThree’/> </menu> </menubar> <toolbar name=’ToolBar’> <toolitem action=’FileNewStandard’ /> <toolitem action=’FileQuit’ /> </toolbar> <popup name=’PopupMenu’> <menuitem action=’EditCopy’ /> <menuitem action=’EditPaste’ /> <menuitem action=’EditSomething’ /> </popup> </ui> """ 38 39 class MenuExampleWindow(Gtk.get_widget("/MenuBar") 56 57 58 box = Gtk. False. title="Menu Example") 43 44 self.add(label) 69 70 self. False. False.EventBox() eventbox.Orientation.Window): 40 41 42 def __init__(self): Gtk. True.pack_start(toolbar. 200) 45 46 action_group = Gtk. Release 3.connect("button-press-event".__init__(self.pack_start(eventbox. 0) 66 67 68 label = Gtk.VERTICAL) box. Example 83 .insert_action_group(action_group) 54 55 menubar = uimanager. self. True. 0) 59 60 61 toolbar = uimanager. 0) 62 63 64 65 eventbox = Gtk.add_choices_menu_actions(action_group) 51 52 53 uimanager = self.get_widget("/PopupMenu") 71 16.pack_start(menubar.add_file_menu_actions(action_group) self.create_ui_manager() uimanager.3.popup = uimanager.") eventbox.add_edit_menu_actions(action_group) self.Window. Action("FileMenu".on_menu_choices_toggled) action_group. None.get_accel_group() self. None. self. None. None. None. ("ChoiceTwo". None. self.STOCK_PASTE.connect("activate".UIManager() 121 122 123 # Throws exception if something went wrong uimanager.on_menu_file_new_generic).add_action(action_filemenu) 74 75 76 77 action_filenewmenu = Gtk.on_menu_file_quit) action_group. None.on_menu_others). None. None) three.on_menu_file_new_generic).connect("toggled".Action("FileQuit". ]) 86 87 88 89 90 91 92 action_filequit = Gtk. None. None. None.The Python GTK+ 3 Tutorial. None. None.add_action(three) 117 118 119 120 def create_ui_manager(self): uimanager = Gtk. None. None. "Three". None. Release 3. action_group): action_filemenu = Gtk. Gtk.STOCK_NEW) action_group.connect("activate".add_radio_actions([ ("ChoiceOne". self. Gtk. None. self. None) action_group.STOCK_NEW) action_new.add_action_with_accel(action_new.ToggleAction("ChoiceThree". "Two".STOCK_COPY. None. None. "<control><alt>S". "Something". Gtk. self.on_menu_choices_changed) 112 113 114 115 116 three = Gtk. Gtk.on_menu_file_new_generic) action_group.add_actions([ ("EditMenu". None. "Choices". "New Foo".add_action(Gtk. self.on_menu_others). self.STOCK_QUIT) action_filequit.add_actions([ ("FileNewFoo". "Create new foo". Menus . 2) ]. None. None. "Edit").add_action(action_filenewmenu) 78 79 80 action_new = Gtk.add_ui_from_string(UI_INFO) 124 125 126 # Add the accelerator group to the toplevel window accelgroup = uimanager. "_New Goo". None. action_group): action_group.add_accel_group(accelgroup) 127 128 129 84 Chapter 16. None. None) 81 82 83 84 85 action_group. "One". ("EditCopy". ("EditPaste". "Create a new file". self. ("EditSomething". None.Action("ChoicesMenu".add(box) 72 73 def add_file_menu_actions(self. 1.Action("FileNewStandard".4 self. "File".add_action(action_filequit) 93 94 95 96 def add_edit_menu_actions(self. action_group): action_group.Action("FileNew".on_menu_others) ]) 97 98 99 100 101 102 103 104 105 106 107 def add_choices_menu_actions(self. None)) 108 109 110 111 action_group. 1). self. None. Gtk. "Create new goo". ("FileNewGoo". "_New". BUTTON_PRESS and event. widget): print("A File|New menu item was selected. None.") 134 135 136 def on_menu_file_quit(self.main_quit) window.button == 3: self. widget): Gtk.popup(None. event. current): print(current.time) return True # event has been handled 155 156 157 158 159 window = MenuExampleWindow() window. None.popup.4 130 return uimanager 131 132 133 def on_menu_file_new_generic(self.button. Release 3. event.The Python GTK+ 3 Tutorial.get_active(): print(widget. Example 85 . widget.connect("delete-event".show_all() Gtk.get_name() + " deactivated") 149 150 151 152 153 154 def on_button_press_event(self. widget. widget): if widget. widget): print("Menu item " + widget.type == Gdk.get_name() + " was selected") 140 141 142 def on_menu_choices_changed(self.") 143 144 145 146 147 148 def on_menu_choices_toggled(self.main_quit() 137 138 139 def on_menu_others(self. Gtk.get_name() + " was selected. None.main() 16. event): # Check if right mouse button was preseed if event.3.EventType.get_name() + " activated") else: print(widget. Menus .The Python GTK+ 3 Tutorial. Release 3.4 86 Chapter 16. however keeps it stored in memory.Dialog.Dialog. one which freezes the rest of the application from user input). you can call Gtk.Box.ResponseType or it could be the custom response value that you specified in the Gtk. buttons.Button to the bottom of the dialog. From there. There are several derived Dialog classes which you might find useful.Widget.set_modal on the dialog or set the flags argument of the Gtk. can be created by calling Gtk.hide() method removes the dialog from view.get_content_area().add_button(). It should be noted that if the dialog needs to be accessed after it has been destroyed. 87 . you should pack them into the Gtk. They are often used to provide a preferences window.1 Custom Dialogs To pack widgets into a custom dialog. and are used to provide or retrieve information from the user. Finally. A ‘modal’ dialog (that is. we can simply add labels. it will need to be constructed again otherwise the dialog window will be empty. This is useful to prevent having to construct the dialog again if it needs to be accessed at a later time. for example. If you want to block waiting for a dialog to return before returning control flow to your code.Dialog constructor or Gtk.Widget.Dialog constructor to include the Gtk.add_button() method.DialogFlags. But at other times you might need to derive your own dialog class to provide more complex functionality. The major difference a dialog has is some prepacked widgets which layout the dialog automatically. you could use the Gtk.Dialog. 17. The Gtk. Clicking a button will emit a signal called “response”.CHAPTER 17 Dialogs Dialog windows are very similar to standard windows. Gtk. To just add a Gtk. check buttons.MessageDialog is used for most simple notifications.run(). the Gtk. This method returns an int which may be a value from the Gtk.destroy() method can be used to delete the dialog from memory once it is no longer needed. etc.MODAL flag. Another big difference is the handling of responses to control how the application should behave after the dialog has been interacted with.Dialog. Alternatively.Dialog. available via Gtk. there are two ways to remove a dialog. Window.Label("This is a dialog to display additional information") 12 13 box = self. Gtk.repository import Gtk 2 3 class DialogExample(Gtk.CANCEL. parent.CANCEL: print("The Cancel button was clicked") 34 35 36 37 38 dialog.set_default_size(150. widget): dialog = DialogExample(self) response = dialog. Release 3.OK)) 5 6 7 8 9 self.connect("clicked".ResponseType. title="Dialog Example") 20 21 22 self.__init__(self.connect("delete-event".Window): 19 def __init__(self): Gtk.ResponseType.show_all() 88 Chapter 17.destroy() 39 40 41 42 43 win = DialogWindow() win.ResponseType. Gtk.1.on_button_clicked) 25 26 27 self.main_quit) win.1 Example 1 from gi.add(label) self. Gtk.STOCK_OK.__init__(self.set_border_width(6) 23 24 button = Gtk.ResponseType.4 17.run() 30 31 32 33 if response == Gtk. parent): Gtk.Dialog): 4 def __init__(self. 100) 10 11 label = Gtk. (Gtk. Dialogs . Gtk.Button("Open dialog") button.add(button) 28 29 def on_button_clicked(self.show_all() 14 15 16 17 18 class DialogWindow(Gtk. self. 0. "My Dialog".The Python GTK+ 3 Tutorial.STOCK_CANCEL.get_content_area() box.OK: print("The OK button was clicked") elif response == Gtk.Dialog. 1 Example 1 from gi.Button("Question") button4.add(box) 10 11 12 13 button1 = Gtk.on_warn_clicked) box.connect("clicked".Box(spacing=6) self. title="MessageDialog Example") 7 8 9 box = Gtk.MessageDialog constructor.repository import Gtk 2 3 class MessageDialogWindow(Gtk.Button("Information") button1. In some dialogs which require some further explanation of what has happened.Button("Error") button2. self.The Python GTK+ 3 Tutorial.main() 17. and buttons for user response You can specify the type of message and the text in the Gtk.MessageDialog is a convenience class.connect("clicked".Window): 4 5 6 def __init__(self): Gtk.4 44 Gtk.__init__(self. used to create simple.connect("clicked".add(button1) 14 15 16 17 button2 = Gtk. self. self.on_question_clicked) 17.add(button3) 22 23 24 button4 = Gtk. MessageDialog 89 .2.format_secondary_text(). with a message.2.2 MessageDialog Gtk. 17.connect("clicked".Window.MessageDialog. standard message dialogs.on_info_clicked) box. self. a secondary text can be added. In this case. as well as specifying standard buttons. The secondary message can be set by calling Gtk.add(button2) 18 19 20 21 button3 = Gtk. the primary message entered when creating the message dialog is made bigger and set to bold text.Button("Warning") button3. an icon.on_error_clicked) box. Release 3. ResponseType.destroy() 35 36 def on_error_clicked(self.MessageDialog(self.ResponseType. widget): dialog = Gtk.show_all() Gtk. Gtk.") response = dialog. Gtk.main_quit) win. Gtk.4 box.format_secondary_text( "And this is the secondary text that explains things.The Python GTK+ 3 Tutorial.destroy() 71 72 73 74 75 76 win = MessageDialogWindow() win.MessageType.YES: print("QUESTION dialog closed by clicking YES button") elif response == Gtk. "This is an INFO MessageDialog") dialog.CANCEL: print("WARN dialog closed by clicking CANCEL button") 47 48 49 50 51 52 53 54 55 56 57 dialog. "This is an WARNING MessageDialog") dialog.MessageType.OK_CANCEL.INFO.run() if response == Gtk. widget): dialog = Gtk.run() print("ERROR dialog closed") 37 38 39 40 41 42 43 44 dialog.") dialog. Gtk. Gtk. 0. Gtk. Gtk. 0.QUESTION. widget): dialog = Gtk.format_secondary_text( "And this is the secondary text that explains things. "This is an ERROR MessageDialog") dialog.format_secondary_text( "And this is the secondary text that explains things.ButtonsType.connect("delete-event".ResponseType.ERROR.ButtonsType. 0.main() 90 Chapter 17. Gtk.WARNING.run() if response == Gtk.add(button4) 25 26 def on_info_clicked(self.MessageType.ButtonsType.OK.MessageDialog(self.") response = dialog. Dialogs .destroy() 45 46 def on_warn_clicked(self.YES_NO.destroy() 58 59 def on_question_clicked(self. Release 3.MessageType.NO: print("QUESTION dialog closed by clicking NO button") 60 61 62 63 64 65 66 67 68 69 70 dialog. 0.CANCEL. widget): dialog = Gtk.ResponseType.MessageDialog(self.format_secondary_text( "And this is the secondary text that explains things.OK: print("WARN dialog closed by clicking OK button") elif response == Gtk. "This is an QUESTION MessageDialog") dialog. Gtk.run() print("INFO dialog closed") 27 28 29 30 31 32 33 34 dialog.") dialog.MessageDialog(self.ButtonsType. 17.ResponseType.The Python GTK+ 3 Tutorial.APPLY When the user is finished selecting files.FileChooser only allows a single file to be selected at a time.FileChooser.SELECT_FOLDER.show_hidden(): Hidden files and folders are displayed.FileChooserDialog is suitable for use with “File/Open” or “File/Save” menu items. name. use Gtk.get_uri()).add_filter().FileChooserAction.FileChooser methods on the file chooser dialog as well as those for Gtk.4 17.SAVE mode. so buttons have response IDs such as Gtk. your program can get the selected names either as filenames (Gtk. use Gtk. Release 3. Gtk. as for a File/Save command.YES • Gtk.set_current_name(). the existing filename with • To choose a folder instead of a file.FileChooserDialog constructor. you can not use custom response codes with Gtk. as for a File/Open command.FileChooser. and as set for a File/Save As command.set_do_overwrite_confirmation(): If the file chooser was configured in Gtk.SAVE. Gtk. use Gtk.FileChooser.3 FileChooserDialog The Gtk.SAVE. you can specify which kind of files are displayed by creating Gtk. Gtk. When creating a Gtk. By default.get_uris().set_select_multiple(). Gtk.ResponseType. You can use all of the Gtk. and suggest a name such as “Untitled” with Gtk.FileChooserAction.get_filename()) or as URIs (Gtk.OPEN • To save a file for the first time.FileChooserAction. The user can then select one of the added filters from a combo box at the bottom of the file chooser.FileChooser also supports a variety of options which make the files and folders more configurable and accessible.Dialog.set_filename(). • Gtk. To enable multiple files to be selected.ACCEPT and Gtk. • To save a file under a different use Gtk.Dialog. Furthermore.FileChooser.FileChooserDialog. • Gtk.ResponseType.OK • Gtk.FileChooserDialog inherits from Gtk.Dialog. Retrieving a list of selected files is possible with either Gtk.CANCEL which can be specified in the Gtk.get_filenames() or Gtk. • Gtk.FileChooserAction.FileFilter objects and calling Gtk.FileChooserDialog you have to define the dialog’s purpose: • To select a file for opening.FileChooser.FileChooser.3.FileChooser. it will present a confirmation dialog if the user types a file name that already exists. use Gtk. FileChooserDialog 91 .ACCEPT • Gtk. It expects that at least one button will have of the following response IDs: • Gtk.ResponseType.FileChooser.ResponseType.FileChooser.FileChooserAction.FileChooser. In contrast to Gtk.ResponseType.set_local_only(): Only local files can be selected.FileChooser. Release 3. 19 20 21 22 92 Chapter 17.Window.3.1 Example 1 from gi.CANCEL.on_file_clicked) box.Window): 4 def __init__(self): Gtk.repository import Gtk 2 3 class FileChooserWindow(Gtk.add(button1) 11 12 13 14 button2 = Gtk.STOCK_CANCEL.The Python GTK+ 3 Tutorial. Dialogs .Box(spacing=6) self. self.Button("Choose File") button1.add(button2) 15 16 17 18 def on_file_clicked(self.Button("Choose Folder") button2.on_folder_clicked) box. self.4 17.ResponseType.connect("clicked". Gtk. self. widget): dialog = Gtk.add(box) 8 9 10 button1 = Gtk. Gtk. (Gtk.FileChooserAction.OPEN.connect("clicked". title="FileChooser Example") 5 6 7 box = Gtk.__init__(self.FileChooserDialog("Please choose a file". The Python GTK+ 3 Tutorial, Release 3.4 23 Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) 24 25 self.add_filters(dialog) 26 27 28 29 30 31 32 response = dialog.run() if response == Gtk.ResponseType.OK: print("Open clicked") print("File selected: " + dialog.get_filename()) elif response == Gtk.ResponseType.CANCEL: print("Cancel clicked") 33 34 dialog.destroy() 35 36 37 38 39 40 def add_filters(self, dialog): filter_text = Gtk.FileFilter() filter_text.set_name("Text files") filter_text.add_mime_type("text/plain") dialog.add_filter(filter_text) 41 42 43 44 45 filter_py = Gtk.FileFilter() filter_py.set_name("Python files") filter_py.add_mime_type("text/x-python") dialog.add_filter(filter_py) 46 47 48 49 50 filter_any = Gtk.FileFilter() filter_any.set_name("Any files") filter_any.add_pattern("*") dialog.add_filter(filter_any) 51 52 53 54 55 56 57 def on_folder_clicked(self, widget): dialog = Gtk.FileChooserDialog("Please choose a folder", self, Gtk.FileChooserAction.SELECT_FOLDER, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, "Select", Gtk.ResponseType.OK)) dialog.set_default_size(800, 400) 58 59 60 61 62 63 64 response = dialog.run() if response == Gtk.ResponseType.OK: print("Select clicked") print("Folder selected: " + dialog.get_filename()) elif response == Gtk.ResponseType.CANCEL: print("Cancel clicked") 65 66 dialog.destroy() 67 68 69 70 71 win = FileChooserWindow() win.connect("delete-event", Gtk.main_quit) win.show_all() Gtk.main() 17.3. FileChooserDialog 93 The Python GTK+ 3 Tutorial, Release 3.4 94 Chapter 17. Dialogs CHAPTER 18 Clipboard Gtk.Clipboard provides a storage area for a variety of data, including text and images. Using a clipboard allows this data to be shared between applications through actions such as copying, cutting, and pasting. These actions are usually done in three ways: using keyboard shortcuts, using a Gtk.MenuItem, and connecting the functions to Gtk.Button widgets. There are multiple clipboard selections for different purposes. In most circumstances, the selection named CLIPBOARD is used for everyday copying and pasting. PRIMARY is another common selection which stores text selected by the user with the cursor. 18.1 Example 1 from gi.repository import Gtk, Gdk 2 3 class ClipboardWindow(Gtk.Window): 4 5 6 def __init__(self): Gtk.Window.__init__(self, title="Clipboard Example") 7 8 table = Gtk.Table(3, 2) 9 10 11 12 self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) self.entry = Gtk.Entry() self.image = Gtk.Image.new_from_stock(Gtk.STOCK_STOP, Gtk.IconSize.MENU) 13 14 15 16 17 button_copy_text = Gtk.Button("Copy Text") button_paste_text = Gtk.Button("Paste Text") button_copy_image = Gtk.Button("Copy Image") button_paste_image = Gtk.Button("Paste Image") 18 95 clipboard.paste_image) 26 27 28 29 30 self.connect("clicked".entry.The Python GTK+ 3 Tutorial. self.set_from_pixbuf(image) 49 50 51 52 53 54 55 56 57 58 win = ClipboardWindow() win.set_text(text) else: print("No text on the clipboard. widget): text = self.ImageType. 3. 3. 2) table. 0.entry. 1.clipboard. 2. 2) 19 20 21 22 23 24 25 button_copy_text. Clipboard .") 43 44 45 46 47 48 def paste_image(self. self.main_quit) win.attach(button_paste_image. 0.get_pixbuf()) else: print("No image has been pasted yet. 0.attach(self.attach(button_copy_text. 1.clipboard.clipboard. 0.attach(self.paste_text) button_copy_image. -1) 33 34 35 def paste_text(self. 2.get_text().image.wait_for_image() if image != None: self.image.set_text(self. Gtk.connect("clicked".copy_text) button_paste_text. 1. 2) table. 1.connect("clicked". 0. 1.connect("clicked".image.wait_for_text() if text != None: self.main() 96 Chapter 18.add(table) 31 32 def copy_text(self.connect("delete-event". widget): if self. widget): self.attach(button_paste_text. 2. 1) table. self. 2.attach(button_copy_image. self.show_all() Gtk.copy_image) button_paste_image. 1) table. 1) table. Release 3. 1.entry.image.get_storage_type() == Gtk.4 table.") 36 37 38 39 40 41 42 def copy_image(self. widget): image = self.PIXBUF: self. 1.set_image(self. drag_dest_set() some specialised widgets require the use of specific functions (such as Gtk. Setting up drag and drop between widgets consists of selecting a drag source (the widget which the user starts the drag from) with the Gtk. you will need to create the Gtk.SelectionData variable supplied in the “drag-data-get” and “drag-data-received” signals using the Gtk.TargetEntry’s to a source and destination.drag_source_set() method.drag_dest_set() method and then handling the relevant signals on both widgets. you can use the group of methods mentioned here.SelectionData get and set methods. a common list of Gtk. Therefore a version of PyGObject >= 3.TargetEntry’s using the Gtk. If you require more than one type of data or wish to do more complex things with the data. selecting a drag destination (the widget which the user drops onto) with the Gtk.TreeView and Gtk. A Gtk. In order to transfer data between the source and destination. A basic drag and drop only requires the source to connect to the “drag-data-get” signal and the destination to connect to the “drag-data-received” signal.TargetEntry describes a piece of data that will be sent by the drag source and received by the drag destination.TargetEntry’s are required.IconView). If the drag and drop is simple and each target entry is of a different type.3 contain a bug which does not allow drag and drop to function correctly.Widget.drag_source_set() and Gtk. 19.Widget. Instead of using Gtk.0. 97 . There are two ways of adding Gtk.CHAPTER 19 Drag and Drop Note: Versions of PyGObject < 3.DragContext object it supplies.Widget.1 Target Entries To allow the drag source and destination to know what data they are receiving and sending.3 is required for the following examples to work.Widget. More complex things such as specific drop areas and custom drag icons will require you to connect to additional signals and interact with the Gdk.0.TargetEntry.new() method. you must interact with the Gtk. MOVE is completed When the drag is complete Common Purpose Set-up drag icon Transfer drag data from source to destination Delete data from the source to complete the ‘move’ Undo anything done in drag-begin 19.repository import Gtk.The Python GTK+ 3 Tutorial.2 Drag Source Signals Name drag-begin drag-dataget drag-datadelete drag-dataend When it is emitted User starts a drag When drag data is requested by the destination When a drag with the action Gdk. TARGET_ENTRY_PIXBUF) = range(2) (COLUMN_TEXT. COLUMN_PIXBUF) = range(2) 98 Chapter 19.4 Example 1 from gi.3 Drag Destination Signals Name drag-motion drag-drop drag-datareceived When it is emitted Drag icon moves over a drop area Icon is dropped onto a drag area When drag data is received by the destination Common Purpose Allow only certain areas to be dropped onto Allow only certain areas to be dropped onto Transfer drag data from source to destination 19.4 19. Gdk. GdkPixbuf 2 3 4 (TARGET_ENTRY_TEXT.DragAction. Release 3. Drag and Drop . new_with_label_from_widget(image_button. True.add(vbox) 15 16 17 hbox = Gtk.Orientation.Window. 0) 24 25 26 button_box = Gtk. True.add_text_targets) button_box. 0) 27 28 29 30 31 image_button = Gtk.connect("toggled".DragAction. 0) hbox.iconview.Box(spacing=6) vbox.iconview = DragSourceIconView() self. True.pack_start(image_button. False.IconView. button=None): targets = Gtk.IconView): 55 56 57 58 59 def __init__(self): Gtk.COPY 7 8 class DragDropWindow(Gtk. 0) 18 19 20 self.add_image_targets() 39 40 41 42 def add_image_targets(self. 0) 37 38 self.drop_area.pack_start(hbox. True.RadioButton.drag_source_set_target_list(None) 50 51 52 self.__init__(self.connect("toggled". GdkPixbuf.TargetList.Window): 9 10 11 def __init__(self): Gtk.pack_start(self.add_image_targets) button_box.add_image_targets(TARGET_ENTRY_PIXBUF.Box(spacing=12) vbox. 0) 32 33 34 35 36 text_button = Gtk.4.The Python GTK+ 3 Tutorial. True.drag_dest_set_target_list(targets) self.4 5 6 DRAG_ACTION = Gdk. spacing=6) self. title="Drag and Drop Demo") 12 13 14 vbox = Gtk. True.__init__(self) self. False.drop_area = DropArea() 21 22 23 hbox.set_text_column(COLUMN_TEXT) self.iconview.RadioButton.drop_area.pack_start(text_button.iconview. True. self.pack_start(button_box.drop_area. True.Box(orientation=Gtk. True) 43 44 45 self. Example 99 .pack_start(self.set_model(model) 19.drag_source_set_target_list(targets) 46 47 48 49 def add_text_targets(self.drag_dest_set_target_list(None) self.set_pixbuf_column(COLUMN_PIXBUF) 60 61 62 model = Gtk.new_with_label_from_widget(None.ListStore(str.drag_dest_add_text_targets() self.VERTICAL.Pixbuf) self. "Text") text_button. False. self. button=None): self.drag_source_add_text_targets() 53 54 class DragSourceIconView(Gtk. Release 3.drop_area. "Images") image_button.iconview.new([]) targets. True. 4 self.__init__(self. icon_name): pixbuf = Gtk. drag_context. info. [].get_selected_items()[0] selected_iter = self.get_model().connect("drag-data-received".Label): 88 def __init__(self): Gtk.get_model(). self.y.on_drag_data_get) 67 68 69 70 def on_drag_data_get(self.get_default().connect("drag-data-get". widget. data.append([text.Label.get_model(). DRAG_ACTION) 89 90 91 92 self.DestDefaults.ALL. time): selected_path = self. 16.main() 100 Chapter 19. x. widget. "gtk-about") self. pixbuf]) 82 83 84 85 86 87 class DropArea(Gtk. Drag and Drop . self.on_drag_data_received) 93 94 def on_drag_data_received(self.IconTheme.BUTTON1_MASK. Release 3.enable_model_drag_source(Gdk.get_text() print("Received text: %s" % text) 95 96 97 98 99 elif info == TARGET_ENTRY_PIXBUF: pixbuf = data. -1) elif info == TARGET_ENTRY_PIXBUF: pixbuf = self. height)) 105 106 107 108 109 110 111 win = DragDropWindow() win.get_pixbuf() width = pixbuf.get_value(selected_iter.add_item("Item 3". text.set_pixbuf(pixbuf) 75 76 77 78 79 80 81 def add_item(self.get_value(selected_iter. "Drop something on me!") self.info.load_icon(icon_name.set_text(text. time): if info == TARGET_ENTRY_TEXT: text = data.ModifierType.add_item("Item 2".drag_dest_set(Gtk. 0) self. Gtk.connect("delete-event". []. "edit-copy") 63 64 65 66 self.add_item("Item 1".get_width() height = pixbuf.main_quit) win.The Python GTK+ 3 Tutorial. DRAG_ACTION) self. COLUMN_PIXBUF) data.get_height() 100 101 102 103 104 print("Received pixbuf with width %spx and height %spx" % (width. "image") self. data.show_all() Gtk. drag_context. COLUMN_TEXT) data.get_iter(selected_path) 71 72 73 74 if info == TARGET_ENTRY_TEXT: text = self.get_model(). CHAPTER 20 Glade and Gtk.Builder The Gtk.Builder class offers you the opportunity to design user interfaces without writing a single line of code. This is possible through describing the interface by a XML file and then loading the XML description at runtime and create the objects automatically, which the Builder class does for you. For the purpose of not needing to write the XML manually the Glade application lets you create the user interface in a WYSIWYG (what you see is what you get) manner This method has several advantages: • Less code needs to be written. • UI changes can be seen more quickly, so UIs are able to improve. • Designers without programming skills can create and edit UIs. • The description of the user interface is independent from the programming language being used. There is still code required for handling interface changes triggered by the user, but Gtk.Builder allows you to focus on implementing that functionality. 20.1 Creating and loading the .glade file First of all you have to download and install Glade. There are several tutorials about Glade, so this is not explained here in detail. Let’s start by creating a window with a button in it and saving it to a file named example.glade. The resulting XML file should look like this. <?xml version="1.0" encoding="UTF-8"?> <interface> <!-- interface-requires gtk+ 3.0 --> <object class="GtkWindow" id="window1"> <property name="can_focus">False</property> <child> <object class="GtkButton" id="button1"> <property name="label" translatable="yes">button</property> <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> <property name="use_action_appearance">False</property> </object> </child> </object> </interface> 101 The Python GTK+ 3 Tutorial, Release 3.4 To load this file in Python we need a Gtk.Builder object. builder = Gtk.Builder() builder.add_from_file("example.glade") The second line loads all objects defined in example.glade into the Builder object. It is also possible to load only some of the objects. The following line would add only the objects (and their child objects) given in the tuple. # we don’t really have two buttons here, this is just an example builder.add_objects_from_file("example.glade", ("button1", "button2")) These two methods exist also for loading from a string rather than a file. Their corresponding names are Gtk.Builder.add_from_string() and Gtk.Builder.add_objects_from_string() and they simply take a XML string instead of a file name. 20.2 Accessing widgets Now that the window and the button are loaded we also want to show them. Therefore the Gtk.Window.show_all() method has to be called on the window. But how do we access the associated object? window = builder.get_object("window1") window.show_all() Every widget can be retrieved from the builder by the Gtk.Builder.get_object() method and the widget’s id. It is really that simple. It is also possible to get a list of all objects with builder.get_objects() 20.3 Connecting Signals Glade also makes it possible to define signals which you can connect to handlers in your code without extracting every object from the builder and connecting to the signals manually. The first thing to do is to declare the signal names in Glade. For this example we will act when the window should be closed and when the button was pressed, so we give the name “onDeleteWindow” to the “delete-event” signal of the window and “onButtonPressed” to the “pressed” signal of the button. Now the XML file should look like this. <?xml version="1.0" encoding="UTF-8"?> <interface> <!-- interface-requires gtk+ 3.0 --> <object class="GtkWindow" id="window1"> <property name="can_focus">False</property> <signal name="delete-event" handler="onDeleteWindow" swapped="no"/> <child> <object class="GtkButton" id="button1"> <property name="label" translatable="yes">button</property> <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> <property name="use_action_appearance">False</property> 102 Chapter 20. Glade and Gtk.Builder The Python GTK+ 3 Tutorial, Release 3.4 <signal name="pressed" handler="onButtonPressed" swapped="no"/> </object> </child> </object> </interface> Now we have to define the handler functions in our code. The onDeleteWindow should simply result in a call to Gtk.main_quit(). When the button is pressed we would like to print the string “Hello World!”, so we define the handler as follows def hello(button): print "Hello World!" Next, we have to connect the signals and the handler functions. The easiest way to do this is to define a dict with a mapping from the names to the handlers and then pass it to the Gtk.Builder.connect_signals() method. handlers = { "onDeleteWindow": Gtk.main_quit, "onButtonPressed": hello } builder.connect_signals(handlers) An alternative approach is to create a class which has methods that are called like the signals. In our example the last code snippet could be rewritten as: 1 2 3 class Handler: def onDeleteWindow(self, *args): Gtk.main_quit(*args) 4 5 6 def onButtonPressed(self, button): print("Hello World!") 7 8 9 10 builder = Gtk.Builder() builder.add_from_file("builder_example.glade") builder.connect_signals(Handler()) 20.4 Example The final code of the example 1 from gi.repository import Gtk 2 3 4 5 class Handler: def onDeleteWindow(self, *args): Gtk.main_quit(*args) 6 7 8 def onButtonPressed(self, button): print("Hello World!") 9 10 11 12 builder = Gtk.Builder() builder.add_from_file("builder_example.glade") builder.connect_signals(Handler()) 13 14 15 window = builder.get_object("window1") window.show_all() 16 17 Gtk.main() 20.4. Example 103 4 104 Chapter 20. Release 3.The Python GTK+ 3 Tutorial. Glade and Gtk.Builder . It may be interesting to make an inherited class to create a new widget.GObject. 21. For example. like a settings dialog. and signal support. we generally use inherited class.CHAPTER 21 Objects GObject is the fundamental type providing the common attributes and methods for all object types in GTK+. Pango and other libraries based on GObject.GObject A native GObject is accessible via GObject. in GTK+. every user event (keystroke or mouse move) is received from the X server and generates a GTK+ event under the form of a signal emission on a given object instance.Widget is an inherited class of a GObject.GObject. Users can also emit the signal by themselves or stop the emission of the signal from within one of the functions connected to the signal. 21.__init__() for instance). it must call Gtk.Button.2.GObject.GObject. A Gtk.GObject class provides methods for object construction and destruction. It is rarely instantiated directly. Each signal is registered in the type system together with the type on which it can be emitted: users of the type are said to connect to the signal on a given type instance when they register a function to be invoked upon the signal emission.GObject.repository import GObject class MyObject(GObject. The GObject.1 Inherit from GObject. property access methods.2 Signals Signals connect arbitrary application-specific events with any number of listeners. This section will introduce some important aspects about the GObject implementation in python. you must call GObject. To inherit from GObject.__init__() in your constructor (if the class inherits from Gtk.GObject): def __init__(self): GObject.Button. like in the example below: from gi.1 Receive signals See Main loop and Signals 105 .__init__(self) 21. GObject): foo = GObject. float. This argument type list must end with a comma. you can’t change the type of a property once it is defined. A property can be created using GObject. (int. it will be called each time the signal is emitted. there are two functions to get and set them.property(type=str. class MyObject(GObject.__gsignals__. For the property “label” of a button. Each property has a type which never changes (e. a dictionary: When a new signal is created.GObject.set_label(). the signal will only take one argument.) indicates the signal arguments.).. from gi.2 Create new signals New signals can be created by adding them to GObject.emit("my_signal". with the # argument 42 21.GObject): __gsignals__ = { ’my_signal’: (GObject. called getter and setter. 21. The second part.repository import GObject class MyObject(GObject.SIGNAL_RUN_FIRST indicates that this signal will invoke the object method handler (do_my_signal() here) in the first emission stage.GObject. Signals can be emitted using GObject.emit(): my_obj. properties.)) } def do_my_signal(self. Gtk. Release 3. Some properties also have functions dedicated to them. 21. arg): print "class method for ‘my_signal’ called with argument".3 Properties One of GObject’s nice features is its generic get/set mechanism for object properties.3. here.g.set_property().property(). Each class inherited from GObject. int. 42) # emit the signal "my_signal".2. indicates the return type of the signal.3. str. None. (int. None.Button.Button. they are used for Gtk.4 21.GObject provides several useful functions to manage existing GObject.Button where there is a “label” property which contains the text of the button.get_property() and GObject.The Python GTK+ 3 Tutorial.SIGNAL_RUN_FIRST.2 Create new properties A property is defined with a name and a type. whose type is int. Objects .SIGNAL_RUN_CLEANUP (invoke the method handler in the last emission stage).1 Use existing properties The class GObject.get_label() and Gtk. Even if python itself is dynamically typed.GObject. It is called do_signal_name. a method handler can also be defined.. For instance.GObject can define new properties. Alternatives are GObject.GObject. arg GObject.SIGNAL_RUN_LAST (the method handler will be invoked in the third emission stage) and GObject. default=’bar’) 106 Chapter 21. usually None. property(type=str. GObject.__init__(self) @GObject.GObject.3. # min 5.readonly print my_object.GObject): def __init__(self): GObject.4 property_float = GObject.name == ’int-prop’: return self.__init__(self) Properties can also be read-only.GObject.PARAM_READABLE (only read access for external code). } def __init__(self): GObject. you can add some flags to the property definition.GObject): __gproperties__ = { "int-prop": (int. flags = GObject.repository import GObject class MyObject(GObject.repository import GObject class MyObject(GObject.’ You can get this property using: my_object = MyObject() print my_object.name def do_set_property(self. Release 3. # max 2. GObject. value): 21. # nick "A property that contains an integer". using a more verbose form: from gi. flags = GObject. Flags are GObject.int_prop = 2 def do_get_property(self. to control read/write access.property(type=str.get_property("readonly") There is also a way to define minimum and maximum values for numbers. Properties 107 . To do so.property def readonly(self): return ’This is read-only. # default GObject. prop): if prop. # type "integer prop".__init__(self) self. # blurb 1.PARAM_WRITABLE (only write access). prop.PARAM_WRITABLE) # not readable You can also define new read-only properties with a new method decorated with GObject.property(): from gi.GObject.PARAM_READWRITE # flags ).The Python GTK+ 3 Tutorial.PARAM_READABLE) # not writable bar = GObject.PARAM_READWRITE (public): foo = GObject. if you want some properties to be readable but not writable.int_prop else: raise AttributeError. ’unknown property %s’ % prop.property(type=float) def __init__(self): GObject. 3.name == ’int-prop’: self. and handled in do_get_property and do_set_property.g.emit(signal_name. 21.__gproperties__. whose name is “notify::property_name”: my_object = MyObject() def on_notify_foo(obj. Signal arguments must follow. Release 3.). 42) freeze_notify() This method freezes all the “notify::” signals (which are emitted when any property is changed) until the thaw_notify() method is called.The Python GTK+ 3 Tutorial.4 if prop. if your signal is of type (int. a dictionary.set_property("foo".. emit(signal_name.name Properties must be defined in GObject. gparamstring): print "foo changed" my_object. Objects . e.3 Watch properties When a property is modified. a signal is emitted..connect("notify::foo". ’unknown property %s’ % prop.GObject get_property(property_name) Retrieves a property value.freeze_notify(): # Do your work here . on_notify_foo) my_object. value) Set property property_name to value. 108 Chapter 21. "bar") # on_notify_foo will be called 21. that way it is ensured that thaw_notify() is called implicitly at the end of the block: with an_object.. thaw_notify() Thaw all the “notify::” signals which were thawed by freeze_notify().int_prop = value else: raise AttributeError.. it must be emitted with: self. set_property(property_name. It recommended to use the with statement when calling freeze_notify().4 API class GObject.GObject.) Emit signal signal_name. . It is recommended to not call thaw_notify() explicitly but use freeze_notify() together with the with statement. SIGNAL_RUN_CLEANUP. (int.) is the list of the parameters of the signal. int. None is the return type of the signal. Each element in the dictionary is a new signal. GObject.PARAM_READABLE. handler_unblock(handler_id) Undoes the effect of handler_block(). Also used by Glade and similar programs. like the graphical user interface builder Glade. The third one is the property’s description or blurb. This is generally used by programs with strong introspection capabilities.. __gproperties__ The __gproperties__ dictionary is a class property where you define the properties of your object.4 handler_block(handler_id) Blocks a handler of an instance so it will not be called during any signal emissions unless handler_unblock() is called for that handler_id. Thus we have the following situations: If the type is bool or str. float. The second element is the property’s nick name. The benefits of this method is that a property can be defined with more settings.PARAM_READWRITE. This is not the recommend way to define new properties.g. API 109 . The absolute length of the tuple depends on the property type (the first element of the tuple).handler_block(handler_id): # Do your work here . it must end with a comma. __gsignals__ A dictionary where inherited class can define new signals.4. The key is the name of the property The value is a tuple which describe the property.. which is a string with a short description of the property. 21.The Python GTK+ 3 Tutorial. It is recommended to use handler_block() in conjunction with the with statement which will call handler_unblock() implicitly at the end of the block: with an_object. (int.)) GObject. which is another string with a longer description of the property.SIGNAL_RUN_FIRST can be replaced with GObject.). the method written above is much less verbose. like the minimum or the maximum for numbers..SIGNAL_RUN_LAST or GObject. A blocked handler is skipped during signal emissions and will not be invoked until it has been unblocked exactly the amount of times it has been blocked before. GObject. It is recommended to not call handler_unblock() explicitly but use handler_block() together with the with statement.SIGNAL_RUN_FIRST. None. The last one (which is not necessarily the forth one as we will see later) is the property’s flags: GObject. Thus “blocking” a signal handler means to temporarily deactivate it. with the form: (GObject. The number of elements of this tuple depends on its first element but the tuple will always contain at least the following items: The first element is the property’s type (e. a signal handler has to be unblocked exactly the same amount of times it has been blocked before to become active again. The value is a tuple.. the forth element is the default value of the property.PARAM_WRITABLE. Release 3. The key is the signal name. SIGNAL_RUN_LAST Invoke the object method handler in the third emission stage. GObject. GObject. GObject. GObject.SIGNAL_RUN_CLEANUP Invoke the object method handler in the last emission stage.SIGNAL_RUN_FIRST Invoke the object method handler in the first emission stage.PARAM_WRITABLE The property is writable. 110 Chapter 21. there is no extra element.PARAM_READWRITE The property is readable and writable. Objects . GObject.PARAM_READABLE The property is readable. the fifth element is the maximum accepted value and the sixth element is the default value. the forth element is the minimum accepted value.4 If the type is int or float. GObject. If the type is not one of these. Release 3.The Python GTK+ 3 Tutorial. STOCK_ADD • Gtk.STOCK_CLOSE • Gtk. Each stock item is identified by a stock ID.STOCK_COLOR_PICKER 111 .STOCK_APPLY • Gtk.STOCK_CAPS_LOCK_WARNING • Gtk.STOCK_CANCEL • Gtk.CHAPTER 22 Stock Items Stock items represent commonly-used menu or toolbar items such as “Open” or “Exit”.STOCK_CDROM • Gtk. but constants such as Gtk.STOCK_ABOUT • Gtk.STOCK_BOLD • Gtk.STOCK_CLEAR • Gtk.STOCK_OPEN are provided to avoid typing mistakes in the strings. stock IDs are just strings. • Gtk. STOCK_CUT • Gtk.The Python GTK+ 3 Tutorial.STOCK_CONVERT • Gtk.STOCK_DIALOG_WARNING • Gtk.STOCK_DELETE • Gtk.STOCK_DIALOG_ERROR • Gtk.STOCK_DIALOG_QUESTION • Gtk.4 • Gtk.STOCK_COPY • Gtk.STOCK_DIALOG_INFO • Gtk. Release 3.STOCK_CONNECT • Gtk.STOCK_DIALOG_AUTHENTICATION • Gtk.STOCK_DISCARD • Gtk. Stock Items .STOCK_DISCONNECT 112 Chapter 22. STOCK_GOTO_BOTTOM • Gtk.STOCK_FIND_AND_REPLACE • Gtk.The Python GTK+ 3 Tutorial.STOCK_FULLSCREEN • Gtk.STOCK_FLOPPY • Gtk.STOCK_GOTO_FIRST LTR variant: RTL variant: • Gtk.STOCK_DND • Gtk.STOCK_DND_MULTIPLE • Gtk.STOCK_FILE • Gtk. Release 3.STOCK_GOTO_LAST 113 .STOCK_FIND • Gtk.4 • Gtk.STOCK_EDIT • Gtk.STOCK_EXECUTE • Gtk. STOCK_GO_FORWARD LTR variant: RTL variant: • Gtk. Release 3.STOCK_GO_BACK LTR variant: RTL variant: • Gtk.STOCK_GOTO_TOP • Gtk.STOCK_HELP • Gtk.STOCK_HOME • Gtk.STOCK_INDENT 114 Chapter 22.STOCK_INDEX • Gtk.The Python GTK+ 3 Tutorial.STOCK_HARDDISK • Gtk.STOCK_GO_UP • Gtk.4 LTR variant: RTL variant: • Gtk. Stock Items .STOCK_GO_DOWN • Gtk. STOCK_JUSTIFY_LEFT • Gtk.STOCK_MEDIA_FORWARD LTR variant: 115 . Release 3.STOCK_MISSING_IMAGE • Gtk.STOCK_JUSTIFY_FILL • Gtk.STOCK_JUSTIFY_RIGHT • Gtk.STOCK_INFO • Gtk.STOCK_JUMP_TO LTR variant: RTL variant: • Gtk.4 LTR variant: RTL variant: • Gtk.STOCK_LEAVE_FULLSCREEN • Gtk.The Python GTK+ 3 Tutorial.STOCK_ITALIC • Gtk.STOCK_JUSTIFY_CENTER • Gtk. STOCK_MEDIA_PREVIOUS LTR variant: RTL variant: • Gtk.STOCK_MEDIA_PLAY LTR variant: RTL variant: • Gtk.STOCK_MEDIA_RECORD • Gtk.STOCK_MEDIA_STOP • Gtk.STOCK_MEDIA_NEXT LTR variant: RTL variant: • Gtk.STOCK_MEDIA_PAUSE • Gtk.4 RTL variant: • Gtk. Release 3. Stock Items .The Python GTK+ 3 Tutorial.STOCK_MEDIA_REWIND LTR variant: RTL variant: • Gtk.STOCK_NETWORK 116 Chapter 22. STOCK_PRINT_PAUSED 117 . Release 3.STOCK_ORIENTATION_LANDSCAPE • Gtk.STOCK_PAGE_SETUP • Gtk.STOCK_NO • Gtk.STOCK_NEW • Gtk.The Python GTK+ 3 Tutorial.4 • Gtk.STOCK_ORIENTATION_REVERSE_LANDSCAPE • Gtk.STOCK_PREFERENCES • Gtk.STOCK_PRINT_ERROR • Gtk.STOCK_PRINT • Gtk.STOCK_ORIENTATION_REVERSE_PORTRAIT • Gtk.STOCK_ORIENTATION_PORTRAIT • Gtk.STOCK_OK • Gtk.STOCK_PASTE • Gtk.STOCK_OPEN • Gtk. STOCK_PRINT_WARNING • Gtk.STOCK_QUIT • Gtk.STOCK_REDO LTR variant: RTL variant: • Gtk.STOCK_REMOVE • Gtk.STOCK_SAVE_AS • Gtk.4 • Gtk. Release 3.STOCK_REVERT_TO_SAVED LTR variant: RTL variant: • Gtk.STOCK_SAVE • Gtk.STOCK_PRINT_PREVIEW • Gtk.STOCK_PRINT_REPORT • Gtk.STOCK_REFRESH • Gtk. Stock Items .STOCK_PROPERTIES • Gtk.STOCK_SELECT_ALL 118 Chapter 22.The Python GTK+ 3 Tutorial. STOCK_UNDO LTR variant: RTL variant: • Gtk.STOCK_SELECT_COLOR • Gtk.STOCK_UNDELETE LTR variant: RTL variant: • Gtk.STOCK_SORT_DESCENDING • Gtk.STOCK_SELECT_FONT • Gtk. Release 3.STOCK_STOP • Gtk.STOCK_UNDERLINE • Gtk.4 • Gtk.STOCK_UNINDENT 119 .The Python GTK+ 3 Tutorial.STOCK_SORT_ASCENDING • Gtk.STOCK_SPELL_CHECK • Gtk.STOCK_STRIKETHROUGH • Gtk. STOCK_YES • Gtk.The Python GTK+ 3 Tutorial.STOCK_ZOOM_IN 120 Chapter 22.STOCK_ZOOM_100 • Gtk.4 LTR variant: RTL variant: • Gtk.STOCK_ZOOM_FIT • Gtk. Stock Items . Release 3. CHAPTER 23 Indices and tables • search 121 . The Python GTK+ 3 Tutorial. Indices and tables .4 122 Chapter 23. Release 3. GObject attribute).GObject method).GObject method). 108 SIGNAL_RUN_CLEANUP (GObject attribute). 109 P PARAM_READABLE (GObject attribute). 110 PARAM_READWRITE (GObject attribute). 108 123 . 110 SIGNAL_RUN_FIRST (GObject attribute). 108 handler_unblock() (GObject. 108 H handler_block() (GObject. 109 __gsignals__ (GObject. 108 G get_property() (GObject.GObject method). 109 E emit() (GObject. 108 GObject.GObject method). 110 PARAM_WRITABLE (GObject attribute).GObject attribute). 110 T thaw_notify() (GObject.GObject method).GObject (built-in class). 108 F freeze_notify() (GObject. 110 SIGNAL_RUN_LAST (GObject attribute).GObject method). 110 S set_property() (GObject.Index Symbols __gproperties__ (GObject.GObject method).
Copyright © 2024 DOKUMEN.SITE Inc.