| FAQ Index - Search - Recent Changes - Everything - Add entry |
Last changed on Sat Apr 20 23:03:22 2013 CDT
(Entries marked with ** were changed within the last 24 hours; entries marked with * were changed within the last 7 days.)
1. General information and availability
- 1.1. What is PyGTK?
- 1.2. Where can I get PyGTK?
- 1.3. How do I get the very latest PyGTK source code [from git]
- 1.4. What is the password to change and add FAQ entries?
- 1.5. How do I get support for PyGTK [mailing lists, IRC]?
- 1.6. Eeek, I found a bug in PyGTK. Where do I report it?
- 1.7. Where are the reference manuals?
- 1.8. I need PyGTK/libglade compiled for [insert Unix OS here]!
- 1.9. Are there any PyGTK tutorials available?
- 1.10. I have multiple copies of python but pygtk only works with one of them!
- 1.11. How do I extend PyGTK (or the art of wrapping)
- 1.12. Where can I find the API documentation ?
- 1.13. Where can I get gnome-python?
- 1.14. How do I compile pygtk or gnome-python from SVN?
- 1.15. How do I tell what version of PyGTK I'm running?
- 1.16. I wrote a patch for PyGTK that fixes bug X, or implements feature Y, what do I do?
- 1.17. How do I search Bugzilla for PyGTK bugs
- 1.18. My programs configure says: No package 'pygtk-2.0' found
- 1.19. Is there a PyGTK for MacOS X?
- 1.20. Can I use PyGTK to build closed-source applications?
- 1.21. Does PyGTK have timers?
2. Changes from 1.2 to 1.3/2.0
- 2.1. How do I install PyGTK-2 and PyGTK-0 side by side in the same system?
- 2.2. What are the major changes in PyGTK-2 for GTK+ 2.2?
- 2.3. Is there a checklist of changes to migrate an application from PyGTK-0 to PyGTK-2?
- 2.4. If I installed PyGTK-0 and PyGTK-2 in parallel (using pygtk.pth) how do I indicate which one my script should use?
- 2.5. Which versions of PyGTK support parallel install using the pygtk.pth method?
- 2.6. FAQ 2.4 sucks and doesn't work. Truthfuly, how do I require a specific version of PyGTK (or When do I need to use pygtk.require())?
- 2.7. What happened to the GTK and GDK constants/symbols?
- 2.8. For some users import libglade (or GDK) is working and for some users it's not
- 2.9. FAQ 2.4, 2.6 and etc etc all suck. Python still doesn't find the version of pygtk I want.
- 2.10. How do I get my 1.2 gladefiles to work with 2.0?
3. Signal handling
- 3.1. When I connect to a signal, my handler gets called but reports "XXX takes no arguments (1 given)"
- 3.2. How do I detect that a mouse or keyboard event has been triggered?
- 3.3. I connected to some signals but nothing happens. Why?
- 3.4. I've fiddled with the mask but nothing happened. Why?
- 3.5. Which widgets are unable to receive events or be styled?
- 3.6. I attach a callback to a signal, but I keep getting an error: "TypeError: object of type X is not callable"
- 3.7. How can I force updates to the application windows during a long callback or other internal operation?
- 3.8. I want my callback to execute, but not the default callback (or, how to I stop GTK from doing the default action when doing X)?
- 3.9. When creating a new signal, how do I define one of the signal arguments as Python data?
- 3.10. How do I specify user data to a signal?
- 3.11. How do signals and events propagate in GTK+?
- 3.12. Why does handling expose events break drag-n-drop?
- 3.13. How do I pass extra data to a signal handler?
- 3.14. How to construct my own "fake" gtk.gdk.Event?
- 3.15. How do I pass data to a signal handler in Glade?
4. Themes, fonts and styles
- 4.1. How do I change font properties on gtk.Labels and other widgets?
- 4.2. Why don't my style changes apply only to the widget I requested it from?
- 4.3. My user defined styles get overridden by the default theme!
- 4.4. How do I change the background color of my application's dialog?
- 4.5. How do I use the style object?
- 4.6. How do I change the colour of a widget (or how do I get a GdkColor)?
- 4.7. How do I get a Graphics Context, or GdkGC?
- 4.8. How does the alloc() method to the GdkColormap work?
- 4.9. How do I use pango instead of GdkFont for font handling in a GtkDrawingArea?
- 4.10. How can I use Unicode (or other format) strings in my PyGTK application, or, why do I get a UTF-8 warning when using a string?
- 4.11. How can I create a new pango context()
- 4.12. How do I get antialiased fonts in GTK+?
- 4.13. Does PyGTK support TrueType fonts?
- 4.14. What units does pango use to define sizes and widths?
- 4.15. Can I find out how long (wide) a string is in a certain font?
- 4.16. How do I change the background and colour of an Editable (GtkEntry, GtkTextView and friends)?
- 4.17. Why does FontSelection's set_font_name return False?
- 4.18. How do I change GtkMenubar.shadow_type (or other style properties)?
- 4.19. Can I pass strings of unicode instance to gtk or do I need to convert them to utf8?
5. Basic Objects: GObject, GtkWidget and other critters
- 5.1. I want to understand this "data" object that is used in the set_*_data() and get_*_data() calls.
- 5.2. How do I check if a widget is currently sensitive?
- 5.3. Where is get_state() in PyGTK 0.6.x?
- 5.4. How do I catch right-click, middle-click and double-click on my widget?
- 5.5. How do I capture keypresses, and how do I perform a certain action depending on the key pressed?
- 5.6. How do I change the cursor for a certain widget?
- 5.7. How can I tell my program that the cursor should jump to a specific widget?
- 5.8. What signal is triggered when I change a widget's sensitivity?
- 5.9. How do I find out the size of a widget?
- 5.10. How do I focus a widget? How do I focus it before its toplevel window is shown?
- 5.11. My callback is getting a gtk.gdk.Event object, but I need an EventExpose!
- 5.12. How do I check if a widget is mapped? And realized? And visible? [...]
- 5.13. While calling get_property(), I get an "invalid property id" warning. Why?
- 5.14. How can I discover what properties and signals a GObject supports?
- 5.15. How do I access one of these properties in a GObject?
- 5.16. What's the difference between a property and an attribute?
- 5.17. Do I need to handle reference counting for GObjects? What about for other objects in PyGTK/gnome-python?
- 5.18. Focusing a widget after when selecting an item from Treeview
- 5.19. How can I listen to events from the scroll wheel on my mouse?
- 5.20. How do I move focus between widgets?
6. Widget subclasses and user signals: GObject
- 6.1. What is the canonical reference on widget (and GObject) subclassing and property overriding?
- 6.2. When subclassing a widget (or a GObject), why are the additional signals I define not usable?
- 6.3. How do I wrap a GObject in Python?
- 6.4. How can I draw on top of a subclassed widget?
- 23.33. Using metaclasses in GObject subclasses.
7. Labels: GtkLabel
- 7.1. How can I use mnemonics for my GtkLabel?
- 7.2. Where is GtkLabel.get_text()?
- 7.3. How do I make a GtkLabel font larger or bold?
- 7.4. How do I left, center, right, top, bottom, middle align a GtkLabel?
- 7.5. How do I change a Label's background color, or why doesn't my Label receive any signals?
- 7.6. How do I render a label in a button or menuitem with an underscore in its label?
- 7.7. I set my labels to use_markup in glade-2. Why don't they markup the contents I set?
- 7.8. How can I change the appearance of a label without using pango markup?
8. Images: GtkImage, GtkPixmap, GdkPixbuf
- 8.1. How do I load an image from a filename into my application UI?
- 8.2. What about loading other image formats besides XPM, like JPEG or PNG?
- 8.3. How do I convert a Numeric array to a Pixbuf object?
- 8.4. Is there a resource leak? Why do I run out of memory using Pixbuf?
- 8.5. How do I to display an image from data (using a drawable or Image widget)?
- 8.6. How do I resize a gtk.Image?
- 8.7. What if I want to add a PIL image to a drawable?
- 8.8. Does somebody know what all these image/pixmap classes are?
- 8.9. How do I flip an image horizontally or vertically?
- 8.10. Is it possible to use SVG icons and images in PyGTK?
- 8.11. How do I get a Pixbuf of a stock icon?
- 8.12. How do I register stock icons from an image file?
- 8.13. How can I use an image as background in a gtk.Window?
- 8.14. How do I convert a pixbuf to a PIL Image?
- 8.15. How can I get the data of a gtk.Image and save it in an external file?
- 8.16. How to show data that I already own from outside, in a gtk.Image?
- 8.17. How to make a colorful image grayscale without using PIL?
- 8.18. How blend (composite) two images together?
- 8.19. How can I make a stock icon the default icon?
- 8.20. How do I draw a text [or something else] on a gtk.gdk.pixbuf?
- 8.21. How can I use an image as background in a widget?
9. Buttons: GtkButtons
- 9.1. How does one group radio buttons to allow only one concurrent button to be depressed?
- 9.2. How do I create buttons that contain a pixmap?
- 9.3. PyGTK 0.6.x: The stock pixmap buttons in glade, but they don't show in my buttons? (pygtk0.x)
- 9.4. Why is a handler connected to a GtkRadioButton being called twice?
- 9.5. How do I render a stock button with a different label?
- 9.6. How do I add tooltips to a ToolButton in a Toolbar?
- 9.7. How do I add a stock icon to a ToggleButton?
- 9.8. How do I change the text color of a gtk button?
10. Windows: GtkWindows and GtkDialogs
- 10.1. How do I get a GdkWindow from a GtkWindow?
- 10.2. Where are GtkDialogFlags defined?
- 10.3. How do I get my windows to show up where I want?
- 10.4. How do I make a dialog block the whole application, so the user is forced to answer it?
- 10.5. I click on the close button (X) to close my gtk.Window. It disappears, but the program seems to hang!
- 10.6. How do I avoid having my gtk.Window instance destroyed when I click on the window's close button? (or, When I redisplay my window, all my child widgets are missing and I get a bunch of Gtk-Critical errors!)
- 10.7. How do I change the window manager's icon for a PyGTK Window?
- 10.8. How do I get the GtkWindow's title?
- 10.9. How do I change the buttons on a MessageDialog?
- 10.10. How do I scroll a ScrolledWindow to the position of a given child widget?
- 10.11. How do GtkDialogs work?
- 10.12. How do I make ENTER in an entry box activate the OK signal
- 10.13. When closing the GnomeAbout box (or other GtkDialog subclasses), I get crashes and weird callback behaviour. What up with that?
- 10.14. I created a modal dialog, but clicking on the main window covers it!
- 10.15. How do I get the position of my window in absolute terms (IOW, relative to the root X window)
- 10.16. How do I start up a window maximized?
- 10.17. How do I run a dialog without running another main loop?
- 10.18. Changing a Window's background color
- 10.19. How do I get XID for a GtkWindow? And for the root window?
- 10.20. How can I make my window appear in the center of the screen?
- 10.21. How to hide a window when clicking the close button (instead of destroying it)
- 10.22. How can I find out when my GtkWindow is minimized?
- 10.23. How can I find out if a gtk.Window is visible?
- 10.24. How do I create a shaped window?
- 10.25. How do I raise a window that is minimized or covered?
- 10.26. Creating dialogs using the Glade file
- 10.27. How can I focus an external window?
- 10.28. How do I make a ScrolledWindow take the size of its child?
11. Menus: Gtk*Menu and Gtk*MenuItem GtkToolbar
- 11.1. How do I turn off tearoff menus in libglade?
- 11.2. How do I pop up a menu with a button click?
- 11.3. How do I find out if a GtkCheckMenuItem is selected (active)?
- 11.4. I create a menubar with ItemFactory, but it disappears
- 11.5. When specifying items to an ItemFactory, I pass the extra argument for the image but I can't see anything!
- 11.6. How do I specify and save accelerators for my menu?
- 11.7. How to i put a custom icon and custom label in a gtk.ImageMenuItem
- 11.8. How can I make the label for an action created using ui_manager appear beside rather than below the icon?
- 11.9. How can I insert space in a toolbar created with ui_manager to spread out groups of action buttons?
- 11.10. How can I display the tooltip of the currently selected menuitem in a statusbar?
12. Simple Containers: GtkBoxes, GtkTable, GtkFixed, GtkAlignment
- 12.1. What are the parameters to GtkAlignment.set()
- 12.2. How does packing work (or how do I get my widget to stay the size I want)
13. Lists and Trees: GtkList/TreeView
- 13.1. Is there a nice tutorial on using GtkTreeView and GtkTreeModel?
- 13.2. How do the TreeStore and ListStore sequence APIs behave? [PyGTK2]
- 13.3. How do GtkTreePaths work? [PyGTK2]
- 13.4. How do I define columns for a TreeView using TreeViewColumn?
- 13.5. How do I create my own custom TreeModel.
- 13.6. How do I put icons in a TreeView?
- 13.7. How do I get all the selections in my TreeView.
- 13.8. How do I delete the selected rows in a TreeView?
- 13.9. Is there a way to mass-specify columns in ListStore?
- 13.10. How do I make a GtkTreeView with editable cells?
- 13.11. What signal is emitted when a user selects/clicks on a row in a GtkTreeView?
- 13.12. How do I change the color of the alternate row shading on the TreeView widget?
- 13.13. How do I create a lazy TreeView?
- 13.14. How do I show different images when a TreeView item is expanded and collapsed.
- 13.15. My TreeView/TreeModel rows represent instances (or any python object), but how can I keep track of them?
- 13.16. My Treeview shows all my strings/text values as numbers in the columns!
- 13.17. How do I make a popup menu appear when I right-click my TreeView?
- 13.18. Is it possible for a TreeModel to tell a CellRendererToggle that it is in an "in between" (inconsistent) state?
- 13.19. How do I change alignment on a specific cell renderer?
- 13.20. How do I keep GenericTreeModel from leaking references?
- 13.21. How do I get changes in my TreeModel to show up in my TreeView?
- 13.22. How do I display a combo box in a Treeview?
- 13.23. Why doesn't expand_row() display an expanded row for paths longer than one element?
- 13.24. How do I transform the value in my model before displaying it in the TreeView?
- 13.25. How do I delete multiple selections?
- 13.26. How do I perform an action when the user clicks on the title column of a TreeView?
- 13.27. How do I run a command for each TreeModel row, or how does TreeModel.foreach() work?
- 13.28. When connecting to 'row-inserted', my model value is always None. Why?
- 13.29. How do I use a python object to store data for all the columns in a row?
- 13.30. How do I move rows around in a GtkTreeView?
- 13.31. How do I change the color of a row or column of a TreeView?
- 13.32. How do I select [or edit] a row in my TreeView?
- 13.33. How do I handle DnD operations in a GtkTreeView?
- 13.34. How do I work with the reorderable() property of GtkTreeview?/The reorderable() property of GtkTreeView is too limited
- 13.35. How do I use the TreeModelFilter to process tree/store data automatically?
- 13.36. How do I unselect a path in a TreeView?
- 13.37. How do I avoid displaying (hide) a certain column in a TreeView?
- 13.38. How do I display pixbufs instead of numbers for integer or boolean values in my treemodel?
- 13.39. I defined a TreeView in glade, how do I manipulate its columns and other properties?
- 13.40. How do I change the font of a CellRendererText?
- 13.41. How do I show a GtkImage (even animations) in a treeview? (subclassing GtkCellRenderer)
- 13.42. How do I show a picture (image) in a treeview background or exist any way how to set treeview (and window with treeview) as transparency ?
- 13.43. Are there tips for improving performance when adding many rows to a Treeview?
- 13.44. What is TreeRowReference and how to use it?
- 13.45. How do I create a custom gtk.CellRenderer?
- 13.46. How do I add a tooltip to a cell, row or column of a TreeView
- 13.47. How do I create a GtkTreeView having nodes with underlined text?
- 13.48. How do I hide some rows in a TreeView?
- 13.49. How to manually sort rows?
- 13.50. Target sensitive tooltip for treeview/iconview.
- 13.51. How do I get to previous row in the model when iter_prev() method doesn't exist?
- 13.52. How can I save and restore which rows are expanded in a TreeView?
- 13.53. How can I expand a range of nodes specified by first and last path?
- 13.54. How can I cut/copy/paste TreeStore rows using clipboard?
- 13.55. How do I enable editing of CellRendererProgress?
- 13.56. How do I create my own CellRendererDate?
- 13.57. How do I create my own CellRendererMultiline?
- 13.58. How do I hide the row expanders (or How do I share a model between tree and table view)?
- 13.59. Changing full background color of Treeview
- 13.60. How do I end editing immediately after an item is selected in a CellRendererCombo?
14. Editables: GtkEntry, GtkCombo, GtkText, GtkSpinButton, GtkTextView
- 14.1. How do I make a GtkEntry exactly 5 characters long?
- 14.2. What is a GtkTextIter, and how do I get one for position X (and other positions)?
- 14.3. How do I change the cursor for a GtkEntry?
- 14.4. Why does GtkText's insert_text generate critical messages complaining "assertion `index <= TEXT_LENGTH (text)' failed."?
- 14.5. I want to change the text being typed into an entry or textbox, but the original text is also inserted!
- 14.6. Why does the second parameter to insert_text (the `text' parameter) contain garbage?
- 14.7. Why isn't GtkText.insert_defaults() generating the signal insert_text
- 14.8. How do I get the currently selected text in a GtkCombo?
- 14.9. How do I programatically set the max value for a GtkSpinButton?
- 14.10. How do I scroll a TextView to display the text being inserted?
- 14.11. How do I insert colored text into a TextView?
- 14.12. How can I make GtkTextView to always show the last line
- 14.13. How do I add items into GtkCombo
- 14.14. How can get back the strings that I set using Combo.set_popdown_strings()
- 14.15. How do I change the mouse cursor on a TextView (or how do I get the "right" GdkWindow from a TextView)?
- 14.16. Is there a signal sent when a user hits enter in an editable?
- 14.17. What X clipboard do TextView's context menu items use?
- 14.18. How do I get the clipboard functions to work properly?
- 14.19. I'm getting a Gtk-CRITICAL messsage: assertion `g_utf8_validate (text, len, NULL)' failed [using insert_*]
- 14.20. How do I write clipboard callbacks for multiple widgets?
- 14.21. How do I right-align text in an Entry?
- 14.22. How do I create a mask or validator for a GtkEntry?
- 14.23. How do I send the output of an external process to a gtk.TextView without freezing the GUI?
- 14.24. How do I add completion support for an entry?
- 14.25. How can I place a background image on a TextView widget?
- 14.26. The text in the TextView is not aligned! Any ideas?
- 14.27. How do I prevent unselected gtk.Entry from being highlighted after losing focus?
- 14.28. How do I make the Enter key behave as a Tab key in a GtkEntry?
16. GtkOptionMenu, GtkComboBox, GtkComboBoxEntry
- 16.1. Why doesn't the GtkOptionMenu work like a real listbox?
- 16.2. Let's say I accept it as it is. How do I implement one using pygtk?
- 16.3. If I set the OptionMenu's state to insensitive, and i call set_history() on it, and put it back to sensitive, the previously selected menuitem still looks insensitive!
- 16.4. How do I find out which is the selected item in a GtkOptionMenu?
- 16.5. What signal is emitted when an optionmenu's item is selected?
- 16.6. How do I get the label of an OptionMenu's item?
- 16.7. How do I get the text from the selected item in GtkComboBox/ComboBoxEntry
- 16.8. How do I populate a ComboBox or ComboBoxEntry with strings?
17. GtkNoteBook
- 17.1. How do I get a reference to the page my GtkNotebook just switched to (or, what is the deal with the second argument to GtkNotebook's switch_page handler)?
- 17.2. How do I make one toolbar button (e.g. an Add button) call a different function for each notebook tab?
- 17.3. How do I create a popup menu on a notebook tab and figure out which tab a click comes from
18. GtkDrawingArea
- 18.1. How do I make a gray-scale gradient picture?
- 18.2. When I place a DrawingArea inside a ScrolledWindow the event object in callbacks has X and Y coordinates off by a few pixels!
- 18.3. How do I set line attributes for draw_line() and draw_lines()?
- 18.4. How do I draw dashed or dotted lines in a GtkDrawingArea?
- 18.5. What's the essential approach to tracking mouse events in a GtkDrawingArea?
- 18.6. How do I get scrollbars to work with a DrawingArea?
- 18.7. How do I make my DrawingArea have the same background used in other widgets?
- 18.8. What basic pattern should I follow when using a DrawingArea?
- 18.9. How to set a tiled background pixmap on gnomecanvas.Canvas? Or, how do set custom background on gnomecanvas.Canvas?
19. Other widgets
- 19.1. Are there any HTML rendering widgets for PyGTK?
- 19.2. What about HTML widgets for PyGTK2?
- 19.3. GnomeIconList's get_icon_data() method doesn't work!
- 19.4. Can I do plots or charts with PyGTK?
- 19.5. How do I get the current color from a gnome ColorPicker?
- 19.6. Is there a syntax highlighting widget for PyGTK?
- 19.7. When displaying a GnomeAbout box, it doesn't display the program name or version.
- 19.8. How do I pass extra arguments to a Gnome Applet's setup_menu() callback?
- 19.9. In creating a Gnome Applet, how do I use class members for callbacks?
- 19.10. How do I hide the toolbar of a gnome.ui.App() instance?
- 19.11. Can I use OpenGL to draw in a PyGTK application?
- 19.12. Is there support for tray notification area clients?
- 19.13. How do I a signal a callback when a gtk.Paned widget handle is dragged?
- 19.14. Is there a grid or spreadsheet-like widget available?
- 19.15. How do I embed something using Plugs and Sockets?
- 19.16. How can I use the IconView widget?
- 19.17. How can I distribute gtkhtml2 (outside of gnomepythonextras)?
- 19.18. Why does gtkmozembed somtimes crash in load_url()?
- 19.19. How can I change the background color of the IconView widget?
- 19.20. Could I get another example of how to use the IconView please?
- 19.21. How can I send a pdf file to a printer over the gtk printing dialog?
20. The GTK Mainloop and Threading
- 20.1. What are the general tips for using threads with PyGTK?
- 20.2. On Win32, the input_add() function doesn't work!
- 20.3. How can I make Ctrl-C in the console quit my app which uses PyGTK 1.99.13 or older?
- 20.4. I get random crashing when using lots of threads in PyGTK
- 20.5. I want to show a splash screen and make it disappear. How?
- 20.6. I am using a separate thread to run my code, but the application (or the UI) hangs.
- 20.7. I set up a timeout handler using timeout_add, but the handler only runs once.
- 20.8. How do I check if threading was compiled in my version of PyGTK
- 20.9. I don't want to use threading. What other options do I have?
- 20.10. When an exception is raised, it is printed out to standard error! (or how do I get exceptions to be printed to X or displayed in a window?)
- 20.11. How can I monitor sockets or files inside the gtk mainloop (or how does gtk.input_add() work)?
- 20.12. How do I get an action to run periodically, say, every 30 seconds?
- 20.13. The GTK thread dies, but some windows remain open. I don't want that, what can I do?
- 20.14. My application uses threads and GtkDialogs seem to freeze it! What can I do?
- 20.15. I'm using threads and timeout or idle or input handlers and the app freezes. What's wrong?
- 20.16. So how do I use gobject.io_add_watch (used to be input_add) ?
- 20.17. Why isn't my thread running?
- 20.18. How do I write a qt application using gobject.MainLoop?
- 20.19. What does "Fatal Python error: GC object already tracked" mean?
- 20.20. gobject.io_add_watch doesn't work with non-blocking sockets on win32!
- 20.21. How do I download something without freezing the GUI (and without threading)?
21. Win32 and PyGTK
- 21.1. How do I get PyGTK running on MS Windows?
- 21.2. Is there a walkthrough on getting PyGTK2 and libglade2 to work on win32
- 21.3. Does the Win32 port support threading?
- 21.4. Where is GdkImlib for MS Windows?
- 21.5. How can I bundle a PyGTK program in windows so my users don't need to install Python or the GTK+ libs?
- 21.6. How do I change the Window icon of a Win32 PyGTK app?
- 21.7. How do I make the my PyGTK app look a bit more like a `normal' Windows app?
- 21.8. How do I compile PyGTK for win32
- 21.9. How do I find out the GTK+ installation path on windows?
- 21.10. DLL Errors after upgrading to PyGTK-2.0.0.win32-py2.3
- 21.11. Is it possible to have antialiased fonts on Win32?
- 21.12. How do themes work on win32?
- 21.13. Can PyGTK have the native filechooser of Windows?
22. libglade
- 22.1. How do I use PyGTK and glade together (using libglade)?
- 22.2. How do I internationalize a PyGTK and libglade program?
- 22.3. Why doesn't gettext work on my libglade UIs with Python <= 2.2?
- 22.4. I'm using libglade, but what do I do with the signals and handlers I set in the glade file?
- 22.5. I'm using Gnome and libglade, but some widgets don't work properly.
- 22.6. When I invoke GladeXML() or glade.XML() all the widgets in my gladefile are displayed!
- 22.7. How do I create and use a custom Glade widget?
- 22.8. How do I retrieve the ID of a signal connection made by signal_autoconnect?
- 22.9. My libglade files have widgets that don't show up in the GladeXML tree!
- 22.10. When I load a glade file in GladeXML I get evil warnings about GnomeApp and a crash!
- 22.11. How do I produce or reuse a [portion of a] widget tree in glade?
- 22.12. How can I get a new instance of a widget defined in a glade file?
- 22.13. Tabs in Notebook don't show up!
- 22.14. How do I create and use a custom Builder widget?
- 22.15. How can I make glade to know my custom PyGTK widgets?
23. Miscellaneous questions
- 23.1. Why does ancient PyGTK versions segfault with Python 2.2?
- 23.2. Are there any helpful tools when developing with PyGTK?
- 23.3. How do I find out the current X and Y position of my mouse?
- 23.4. Are there any tips for UI designers?
- 23.5. Why does my X selection disappear when my window dies?
- 23.6. When compiling PyGTK, I get a bunch of weird "Could not write method ..." messages!
- 23.7. Is there a way to get version information from pygtk?
- 23.8. How do I beep the speaker?
- 23.9. Is there a way to grab the keyboard from X (like XGrabKey())?
- 23.10. When wrapping a widget into a new Python extension, I get undefined symbols on importing it!
- 23.11. Does VTK support PyGTK?
- 23.12. How do I create a GdkRectangle?
- 23.13. When I create a gnome Druid, the first and last page are blank.
- 23.14. I disable text or graphics on my GtkToolbar, or the time in my GnomeDateTime, and they still show up, or, why is show_all() considered harmful?
- 23.15. I'm writing a C extension that uses PyGTK. How do I acess a PyGTK object's C counterparts and vice-versa?
- 23.16. How do I change the font and colour of some GnomePrint text?
- 23.17. Is there a way to query for the current screen size?
- 23.18. When dragging and dropping, Netscape/Firefox/etc and gedit/native gtk apps don't behave the same. Why?
- 23.19. What do you see as the flaws in the Minimalist Programme?
- 23.20. How do I update a progress bar and do some work at the same time
- 23.21. How can I package my gnome-python application using autotools?
- 23.22. How can I extend PyGTK using gtkmm/C++ ?
- 23.23. How do I debug a PyGTK application without an interactive session?
- 23.24. Can GTK know the mouse position outside of GTK Application?
- 23.25. Is widget.set_property('visible', False) the same as widget.hide() ?
- 23.26. How do I change window properties involving atom values?
- 23.27. How do I port a GObject/Glib based C application to PyGTK?
- 23.28. How can I distribute gtkspell, trayicon (eg. modules that do not depend on gnome) so my application will take advantage of those but the user won't have to install gnome-python-extras?
- 23.29. How do I configure emacs to be used with pygtk?
- 23.30. Q_() is not available in my pygtk app. How to use Qualified translatable strings?
- 23.31. How to get the path to the file(s)/folder(s) that was dropped (by drag 'n' drop) in my application? [using selection.data]
- 23.32. How to get coordinates relative to X11 for a widget that has no window of its own?
- 23.34. How can I use gtk.binding_entry_add (and why it's better than keypress in most cases)
- 23.35. How can you set the tab / tabbing order?
- 23.36. How do I acquire a screenshot of the whole screen?
- 23.37. How do I create a throbber like the one in Firefox?
- 23.38. How can I access data returned with a gpointer?
- 23.39. How do I acquire a screenshot of the active window?
- 23.40. Is g_utf8_collate and g_utf8_collate_key available in PyGTK?
- 23.41. How can I create a GObject from a memory address?
- 23.42. How can integrate PyGTK with SDL / pygame ?
- 23.43. IDEs and editors with code completion support for PyGTK
- 23.44. How can I embed a Jython application in PyGTK?
- 23.45. How do you get your app to restart after you log out if it was running?
- 23.46. How do I get file mimetype and other info
24. Deprecated List Widgets: GtkList, GtkCList, GtkCTree and others
- 24.1. My GtkCList rows represent instances, but how can I keep track of them?
- 24.2. Why doesn't GtkCList's children() method return the lists rows?
- 24.3. How do I access data that is in a GtkCList?
- 24.4. How do I order the contents of a GtkCList according to the type of data in the columns (or, where is gtk_clist_set_compare_func)?
- 24.5. How do I get the data out of a GtkCTree?
- 24.6. How would I recurse through all nodes in a GtkCTree?
- 24.7. How do I capture a right-click or double-click event on a GtkCList row?
- 24.8. How do I find a row in a GtkCList that contains "X"?
- 24.9. When entering data dynamically into my GtkCList or tree, it flickers like mad!
- 24.10. How do I align a GtkCList's columns?
- 24.11. How do I remove a row from a CList?
- 24.12. How do I find out which row(s) are selected in the GtkCList?
- 24.13. How do I colour the background of a GtkCList row?
- 24.14. How do I find out what the current selection mode in the GtkCList is?
- 24.15. How do I change the style of the white space between CList rows?
- 24.16. Is it possible to define a custom cursor from an image or data?
1. General information and availability
1.1. What is PyGTK?
Python is an interpreted language with a very clean syntax, high-level data structures, dynamic typing, object oriented characteristics and generally acceptable performance. For more information on Python see [www.python.org]
GTK+ is a graphical user interface toolkit, which includes user interface components (hereafter called by the usual name widgets) and a framework for handling events that are produced upon these components. For more information on GTK+ see [www.gtk.org]
A binding is code (usually a library) that allows you to access functions that were coded in another language. In our case, GTK+ was written in C, and applications written in C can use native GTK+. For a Python program to be able to create applications using the GTK+ framework, a special library has to be used. This library is PyGTK.
1.2. Where can I get PyGTK?
- The latest source version released of the 2.0 branch (the "new" stable branch, based on GTK+ 2.0) can be downloaded from [ftp.gnome.org]
- The latest source version released of the 0.6 branch (the old stable branch based on GTK+ 1.2) can be downloaded from [ftp.gtk.org]
- For gnome-python, see FAQ 1.13
- For MacOS X, see FAQ 1.19
- For Microsoft Windows, see FAQ 21.1
PyGTK has a number of optional dependencies you must have installed before compiling if you want to use them. For PyGTK2:
- gtkglarea: [ftp.gnome.org]
- libglade: [ftp.gnome.org]
For PyGTK0.6:
- libglade: [ftp.gnome.org]
- gtkglarea: [www.ece.ucdavis.edu]
- imlib: [ftp.gnome.org]
- gdk-pixbuf: [ftp.gnome.org]
1.3. How do I get the very latest PyGTK source code [from git]
git clone git://git.gnome.org/pygtkand possibly:
git clone git://git.gnome.org/gnome-python git clone git://git.gnome.org/gnome-python-desktop git clone git://git.gnome.org/gnome-python-extrasPlease note that to use PyGTK you rely on recent code for GTK+ , GLib, atk, pango, Python. How recent exactly these dependencies need to be depends largely on the current target for the PyGTK development team. In general, CVS HEAD will use the latest CVS, but ask on the mailing list if problems arise.
1.4. What is the password to change and add FAQ entries?
We only use the password to allow a minimum of control over FAQ changes, and you are of course invited to help maintain it.
1.5. How do I get support for PyGTK [mailing lists, IRC]?
The standard way to get some support is to join the PyGTK mailing list. You can sign up using a webform at [www.daa.com.au] The mailing list is searchable via Gmane: [news.gmane.org]
We also run a channel for pygtk support on IRC. This channel is run on server irc.gnome.org and it's called #pygtk. Stop by and say hello once in a while.
If you want to check out existing bug reports for pygtk, you can use the query interface at [bugzilla.gnome.org] to query for bugs reported against the gnome-python module. I've added two links for easy queries here:
Open bugs (UNCONFIRMED, NEW or ASSIGNED): [bugzilla.gnome.org]
All bugs ever reported: [bugzilla.gnome.org]
Finally, there is an open wiki at [live.gnome.org]
1.6. Eeek, I found a bug in PyGTK. Where do I report it?
a) Test against the latest git version of PyGTK, if you can. This helps catch errors that have already been fixed but haven't migrated into a release.
b) If you are unsure it's a bug, make a request discussing it on the mailing list, or present it to the IRC channel.
c) File a new bug on the pygtk product at GNOME Bugzilla [bugzilla.gnome.org] Remembering the bug number will help when referencing the bug through email. Bugs make remembering problems a lot easier by making sure problems are uniquely identified in a simple and focused way.
Remember, a great deal of help can be provided by a good bug report. Including a testcase will make fixing MUCH easier, and if that's impossible, listing the exact steps to reproduce will help too.
d) If you can, write some code to fix the bug and attach a patch in the unified diff format against current git ("git format-patch" will do the job) to the bug reported. After the patch has been reviewed and approved by someone on the PyGTK developer team, it can be checked in to git -- usually a member of the team will check it in for you if you don't have a git account on git.gnome.org. The next release will include the fix.
More information on bugzilla, the bug tracking tool GNOME uses, can be found in the Using Bugzilla section of the Bugzilla manual: [www.bugzilla.org]
1.7. Where are the reference manuals?
The most complete functional reference for the underlying GTK+ and GDK libraries lives at [www.gtk.org] , and it covers the native C bindings. The mapping from the C API to Python is quite straightforward, and the reference is actually quite thorough.
The source code contains examples that are quite helpful (specially testgtk.py, which includes many widgets and features) in the examples/ directory. The gtk.py file itself is a worthy reference (praise to Python's readability there) and many times will solve a prototype, api or parameter question.
pygtk2 additionally includes docstrings for many of the classes and methods available, which you can inspect from an interactive session:
>>> import gtk >>> help(gtk.Window) Help on class Window in module gtk: class Window(Bin) | Object GtkWindow | | Signals from GtkWindow: | set-focus (GtkWidget) | frame-event (GdkEvent) -> gboolean | activate-focus () | activate-default () | keys-changed () [...]
1.8. I need PyGTK/libglade compiled for [insert Unix OS here]!
cd /usr/src/pygtk-0.9.9 # we wish :-) ./configure make make installFor Redhat 7.1, James Henstridge himself said:
You may as well compile it yourself. Just make sure you have the python2-devel RPM installed on your system, along with the -devel rpms for gtk+, glib, and the other modules you want to be able to use. Then run the following commands:
PYTHON=/usr/bin/python2 ./configure --prefix=/usr make make install
1.9. Are there any PyGTK tutorials available?
- Aug 2003 "A Beginner's Guide to using pyGTK and Glade" by Dave Aitel in the Linux Journal, available at [www.linuxjournal.com]
- Jul 2003 "PyGTK Tutorials" by John Finlay, they are the GTK+ tutorials rewritten for PyGTK v1.x and v2.x, available at [www.moeraki.com]
- Feb 2003 "Bonobo Tutorial for Python" an excellent tutorial by Martin Grimme, available at [www.pycage.de]
- Nov 2002 "Developing GNOME Applications with Python(part 3)" by Hilaire Fernandes, available at [www.linuxfocus.org] Source code is available at [www.linuxfocus.org]
- Jan 2002 "Developing GNOME Applications with Python(part 2)" by Hilaire Fernandes, available at [www.linuxfocus.org]
- Aug 2001 Russ Nelson has a tutorial up at [handhelds.org] that takes you step-by-step to hello world, and uses an interesting class design (with __getitem__() overridden for his "View", interesting)
- Jul 2000 "GNOME Panel Applets" by Daniel Solin at OnLamp (o'reillynet member), available at [www.onlamp.com] (Yes those little applets that live in the gnome panel.)
- Jul 2000 "Developing GNOME Applications with Python(part 1)" by Hilaire Fernandes, available at [www.linuxfocus.org] Source code is available at [www.linuxfocus.org]
- Feb 2000 "Python Gnome tutorial" (unfinished) by Daniel Kornhauser, available at [laguna.fmedic.unam.mx]
(People looking for a GObject tutorial should take a peek at FAQ 6.1.)
1.10. I have multiple copies of python but pygtk only works with one of them!
If you built pygtk for one copy of python on your system (or if you are using packages from your distribution), it will probably not be available on the others.
You will probably need to build pygtk for the other python installations. To do this, set the PYTHON environment variable to the full path of the alternative python before running pygtk's configure script. For example to build pygtk for the python 2.x distributed with Red Hat 7.x, do the following:
PYTHON=/usr/bin/python2 ./configure --prefix=/usr make make install
1.11. How do I extend PyGTK (or the art of wrapping)
Let's call the library "foo" (how original)
1) foo.defs.
- Use h2defs.py found in pyobject/codegen/ on all your _public_ headers for the library.
h2defs.py /usr/include/foo-1.0/*.h > foo.defs2) foomodule.c
- Use atkmodule.c as a template. Replace all instances of atk with foo.
- You most probably won't use any constants (since they require additional work), so just comment out pyatk_add_constants (m, "ATK_");
3) foo.override
- You can also use atkmodule.c as a template for the override file.
- Remove the only function in there (atk_relation_new) and replace the atk headers with your own.
- Don't forget to replace the modulename too.
4) Makefile.am
AUTOMAKE_OPTIONS=1.5
INCLUDES = $(PYTHON_INCLUDES) $(FOO_CFLAGS)
# foo module
pyexec_LTLIBRARIES = foomodule.la
foomodule_la_LDFLAGS = -module -avoid-version -export-symbols-regex initfoo
foomodule_la_LIBADD = $(FOO_LIBS)
foomodule_la_SOURCES = foomodule.c
nodist_foomodule_la_SOURCES = foo.c
foo.c: foo.defs foo.override
CLEANFILES = foo.c
EXTRA_DIST = foo.override
.defs.c:
(cd $(srcdir)\
&& $(PYTHON) codegen/codegen.py \
--override $*.override \
--prefix py$* $*.defs) > gen-$*.c \
&& cp gen-$*.c $*.c \
&& rm -f gen-$*.c
---
Should be enough for you to get started
5) configure.in
- Copy pygobjects configure and remove unnecessary stuff. Should be trivial. Don't forget to define a FOO_LIBS and FOO_CFLAGS
PKG_CHECK_MODULES(FOO, foo >= 1.2,,) AC_SUBST(FOO_CFLAGS) AC_SUBST(FOO_LIBS)Finally, copy autogen.sh and hopefully you'll have most functions wrapped.
Eventually you'll have to wrap a few functions by hand, functions that the code generator cannot handle. Mostly functions with inout params (**) and GSList/GList parameters.
1.12. Where can I find the API documentation ?
1.13. Where can I get gnome-python?
1.14. How do I compile pygtk or gnome-python from SVN?
- gnome-python/pygtk
- gnome-python/pyorbit
- gnome-python/gnome-python
You should run
./autogen.sh make make installin each of these, in that order. If you want to build from SVN, you might want to look at a build script. James recommends jhbuild (also in GNOME svn).
If you want to install them to a separate prefix, eg if you don't have write access to /usr/local, use --prefix as an argument to autogen.sh or configure, eg:
./configure --prefix /home/user/prefixAnd then, don't forget to set PYTHONPATH before running the program, eg:
export PYTHONPATH=/home/user/prefix/lib/python2.3/site-packagesThen you can finally run your program.
For additional information on how to use configure, see the INSTALL file which is included in the source tarball or subversion.
1.15. How do I tell what version of PyGTK I'm running?
>>> import gtk >>> gtk.pygtk_version (2, 17, 0)Get your version of GTK+:
>>> import gtk >>> gtk.gtk_version (2, 20, 1)
1.16. I wrote a patch for PyGTK that fixes bug X, or implements feature Y, what do I do?
Patches should be sent in the unified diff format (the -u flag). A good set of flags is -urNp -- look up man cvs if you're curious. It's a good idea to produce the patch against the CVS version -- see FAQ 1.3 for information on getting pygtk from CVS.
Patches sent to the mailing list may be reviewed and checked in, but they may also be deleted without reading when the maintainers are too busy. Use bugzilla to be on the safe side and make sure your work is not wasted.
1.17. How do I search Bugzilla for PyGTK bugs
If I am trying to do a general query, it helps to "select all" in these boxes by clicking on the first entry and then shift clicking on the last entry. You may also want to activate all the 'Status' entries to see resolved bugs, etc.
Once you have configured all these parameters, go to the Text information section, enter your search terms in the Description or Summary boxes, and click 'Submit Query'.
1.18. My programs configure says: No package 'pygtk-2.0' found
If you build pygtk on your own, from source, then you need to write the following before running the configure script:
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfigOr, replace /usr/local with the prefix you installed pygtk to. /usr/local is however the default and most commonly used one.
If you did not install it from source then it means that you forgot to install the devel/dev package. For Red Hat based distributions (Fedora, SuSe, Mandrake etc) you need to install pygtk2-devel and for debian based distributions you need to install pythonX.Y-gtk2-dev, where X.Y stands for the python version you're using.
1.19. Is there a PyGTK for MacOS X?
One way is running it with native support, which is still in early stages of development and is not feature complete yet. There are currently (as of June 2008) no available binaries for GTK+ running natively under OSX, so you need to compile GTK+ yourself. For more information about the native port check out Imendio's page [developer.imendio.com] . The instructions here tell you how to build GTK+, but not PyGTK; after following the steps here you also must do "jhbuild build meta-gtk-osx-python".
The second way is using Apple's X11 server, which is closer to other Unix systems for portability, but won't integrate very well with the rest of the OS X desktop. If you are running Mac OS X 10.3 (Panther) or above X11 is available as an optional feature from the install CDs. In addition the X11 server can be downloaded from [www.apple.com] . Unfortunately Apple doesn't have an obvious link to the older versions for Mac OS X 10.2, but VersionTracker has a link: [www.versiontracker.com]
You can get the gtk libraries under OS X via darwinports from [darwinports.opendarwin.org]
Daniel Macks and Ben Hines <bhines at alumni dot ucsd dot edu> have also put work into making packages available via Fink on the unstable tree: GNOME at [fink.sourceforge.net] and pygtk 2 specifically at [fink.sourceforge.net] . As of June 2008, Fink does not have pygtk available for Python 2.5 or OS X 10.5 (Leopard).
1.20. Can I use PyGTK to build closed-source applications?
1.21. Does PyGTK have timers?
See [nkour.blogspot.com] for a very easy example on how to use timers in PyGTK
2. Changes from 1.2 to 1.3/2.0
2.1. How do I install PyGTK-2 and PyGTK-0 side by side in the same system?
(There are three different ways detailed to solve this problem, but I will not recommend methods 2 and 3 unless you are unable to upgrade to a version that supports method 1).
- Method 1 (the "pygtk.pth" method)
For PyGTK >= 0.6.10, gnome-python >= 1.4.3 or pygtk2 >= 1.99.13 ONLY! (See faq 2.5)
(Note that RedHat 8.0 ships versions PRIOR to these, you will need to either upgrade the system packages, or use method 2 if you want to install PyGTK-0 and PyGTK-2 together on RH8.)
James has added to pygtk a mechanism that allows installation of both pygtk and pygtk2 to work side by side. This method should be transparent - you can install both versions and simply require one or the other for each program you need (the default being the one you install last), as per faq 2.4. It is implemented by using a pygtk.pth file that indicates which is the default (which one `import gtk' uses) version.
Note that pygtk.pth only works if you use the *default python install path* - if you specify a --prefix to configure it will not work and you will *have to use method 2*!
- Method 2 (PYTHONPATH):
You can install the two conflicting versions to a different prefix. When configuring pygtk2, use something like:
./configure --prefix=/usr/local/gtk2/All pygtk2 files will be installed in this case to
/usr/local/gtk2/lib/pythonX.Y/site-packages/With X.Y replaced by the major and minor numbers in your python version. You will then need to adjust PYTHONPATH (or sys.path) to look at the correct version for the program you want to run. If it requires pygtk2, you could use something like:
export PYTHONPATH=/usr/local/gtk2/lib/pythonX.Y/site-packages/:$PYTHONPATH
- Method 3
You can change PyGTK-2.x's module name to something else. Thomas Leonard has released a patched version that renames the module name to gtk2, available publically at [west.dl.sourceforge.net] See [rox.sourceforge.net] for more information. To use this version, change the first line of your PyGTK-2 programs from
import gtkto
import gtk2 as gtkThis module is not up to date, however, and this is the least recommended method.
2.2. What are the major changes in PyGTK-2 for GTK+ 2.2?
- Python 2.2 is required.
- The old, non-object-oriented C module _gtkmodule.so (accessed normally using "import _gtk" does not exist any more; this code will have to be converted to use the classes provided by the new pygtk.
- It is _strongly_ recommended that you use "import gtk" rather than "from gtk import *"
- The Gtk and Gdk prefixes on classes are gone. This can be fairly easily fixed with simple search and replace operations (gtk.GtkFoo goes to gtk.Foo, and gtk.GdkFoo goes to gtk.gdk.Foo).
- The GDK prefix for constants is gone and the GDK module is gone too. Now the constants are defined in the gtk.gdk module. For instance GDK_2BUTTON_PRESS is wrapped as gtk.gdk._2BUTTON_PRESS, and GDK_BUTTON_PRESS is gtk.gdk.BUTTON_PRESS.
- Widgets are now new style Python 2.2 classes. This probably won't affect anyone.
- Widgets that are considered "broken" (as opposed to deprecated) are not included in the binding. This list is fairly small though:
- GtkText (replaced by GtkTextBuffer/GtkTextView) - GtkTree and GtkTreeItem (replaced by GtkTreeView and GtkTreeModel)
- The new pygtk fixes a number of memory and reference leaks. This may cause you some problems as objects might get freed when previously they would have stayed around (ie. leaked). However, the changes should make PyGTK a bit more predictable.
- All GObjects now have at most one wrapper for their lifetime. This gets rid of the questions about what happens to the attributes set on an object when in a signal handler.
Overall, PyGTK-2 should be a much nicer PyGTK to program with. If you are working on new code, it would be best to use PyGTK-2 instead of 0.6.x.
What's more, there is even some documentation for PyGTK-2, available at [www.gnome.org]
2.3. Is there a checklist of changes to migrate an application from PyGTK-0 to PyGTK-2?
- Because PyGTK now support multiple versions being installed in parallel, you need to signal which one you want to use. ie:
import pygtk
pygtk.require('2.0')
import gtk
- If you used from gtk import *:
* use import gtk instead * from gtk import * * s/mainloop/gtk.mainloop/g # and other functions calls like 'mainquit' * s/Gtk/gtk./g
- If you used import gtk:
* s/Gtk//g
- Window doesn't accept a title keyword parameter to the constructor, use set_title():
- win = GtkWindow(title="Foo bar baz")
+ win = gtk.Window()
+ win.set_title("Foo bar baz")
- Label doesn't accept a label keyword parameter to the constructor: it now requires a string as an argument:
- label = GtkLabel(label="Foobar")
+ label = gtk.Label("Foobar")
- GtkText should be changed to a combination of GtkTextBuffer and GtkTextView:
- self.text = GtkText() + self.textbuffer = gtk.TextBuffer(None) + self.text = gtk.TextView() + self.text.set_buffer(self.textbuffer)
- TextBuffer offers insert_at_cursor, use it instead of GtkText.insert_defaults:
- self.text.insert_defaults( use_var ) + self.textbuffer.insert_at_cursor( use_var,len(use_var) )
- If you use GtkPixmap, it should be converted to gtk.Image, and use Image.set_from_pixmap() in place of GtkPixmap.set().
- Fonts can not be changed by altering the font attribute of the GdkStyle object (if you do style.font = foo it will silently be ignored). Instead, you must use something like:
entry = gtk.Entry()
font_desc = pango.FontDescription('monospace')
entry.modify_font(font_desc)
- To get a GdkWindow use the "window" instance attribute (Note that the widget needs to be realized before the GdkWindow is set):
entry = gtk.Entry() entry.realize() win = entry.window
- The GtkDrawingArea no longer offers proxy methods to its GdkDrawable's methods. In other words, you need to replace calls that looked like drawingarea.draw_point() with:
drawingarea.window.draw_point()
- clip_rectangle(), a method associated to GdkGC, requires a tuple to be passed in (it complains about a GdkRectangle) which is converted internally by PyGTK to a GdkRectangle:
gc.set_clip_rectangle((x, y, width, height))
- If you use a wheel mouse, listen to the new "scroll_event" signal. The old button 4/5 events are not generated anymore (jamesh says: The fact that the scroll wheel on your mouse generates button 4 and 5 events in X is an implementation detail, and was a bit of a pain for other GDK backends to implement.)
- OptionMenu wants get_children() instead of children()
option_menu=tree.get_widget("optionmenu1")
sometext=option_menu.get_children()[0].get()
- Function set_usize() is deprecated and should be replaced by set_size_request()
- Function GtkWindow.set_uposition() is deprecated and GtkWindow.move() should be used in its place.
2.4. If I installed PyGTK-0 and PyGTK-2 in parallel (using pygtk.pth) how do I indicate which one my script should use?
pygtk.require("1.2") # for pygtk-0
and
pygtk.require("2.0") # for pygtk2
Note that you should do this before importing the gtk or gnome modules:
# To require 2.0
import pygtk
pygtk.require("2.0")
import gtk, gtk.glade, gnome, gnome.ui
or:
# To require 1.2
import pygtk
pygtk.require("1.2")
import gtk, libglade, gnome, gnome.ui
If this simply doesn't work, please visit FAQ 2.6 for the nitty-gritty.
2.5. Which versions of PyGTK support parallel install using the pygtk.pth method?
- pygtk-0.6.10 - gnome-python-1.4.3 - pygtk2-1.99.13So any version equal to or later than that is fine. Note that 0.6.10 and 1.4.3 had bugs in it, and you should upgrade to 0.6.11 and 1.4.4 if possible.
Note that these versions are more recent than the version shipped in RedHat 8.0, so RH8.0 does NOT support parallel install using method 1 described in faq 2.4.
2.6. FAQ 2.4 sucks and doesn't work. Truthfuly, how do I require a specific version of PyGTK (or When do I need to use pygtk.require())?
If you installed pygtk to a non-standard directory (i.e., not in your python installation's site-packages directory), you will need to manually set pythonpath accordingly, and take care of python versions youself (checking pygtk_version, for instance). If you installed it into a standard directory, read below.
We have now a concept of a `default pygtk version'. This is the version that you get if you do a simple 'import gtk' in Python. Precisely which is the default version varies:
- If you are using a dual-install version of pygtk (faq 2.5) it depends on the contents of a file called pygtk.pth, which is installed into the python site-packages directory. It's written there by the pygtk source tarball's `make install' target, so if you compile and install pygtk2 after pygtk0 the default will be pygtk2 and vice-versa.
- If you are using an older version of pygtk, you will need to check pygtk_version yourself, noting that you won't be able to select versions using the pygtk module.
To *make sure* you get the right version, you can use:
import pygtk
pygtk.require("1.2") # or 2.0 etc
Which I recommend for maximum cross-site functionality. HOWEVER, not all versions of pygtk offer the pygtk module (again, see faq 2.5). So to do the right thing, you need to wrap that in a try/except clause, and use a check for the previous versions. Something like the following should work if you want to make sure you have version 1.2:
# Make sure we have version 1.2. Swap for 2.0 as necessary.
def get_gtk():
print """You need to get version 0.6 of PyGTK for this to work. You
can get source code from http://ftp.gnome.org/pub/gimp/gtk/python/v1.2/ """
raise SystemExit
try:
import pygtk
pygtk.require("1.2")
except ImportError:
try:
import gtk
except ImportError:
get_pygtk()
if not hasattr(gtk, "GtkWindow"): # renamed in version 2.0
get_pygtk()
except AssertionError:
get_pygtk()
import gtk # we KNOW this is 1.2 at this point
[...]
[The whole pygtk.pth handling has shown itself to be something of a mess, unfortunately, and a separate gtk2 namespace might have saved us some trouble, IMHO. - Kiko]
2.7. What happened to the GTK and GDK constants/symbols?
So GDK_2BUTTON_PRESS is wrapped as gtk.gdk._2BUTTON_PRESS, while GDK_BUTTON_PRESS is gtk.gdk.BUTTON_PRESS (no underscore).
One exception is the keysyms constants. They are accesed through gtk.keysyms.KEY. To see the legal values of KEY just do a
import gtk
print dir(gtk.keysyms)
- For PyGObject Inspection
Robert Park explained the C enumeration naming rule in PyGObject inspection as of v2.26 [1]:
... the file /usr/share/gir-1.0/Gtk-2.0.gir holds all the answers. It's the introspection data in XML format, so it's mostly human readable.
For example, I needed to know the new name for the constant Gtk.TREE_VIEW_COLUMN_AUTOSIZE, so I searched through the .gir file, and eventually found this:
<enumeration name="TreeViewColumnSizing"
glib:type-name="GtkTreeViewColumnSizing"
glib:get-type="gtk_tree_view_column_sizing_get_type"
c:type="GtkTreeViewColumnSizing">
<member name="grow_only"
value="0"
c:identifier="GTK_TREE_VIEW_COLUMN_GROW_ONLY"
glib:nick="grow-only"/>
<member name="autosize"
value="1"
c:identifier="GTK_TREE_VIEW_COLUMN_AUTOSIZE"
glib:nick="autosize"/>
<member name="fixed"
value="2"
c:identifier="GTK_TREE_VIEW_COLUMN_FIXED"
glib:nick="fixed"/>
</enumeration>
The new name of the constant is going to be "Gtk" plus the enumeration
name "TreeViewColumnSizing", plus the member name "autosize" in ALL
CAPS, separated by periods. So: Gtk.TreeViewColumnSizing.AUTOSIZE
On Debian, Gtk-2.0.gir can be found in the package gir-repository-dev.
More hints on PyGobject porting can be found in the pygi-convert script mentioned in PyGObject Introspection Porting page [live.gnome.org] .
2.8. For some users import libglade (or GDK) is working and for some users it's not
Figure out which one is working for your users, and change their script interpreter or path to use that one.
2.9. FAQ 2.4, 2.6 and etc etc all suck. Python still doesn't find the version of pygtk I want.
strace -eopen python <scriptname.py>will let you know where python is looking for the pygtk files. Knowing that, you can tweak PYTHONPATH, --prefix, require() and other assorted nasties to get your versioning correct.
Don't write to the mailing list complaining, because we all know it's hard to make it work. You'll have to debug yourself. Next time complain when a solution that brings endless hassle to installers is implemented!
2.10. How do I get my 1.2 gladefiles to work with 2.0?
There is a program included with libglade 2.0.x called libglade-convert that will do a pretty good job at converting the interface file to the new format. You should be able to edit the file in glade 1.1 after that.
Dave notes that you will probably have to redo all your dialog boxes, since they are going to be converted without some of the GTK 2 things, such as the correct active area interface and GTK 2 button images. You'll also have to redo your trees and lists to conform with GTK 2. A moderately sized project will take around 8 hours to do this to. Even if you don't "make install" libglade 2.0.x, you can use the Python file included (but renamed) in the distribution.
3. Signal handling
3.1. When I connect to a signal, my handler gets called but reports "XXX takes no arguments (1 given)"
To handle a callback, your function signature, therefore, must take this into account. Often you don't even want to use any of the arguments, just trigger an action on a certain signal; an easy way to do this is using a variable argument list (*args) and ignoring them in your method:
def on_win_delete(*args):
print "Deleted, and who cares why"
w = gtk.Window()
w.connect("delete-event", on_win_delete)
If you are attaching to a method, be sure to provide the usual self in the method definition, and specifying self.on_foo_signal as the function to attach to.
3.2. How do I detect that a mouse or keyboard event has been triggered?
The correct way is to hook to some of the basic event signals and then act upon receiving them. The signals you want to look for are:
- mouse motion - key presses - button pressesHowever, many widgets don't have their event masks properly set, so they will ignore these events. The following example shows how it should be done for a GtkWindow, adding the necessary event masks, and then hooking to the signals. Note that you would have to alter the wakeup function to handle the timer operations you would need for a screensaver.
def wakeup(widget, event):
print "Event number %d woke me up" % event.type
w = gtk.Window()
w.add_events(gtk.gdk.KEY_PRESS_MASK |
gtk.gdk.POINTER_MOTION_MASK |
gtk.gdk.BUTTON_PRESS_MASK |
gtk.gdk.SCROLL_MASK)
w.connect("motion-notify-event", wakeup)
w.connect("key-press-event", wakeup)
w.connect("button-press-event", wakeup)
w.connect("scroll-event", wakeup)
w.show()
gtk.main()
Note that mouse "scroll-wheel" events are implemented as button clicks
in the Xorg X11R6 server (button 4 for scroll up, button 5 for scroll
down).
3.3. I connected to some signals but nothing happens. Why?
The first is that some GTK+ widgets do not by nature receive events of any nature - GtkLabel comes to mind as an example. (The technical reason behind this is that they do not have their own X window, but use the one belonging to their parent widget. An X window is not the same as a GTK+ window, mind you; X windows on Unix systems are wrapped by GDK's GdkWindow, which is a lower-level creature). These widgets are listed at [www.moeraki.com] , and discussed further in gtkmm's tutorial: [www.gtkmm.org] . If you want to receive events for one of these widgets, you should add a GtkEventBox around it, and listen for events on that box.
l = gtk.Label("I want events.")
e = gtk.EventBox()
e.add(l)
e.add_events(gtk.gdk.POINTER_MOTION_MASK)
e.connect("motion-notify-event", handle_event)
Additionally, to receive signals, the widget's event mask must be set accordingly. In the answer to FAQ 3.2, for instance, we had to adjust it to receive pointer motion events (among others) - if we didn't, motion_notify_event would never be emitted.
The event masks are defined in the gdk module; they are constants whose name ends in "_MASK". They map directly to X11 masks, and there is a reference to what each X11 mask is at [tronche.com]
The functions that adjust the masks are:
widget.set_events()and
widget.add_events()the second one only adding to the widgets mask, the first one in effect replacing the original mask (* though I believe the "factory supplied" mask is not replaced, but added to, even in the case of set_events()).
In the specific case of the key_press_event, the GTK+ event queue treats this signal specially to manage the widget keyboard focus.When it sees key events targetted at any subwindow within the toplevel, they are redirected to the toplevel GtkWindow. The key_press_event handler for the toplevel window checks to see if the key event corresponds to an accelerator/mnemonic (and activates the appropriate widget if so), or passes the key event on to the widget with focus. In short: if you want a global keyhandler, attach it to your application's GtkWindow(s).
Finally, understanding how the signal propagation system works is also helpful when you run into a tricky situation - you should check out FAQ 3.11 which has more information on this.
3.4. I've fiddled with the mask but nothing happened. Why?
<jamesh_> yeah. A number of the masks cover multiple events and some events are selected by different masks
All event mask constants end with _MASK, and that is a good rule to remember. When doing add_events, you do NOT want (see, no _MASK!):
widget.add_events(gtk.gdk.MOTION_NOTIFY | gtk.gdk.BUTTON_PRESS)This is the correct command:
widget.add_events(gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.BUTTON_PRESS_MASK)(This example is particularly tricky because using BUTTON_PRESS will actually enable the pointer motion mask; this happens because the of the numeric constants used. Remember _MASK.)
3.5. Which widgets are unable to receive events or be styled?
Alignment AspectFrame Arrow Bin HBox VBox Frame Image Label Pixmap ScrolledWindow HSeparator VSeparator Table
3.6. I attach a callback to a signal, but I keep getting an error: "TypeError: object of type X is not callable"
#
# WRONG
button = gtk.Button(label="Quit")
button.connect("clicked", gtk.main_quit())
As you can see, gtk.main_quit() is a call, not the function name. The correct way to do it would be:
# RIGHT
button = gtk.Button(label="Quit")
button.connect("clicked", gtk.main_quit)
Always remember to use gtk.main_quit() instead of gtk.mainquit() since the last one is deprecated.
3.7. How can I force updates to the application windows during a long callback or other internal operation?
This is by design: all gtk events (including window refreshing and updates) are handled in the mainloop, and while your application or callback code is running the mainloop can't handle window update events. Therefore nothing will happen in the application windows.
The trick here is to realize where your operation can take a while to return, or where it is dynamically changing the window contents, and add a code fragment like this wherever you want an update forced out:
while gtk.events_pending(): gtk.main_iteration(False)This tells gtk to process any window events that have been left pending. If your handler has a long loop, for instance, inserting this snippet as part of the loop will avoid it hanging the window till the callback has finished.
More eloquently, in the words of the great Malcolm Tredinnick, 'this requires using what should be called "Secret Technique #1 For Making Your Application Look Responsive"(tm):
If you want to avoid freezes in your application while you are doing large amounts of work in the background, remember to call gtk.mainiteration() from time to time.'
Of course, if your callback has a single instruction that takes a long time to process, this isn't an option. There is no easy alternative to solve this problem, as far as I can see. Doug Quale remarks on how this applies even to idle_add()ed functions:
Idle functions are scheduled when gtk+ doesn't have any other work to perform, but gtk+ doesn't preempt them. Each idle function will run to completion once it's started.
Note that running a mainiteration inside an idle, io (input_add) or timeout handler is generally considered `a bad idea' because it doesn't work very well. If you really need to do so, check FAQ 20.1.
Moreover if during the computation you want to lock the GUI (no operation can be performed) without making all the widget insensitive you can use the other secret technique called "Yeti"... [1]
import gtk
from time import sleep
def response(widget, response_id):
if response_id != gtk.RESPONSE_APPLY:
gtk.main_quit()
else:
i=0
n=1000
progress = dialog.get_data("progress")
progress.set_text("Calculating....")
progress.grab_add()
while i < n:
sleep(0.005)
progress.set_fraction(i/(n - 1.0))
i += 1
while gtk.events_pending():
gtk.main_iteration_do(False)
progress.set_fraction(0.0)
progress.set_text("")
progress.grab_remove()
dialog = gtk.Dialog("Modal Trick", None, 0, (gtk.STOCK_EXECUTE, gtk.RESPONSE_APPLY,
gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE))
dialog.connect("response", response)
dialog.connect("destroy", gtk.main_quit)
box = dialog.get_child()
widget = gtk.CheckButton("Check me!")
box.pack_start(widget, False, False, 0)
widget = gtk.Entry()
box.pack_start(widget, False, False, 0)
adj = gtk.Adjustment(0.0, 0.0, 100.0, 1.0, 10.0, 0.0)
widget = gtk.HScale(adj)
box.pack_start(widget, False, False, 0)
widget = gtk.ProgressBar()
box.pack_start(widget, False, False, 0)
dialog.set_data("progress", widget)
dialog.show_all()
gtk.main()
This way the GUI does not freeze and you cannot interact with widgets, if you like you can unlock one widget (e.g. you want to give the chance to block the long process) using gtk.grab_add() on that widget.
[1] [mail.gnome.org]
3.8. I want my callback to execute, but not the default callback (or, how to I stop GTK from doing the default action when doing X)?
The process to disable a default action is:
- Find out what signal is being emitted and handled by the default handler. Many times you already know the signal since you may be hooking to it already, and observing the default action happen after yours.
- call widget.emit_stop_by_name("signal_name") (to stop the signal emission in the current widget)
- return True (to make sure that the signal won't propagate into parent handlers that may be the actual culprits for the default action)
An example of this usage was reported by Graham Ashton. He had customized a keypress handler for a window, but every time the user triggered the Alt-arrow combination he was handling, the focus moved around between the widgets in the interface (as is the default behaviour).
The solution was simply calling window.emit_stop_by_name("key_press_event") and returning True.
3.9. When creating a new signal, how do I define one of the signal arguments as Python data?
When you add your signal using gobject.signal_new(), use gobject.TYPE_PYOBJECT as the type for the argument being passed in:
gobject.signal_new("signal", ClassName,
gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
(gobject.TYPE_PYOBJECT,))
And then you can emit the signal with Python objects:
mydict = {}
mydict["foo"] = "bar"
class_instance.emit("signal", mydict)
And get them when you connect on the other side:
def signal_cb(instance, mydict):
print mydict["foo"]
class_instance.connect("signal", signal_cb)
3.10. How do I specify user data to a signal?
widget.connect("my_signal", handler, userdata [, ...])
As you can see, you can pass as many items as userdata; the function will receive the same number of user data arguments.
3.11. How do signals and events propagate in GTK+?
A single signal emission will only call handlers attached to the object it was emitted on. The propagation of events up the heirachy is acheived by emitting the signal a number of times.
For events such as the button presses and motion events, the event is delivered first to the widget the event occurred in. It will emit the appropriate event signal. If the event signal returns false (indicating that the event hasn't been handled), then a signal will be emitted on the parent. This continues all the way up to the toplevel if no one handles the event.
Keyboard events are handled differently. When your window receives a keyboard event, it is first dispatched to the toplevel window, which will check if it matches any keyboard shortcuts. If the key press doesn't match a shortcut, then the event is dispatched to the child widget that currently has focus.
3.12. Why does handling expose events break drag-n-drop?
queue_draw_area(x_beg, y_beg, x_end, y_end)in your expose_event handler, don't. It seems to break event propagation which causes drag and drop to not work any more.
3.13. How do I pass extra data to a signal handler?
Suppose you have a dialog with an entry widget. If you want the dialog response handler to do something with the entry value, you could connect to the response signal like this
dialog.connect('response', on_dialog_response, entry)
This lets you easily access methods of the entry widget in the signal handler, perhaps to get the text in the entry
def on_dialog_response(widget, response, entry):
if response == gtk.RESPONSE.ACCEPT:
print 'Accepting', entry.get_text()
Something that might trip you up especially if you are new to Python programming is that you probably don't want to try to pass the entry text to the signal handler like this
# probably wrong!
dialog.connect('response', on_dialog_response, entry.get_text())
The get_text() method is executed when the signal is connected so this would pass a constant value as the extra data. Usually you will want the signal handler to see the current state of the entry widget.
3.14. How to construct my own "fake" gtk.gdk.Event?
event = gtk.gdk.Event(gtk.gdk.KEY_PRESS)
event.keyval = gtk.keysyms.Return
event.state = gtk.gdk.CONTROL_MASK
event.time = 0 # assign current time
widget_that_should_accept_signal.emit('key_press_event', event)
the last line "passes" the signal to the widget we want to handle this fake event.
3.15. How do I pass data to a signal handler in Glade?
In practice, don't even try. Pygtk 2 and Glade are both too buggy to attempt this. Manually connect any signals that need user data.
4. Themes, fonts and styles
4.1. How do I change font properties on gtk.Labels and other widgets?
label = gtk.Label("MyLabel")
label.modify_font(pango.FontDescription("sans 48"))
This method applies to all widgets that use text, so you can change the text of gtk.Entry and other widgets in the same manner.
Note that, some widgets are only containers for others, like gtk.Button. For those you'd have to get the child widget. For a gtk.Button do this:
if button.get_use_stock():
label = button.child.get_children()[1]
elif isinstance(button.child, gtk.Label):
label = button.child
else:
raise ValueError("button does not have a label")
4.2. Why don't my style changes apply only to the widget I requested it from?
get_style() returns an object what aways have the current style of widget. If you want to save an static style, use get_style().copy() instead:
style = widget.get_style().copy()This has some pretty odd effects. If you are creating a window with many gtk.Label's, for instance, and you alter the actual style object (not a copy() if it), all widgets will eventually change style (when they are redrawn by GTK+).
4.3. My user defined styles get overridden by the default theme!
I have succesfully changed the bg colour of some buttons in my program by the use of styles. But..
As soon as my beautiful greenish colour has been painted onto the buttons, my default pixmap theme paints it over with it's gradient grey.
How do I stop this?!
I know I can stop it by choosing a different engine (like notif), but I want to use the default engine... See the prob?
XXX: NEEDS ANSWER
4.4. How do I change the background color of my application's dialog?
4.5. How do I use the style object?
The style is shared between widgets of the same type (XXX: is this true?). To change the style of only one widget in your application, the style object offers a copy() method, which returns a new copy of the GdkStyle, which can me changed and set_style() back to the desired widget.
All attributes of a style can be get and set independently by direct access. The most important attributes of style are the colours (see faq 4.6):
- fg
- bg
- light
- dark
- mid
- text
- base
- black
- white
And the font and bg_pixmap attributes.
4.6. How do I change the colour of a widget (or how do I get a GdkColor)?
There is some confusion about GdkColor and how it is created. There are both the GdkColor() class and colour_alloc() that seem to do the right thing, but they are both duds (as far as I can tell).
The right way of creating a colour is getting the colormap from the widget and using it to allocate a new colour using the GtkColorMap's alloc method:
e = gtk.Entry()
map = e.get_colormap()
colour = map.alloc_color("red") # light red
This way you end up with a red GdkColor in the variable colour. Apart from the X11 rgb.txt names, you can also use hex triplets:
colour = map.alloc_color("#FF9999") # light red
See FAQ 4.8 for more information on alloc_color.
The next step is understanding how to manipulate GtkStyle's colour attributes, which are actually dictionaries: each attribute maps a number of different gtk constants that indicate states:
- gtk.STATE_NORMAL, the normal state of the widget.
- gtk.STATE_ACTIVE, a clicked button or checkbutton, etc.
- gtk.STATE_INSENSITIVE, when the widget is insensitive (set_sensitive(0))
- gtk.STATE_PRELIGHT, when onmouseovered
- gtk.STATE_SELECTED, when part of the widget is selected (text in a GtkEntry, or a selected radiobutton)
So, to change the default border of our entry above to red:
style = e.get_style().copy() style.bg[gtk.STATE_NORMAL] = colour e.set_style(style)Final hint: the default colour for a GtkEntry background is gray84.
4.7. How do I get a Graphics Context, or GdkGC?
gdkwin = widget.window gc = gdkwin.new_gc()The widget must be realized. Then you are free to set the gc's background/foreground, etc. More information on the GdkGC is available at [www.moeraki.com]
4.8. How does the alloc() method to the GdkColormap work?
cmap = widget.get_colormap()
color = cmap.alloc_color("#FFCCAA")
color = cmap.alloc_color("red")
color = cmap.alloc_color(0, 0, 65535)
Note that the third format uses a tuple to specify the individual values for Red, Green and Blue (RGB), each item being an integer from 0 to 65535 (corresponding, therefore, to 0x0-0xFF).
Complete reference documentation on GdkColormap is available at [pygtk.org]
4.9. How do I use pango instead of GdkFont for font handling in a GtkDrawingArea?
import pango
# create a font description
font_desc = pango.FontDescription('Serif 12')
# create a layout for your drawing area
layout = darea.create_pango_layout('hello pango!')
# tell the layout which font description to use
layout.set_font_description(font_desc)
# draw the text with the draw_layout method
darea.window.draw_layout(gc, x, y, layout)
You can find out about the size of the text by using the get_pixel_size() method from your pango layout object. e.g.:
# get the pixel size of a layout text_width, text_height = layout.get_pixel_size()
4.10. How can I use Unicode (or other format) strings in my PyGTK application, or, why do I get a UTF-8 warning when using a string?
If, however, your string is an str ("some string") object, PyGTK requires it to be in UTF-8. Otherwise you will see a warning like this:
WARNING **: Invalid UTF8 string passed to pango_layout_set_text()and your text will be displayed incorrectly.
Luckily, fixing this is trivial in Python by converting the str into a unicode object:
unistr = unicode('your iso 8859-15 text', 'iso8859-15')
# or: 'your iso 8859-15 text'.decode('iso8859-15')
label = gtk.Label(unistr)
If you have no clue about the character encoding used, you can still convert it while silently ignoring errors:
unistr = unicode('text with an unknown encoding', errors='replace')
This will replace any unknown character by the official Unicode replacement character (U+FFFD).
4.11. How can I create a new pango context()
A: widget.create_pango_context() should give you a new one.
Note that pango.Context() doesn't work: PangoContext is really an abstract interface. There are currently context implementations for core X fonts (already removed from the HEAD branch), Xft, Win32 and freetype. Widget.create_pango_context() will create a context appropriate for use with that widget, so you don't need to worry about these details.
4.12. How do I get antialiased fonts in GTK+?
export GDK_USE_XFT=1It's on by default on 2.2 onwards, and in 2.4 the core engine is no longer used by GTK+.
Note that the Xft backend is much better at producing scaled versions of the fonts. The reason is that the core X font system, when you use scalable fonts, will render the entire set of glyphs as bitmaps at the requested size when you open the font (which isn't fast or a good use of memory -- it quite large for big point sizes or fonts with large coverage, such as with Asian fonts).
4.13. Does PyGTK support TrueType fonts?
Note that the way the font is rendered is handled by the rendering backend; see FAQ 4.12 for more information.
4.14. What units does pango use to define sizes and widths?
4.15. Can I find out how long (wide) a string is in a certain font?
context = widget.get_pango_context()
metrics = context.get_metrics('font name, 12')
width = pango.PIXELS(metrics.get_approximate_char_width() * n_chars)
(See FAQ 4.14 to understand how PIXELS() works)
For a monospaced font, this should be quite accurate. You can then use widget.set_size_request() if you would like to set that width as the minimum width for the widget/view.
In PyGTK-0.6, you can ask the font directly how long a given string is going to be, as well as how high. Retrieve the font object from the style, and then query it with the string in question:
font = widget.get_style().font h = font.height(my_string) w = font.width(my_string)The methods return pixel counts. You can then set the size manually to any function of those parameters. For instance, to make a widget twice as wide and as high as the string you measured with, use:
widget.set_usize(w*2, h*2)[Credit: Andrew Reid <Andrew-dot-Reid-at-nist-dot-gov>]
4.16. How do I change the background and colour of an Editable (GtkEntry, GtkTextView and friends)?
widget.modify_fg(state, color) widget.modify_bg(state, color) widget.modify_base(state, color) widget.modify_text(state, color)Windowless widgets such as gtk.Label, gtk.Button, gtk.Paned, gtk.Frame, etc, (see FAQ 3.5) despite inheriting from gtk.Widget don't allow changing its background and base color as those properties don't exist for them. If you want to get them you need to insert the widget inside a gtk.EventBox which adds this properties. Example:
import gtk
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.connect("destroy", gtk.mainquit)
label = gtk.Label("one, two, testing...")
eb = gtk.EventBox()
eb.add(label)
eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("blue"))
window.add(eb)
window.show_all()
gtk.main()
4.17. Why does FontSelection's set_font_name return False?
>>> w = gtk.Window()
>>> f = gtk.FontSelection()
>>> f.get_font_name()
'Sans 10'
>>> f.set_font_name('Sans 12')
False
>>> w.add(f)
>>> f.set_font_name('Sans 12')
True
Once added to the window, the result will indeed be True.
4.18. How do I change GtkMenubar.shadow_type (or other style properties)?
style "menubar-style" {
GtkMenuBar::shadow_type = etched-in
}
class "GtkMenuBar" style "menubar-style"
In this case, possible shadow_types are:
none, in, out, etched-in, etched-outIn general to find out what you can parse you have to check the enum, eg: [pygtk.org] s
Which can be passed on to gtk.rc_parse_string (or put in a file and then passed to gtk.rc_parse).
4.19. Can I pass strings of unicode instance to gtk or do I need to convert them to utf8?
label.set_text(u'abc')
So the above is indeed valid and not only to labels but to any widget.
5. Basic Objects: GObject, GtkWidget and other critters
5.1. I want to understand this "data" object that is used in the set_*_data() and get_*_data() calls.
For example, you can attach to a GtkLabel the instance it represents and a list of of versions using the following code:
l = gtk.Label()
l.set_data("object-name", some_object)
and then retrieve the data using:
>>> some_object = l.get_data("object-name")
There are also related methods associated with the CList/CTree, set/get_row_data(), and GnomeIconList's set/get_icon_data(). These methods don't index on string, but instead on position in their internal arrays.
5.2. How do I check if a widget is currently sensitive?
if widget.get_property('sensitive') == 0:
print "I'm insensitive!"
Note: In ancient versions of pygtk (0.6.x) you could access them using a dictionary interface, this was removed in the 2.x series.
More recently (since PyGTK 2.8) the following method can be used:
if not widget.props.sensitive:
print "I'm insensitive!"
More info here: [live.gnome.org]
5.3. Where is get_state() in PyGTK 0.6.x?
And therefore no way to wrap it in pygtk. There are actually a number of state constants defined in gtk:
gtk.STATE_ACTIVE gtk.STATE_NORMAL gtk.STATE_SELECTED gtk.STATE_INSENSITIVE gtk.STATE_PRELIGHTbut they are to be used with set_state(). In pygtk2, get_state() is implemented and wrapped.
5.4. How do I catch right-click, middle-click and double-click on my widget?
window.add_events(gtk.gdk.BUTTON_PRESS_MASK)You can easily capture a specific button press pattern by checking event.button and comparing event.type with the constants defined in gtk.gdk for multiple button presses. To do this, connect a handler like this one to "button_press_event" on your widget:
def button_clicked(widget, event):
# which button was clicked?
if event.button == 1:
print "left click"
elif event.button == 2:
print "middle click"
elif event.button == 3:
print "right click"
# was it a multiple click?
if event.type == gtk.gdk.BUTTON_PRESS:
print "single click"
elif event.type == gtk.gdk._2BUTTON_PRESS:
print "double click"
elif event.type == gtk.gdk._3BUTTON_PRESS:
print "triple click. ouch, you hurt your user."
Note that it seems that, at least in PyGTK 0.6.x (confirm for 2.x), spawning a modal dialog when handling a double-click event causes a strange focus bug. I've experienced this personally, but this message confirms the problem:
[mail.gnome.org]
To work around it, I changed the modality using idle_add(win.set_modal, 1) before calling mainloop, but it's a very ugly fix.
5.5. How do I capture keypresses, and how do I perform a certain action depending on the key pressed?
def on_key_press_event(widget, event):
keyname = gtk.gdk.keyval_name(event.keyval)
print "Key %s (%d) was pressed" % (keyname, event.keyval)
w = gtk.Window()
w.connect('key_press_event', on_key_press_event)
If you want to block a specific key from being catched by a widget,
just return True in the key_press_event signal handler.
Which will print out the key pressed for that window. To use a specific handler for each key pressed, you can set something up like this:
def on_key_press(self, widget, event):
keyname = gtk.gdk.keyval_name(event.keyval)
func = getattr(self, 'keypress_' + keyname, None)
if func:
return func()
def keypress_A(self):
print "A was pressed!"
def keypress_B(self):
print "B was pressed!"
To capture Control, Alt and Shift combinations, you need to use the gtk.gdk symbols CONTROL_MASK, MOD[1-5]_MASK and SHIFT_MASK and do a binary AND to event.state:
def on_key_press(widget, event):
keyname = gtk.gdk.keyval_name(event.keyval)
print "Key %s (%d) was pressed" % (keyname, event.keyval)
if event.state & gtk.gdk.CONTROL_MASK:
print "Control was being held down"
if event.state & gtk.gdk.MOD1_MASK:
print "Alt was being held down"
if event.state & gtk.gdk.SHIFT_MASK:
print "Shift was being held down"
w = gtk.Window()
w.connect('key_press_event', on_key_press)
5.6. How do I change the cursor for a certain widget?
- You need to create a gtk.gdk.Cursor object first. It's constructor takes a gtk.gdk constant from the list at the end of this faq entry.
- To apply the cursor to a widget, you need to to use gdk.Window's (gdk, _not_ gtk) set_cursor() method (which requires the widget to have an associated X window, as per faq 3.3).
- To change it back to the default cursor, call set_cursor(None).
To change it for a button,
def realize_cb(widget):
b.window.set_cursor(watch)
b = gtk.Button()
watch = gtk.gdk.Cursor(gtk.gdk.WATCH)
b.connect("realize", realize_cb)
And to change it back to normal:
b.window.set_cursor(None)To make an invisible cursor (aka hide the cursor), you can use this code:
pix_data = """/* XPM */
static char * invisible_xpm[] = {
"1 1 1 1",
" c None",
" "};"""
color = gtk.gdk.Color()
pix = gtk.gdk.pixmap_create_from_data(None, pix_data, 1, 1, 1, color, color)
invisible = gtk.gdk.Cursor(pix, pix, color, color, 0, 0)
b.window.set_cursor(invisible)
To change it for a label, which lacks its own gdk.Window, for instance:
boat = gtk.gdk.Cursor(gtk.gdk.BOAT) b = gtk.EventBox() l = gtk.Label() b.add(l) b.window.set_cursor(boat)Note that the widget may already define a cursor: for instance, GtkEntry defines an I-bar for the cursor. X allows you to set a cursor on each gdk.Window, and if a window doesn't have a cursor associated with it, it gets the parent window's cursor.
To change the cursor for all the widgets, you'd need to recurse into all child widgets and set_cursor() on their gdk.Windows.
However, there is an other way, that can be implemented using some gdk.Window functions. For details, read: [www.daa.com.au]
It is also worth noticing that some widgets are composed of multiple X windows. gtk.Entry is an example -- see FAQ 14.3 (you can use the gdk.Window's children() method to get its child windows). Another example is TextView, described in FAQ 14.15.
The constants for icons defined in gtk.gdk are:
X_CURSOR ARROW BASED_ARROW_DOWN BASED_ARROW_UP BOAT BOGOSITY BOTTOM_LEFT_CORNER BOTTOM_RIGHT_CORNER BOTTOM_SIDE BOTTOM_TEE BOX_SPIRAL CENTER_PTR CIRCLE CLOCK COFFEE_MUG CROSS CROSS_REVERSE CROSSHAIR DIAMOND_CROSS DOT DOTBOX DOUBLE_ARROW DRAFT_LARGE DRAFT_SMALL DRAPED_BOX EXCHANGE FLEUR GOBBLER GUMBY HAND1 HAND2 HEART ICON IRON_CROSS LEFT_PTR LEFT_SIDE LEFT_TEE LEFTBUTTON LL_ANGLE LR_ANGLE MAN MIDDLEBUTTON MOUSE PENCIL PIRATE PLUS QUESTION_ARROW RIGHT_PTR RIGHT_SIDE RIGHT_TEE RIGHTBUTTON RTL_LOGO SAILBOAT SB_DOWN_ARROW SB_H_DOUBLE_ARROW SB_LEFT_ARROW SB_RIGHT_ARROW SB_UP_ARROW SB_V_DOUBLE_ARROW SHUTTLE SIZING SPIDER SPRAYCAN STAR TARGET TCROSS TOP_LEFT_ARROW TOP_LEFT_CORNER TOP_RIGHT_CORNER TOP_SIDE TOP_TEE TREK UL_ANGLE UMBRELLA UR_ANGLE WATCH XTERM CURSOR_IS_PIXMAPAlso if you plan to do anything time consuming and want to use the watch cursor you have to be careful that you don't starve the gui thread before it can change the cursor, e.g.
## This Will Not Work ## watch = gtk.gdk.Cursor(gtk.gdk.WATCH) gtk_window.set_cursor(watch) time.sleep(10) # your time consuming operation here gtk_window.set_cursor(None)instead call the time consuming in an idle callback (or in a different thread if you absolutely have to)...
def idle_cb(gtk_window):
time.sleep(10) # your time consuming operation here
gtk_window.set_cursor(None)
watch = gtk.gdk.Cursor(gtk.gdk.WATCH)
gtk_window.set_cursor(watch)
gobject.idle_add(idle_cb, gtk_window)
5.7. How can I tell my program that the cursor should jump to a specific widget?
entry = gtk.Entry() [...] entry.grab_focus()
5.8. What signal is triggered when I change a widget's sensitivity?
5.9. How do I find out the size of a widget?
>>> win = gtk.Window() >>> win.realize() # or win.show() >>> rect = win.allocationWould return a gdk.Rectangle, which can be accessed by using:
>>> rect.width, rect.height, rect.x and rect.yor just convert it to a four sized tuple:
>>> t = tuple(rect)Meaning the widget is at the top left of the window, and is 158x22 pixels in size (the default size of a gtk.Entry, by the way)
To find out how high or wide a widget is (or would be) based on a string size and a font, see FAQ 5.16
5.10. How do I focus a widget? How do I focus it before its toplevel window is shown?
e = gtk.Entry() e.show() e.grab_focus() w = gtk.Window() w.add(e) # oh-oh, added after grab_focus() w.show()would NOT work, but
e = gtk.Entry() w = gtk.Window() w.add(e) e.grab_focus() # called after add w.show_all() # no need for e.show() in this casewill work as expected (using idle_add() to call grab_focus() is naughty and we know that python hackers are never naughty :-P ).
5.11. My callback is getting a gtk.gdk.Event object, but I need an EventExpose!
event.area.x
5.12. How do I check if a widget is mapped? And realized? And visible? [...]
In PyGTK the method is called flags(), and it doesn't take arguments, so you must perform the binary AND yourself:
# To check if `widget' is mapped:
if widget.flags() & gtk.MAPPED:
print "MAPPED!"
There are a number of flags you can test for. The following are defined in the gtk namespace:
# gtk.Object DESTROYED FLOATING CONNECTED CONSTRUCTED # gtk.Widget TOPLEVEL NO_WINDOW REALIZED MAPPED VISIBLE SENSITIVE PARENT_SENSITIVE CAN_FOCUS HAS_FOCUS CAN_DEFAULT HAS_DEFAULT HAS_GRAB RC_STYLE COMPOSITE_CHILD BASIC APP_PAINTABLE RECEIVES_DEFAULT
5.13. While calling get_property(), I get an "invalid property id" warning. Why?
(:2640): Gtk-WARNING **: ../../gtk/gtkcontainer.c:874: invalid property
id 3 for "child" of type `GParamObject' in `GtkButton'
Pretty much all instances of write-only properties in GTK are ones that set some other property, but take a different format. For instance, setting the "markup" property on a gtk.CellRendererText object is equivalent to setting the "text" and "attributes" properties to appropriate values, however "markup" is not readable.
The GtkContainer "child" property looks more like a convenience. Setting the property adds the widget to the container. However, GtkContainer can have multiple children, so it isn't clear what should be returned when reading it.
5.14. How can I discover what properties and signals a GObject supports?
There are several methods to find out what properties and signals are supported in a GObject. First of all, you have the two introspection methods, so for properties use this:
>>> gobject.list_properties(obj)and for signals:
>>> gobject.signal_list_names(obj)Where obj is an instance or a type, which has the disadvantage of not showing a description or other detailed information, but can be used by programs, like gui builders or others. A better method for programmers is the help() method.
>>> help(obj)Where obj also is an instance or a type, it gives you more detailed information.
If the type is in gobject, atk, pango, gdk or gtk, the reference manual is preferred, check it out here:
5.15. How do I access one of these properties in a GObject?
>>> w = gtk.Window()
>>> w.set_title('My Window')
>>> w.show_all()
>>> print w.get_property('modal')
False
>>> print w.get_property('title')
'My Window'
5.16. What's the difference between a property and an attribute?
A property is a GObject property and can be read and write with the GObject.get_property (propname) and GObject.set_property (propname, value) methods.
An attribute is a mapping to the C struct of the GObject and can be read from and (sometimes) written to directly. For example:
adj = gtk.Adjustment(value=0, lower=0, upper=100, step_incr=1, page_incr=10, page_size=10) adj.value = 4.0Since PyGTK 2.8, GObject properties are now mapped as attributes of a special 'props' attribute (gnome bug #81879), so the following also works:
adj.props.value = 4.0
5.17. Do I need to handle reference counting for GObjects? What about for other objects in PyGTK/gnome-python?
- There is a reference cycle between the python wrapper and its underlying C object; this means that the object will not be automatically deallocated when there are no more user references, and you will need the garbage collector to kick in (which may take a few cycles). This occasionally causes the odd problem, such as with pixbufs described in FAQ 8.4
Note that while gnome-vfs objects are not based on GObject, and implement their own reference counting, it's the same from the point of view of Python code: nothing needs to be done. A significant difference in gnome-vfs objects is that they do not allow the programmer to add new attributes or subclass them. Also, they don't have reference cycles, so they are deallocated without help from the garbage collector.
Bonobo objects are GObject based, but they require manual reference counting. There are well defined rules for ownership semantics in remote calls: [developer.gnome.org] . However, for in-process bonobo API calls, there are no rules, and you have to be very careful with the ownership of the references obtained on a per API function basis. Unfortunately the API itself is underdocumented, so...
5.18. Focusing a widget after when selecting an item from Treeview
The solution is to add a timeout. This is how we do it:
# Connect Treeview with cursor-changed signal
treeview.connect("cursor-changed", self.timeoutFocus, focusme)
# The callback function:
# focusme is the widget that will be focused
def timeoutFocus(self,widget, focusme):
gobject.timeout_add(10, lambda: focusme.grab_focus())
and that's all folks!
5.19. How can I listen to events from the scroll wheel on my mouse?
gtk.gdk.SCROLL_UP, gtk.gdk.SCROLL_DOWN, gtk.gdk.SCROLL_LEFT, gtk.gdk.SCROLL_RIGHTExample:
def on_button_scroll_event(button, event):
if event.direction == gtk.gdk.SCROLL_UP:
print "You scrolled up"
b = gtk.Button()
b.connect('scroll-event', on_button_scroll_event)
5.20. How do I move focus between widgets?
1) you want to move focus to particular widget:
widget.grab_focus()
2) move focus from a widget to the next widget, as if user pressed Tab key:
widget.get_toplevel().child_focus(gtk.DIR_TAB_FORWARD)
You can use other gtk.DIR_* constants, they correspond to moving focus wit h other keys; gtk.DIR_TAB_BACKWARD corresponds to Shift-Tab.
6. Widget subclasses and user signals: GObject
6.1. What is the canonical reference on widget (and GObject) subclassing and property overriding?
6.2. When subclassing a widget (or a GObject), why are the additional signals I define not usable?
gtk.DrawingArea.__init__(self)Note, that the old syntax (__gobject_init__) is deprecated and should not be used. Note, that gobject.GObject.__init__ should only be called if you subclass the actual gobject.GObject class.
If you get a "signal XXX cannot be used for action emissions" message, it's also likely that you missed adding gobject.SIGNAL_ACTIONS to the signal flags in the signal definition.
Read more about GObject subclassing in Lorenzo's tutorial at [www.sicem.biz]
6.3. How do I wrap a GObject in Python?
It takes you throught the steps of generating the wrapper, customizing and compiling it, and then using it from Python. See also FAQ 1.11 for a walkthrough of the process.
6.4. How can I draw on top of a subclassed widget?
First, subclass the type properly and make sure the constructor is chained to properly:
class MyButton(gtk.Button):
def __init__(self):
gtk.Button.__init__(self)
Secondly, override the expose-event virtual method, it will be called as soon as the widget is asked to redraw it self
def do_expose_event(self, event):
The first thing we want to do here, is to call the gtk.Button code, to draw something which looks like a button. It's simple, just chain up to the expose_event of the button itself:
retval = gtk.Button.do_expose_event(self, event)
At this point, the button is drawn. Now you can make your own "drawings" on top of the widget.
self.window.draw_ ....()
Finally return the same return value as we got from the parents call
return retval
Don't forget to register the type:
gobject.type_register(MyButton)
23.33. Using metaclasses in GObject subclasses.
TypeError: Error when calling the metaclass bases
metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
In order to correct this you have to do the following:
class Foo:
__metaclass__ = MetaFoo
# This will throw an error
class Bar(Foo, gtk.Object):
pass
# This will not throw an error
class GMetaFoo(MetaFoo, gobject.GObjectMeta):
pass
class Bar(Foo, gtk.Object):
__metaclass__ = GMetaFoo
So, you must create a new metaclass that extends both the metaclass gobject.GObjectMeta and the metaclass used in the other class.
7. Labels: GtkLabel
7.1. How can I use mnemonics for my GtkLabel?
label = gtk.Label('_Change the above color')
label.set_property("use-underline", gtk.TRUE)
7.2. Where is GtkLabel.get_text()?
l = gtk.Label("foobar")
print l.get() # prints "foobar"
In PyGTK-2 you can use get_text() method:
>>> l = gtk.Label("foobar")
>>> print l.get_text()
foobar
>>>
and also get() method still works:
>>> print l.get() foobar
7.3. How do I make a GtkLabel font larger or bold?
bold = "-adobe-helvetica-bold-r-normal-*-*-120-*-*-p-*-iso8859-1" big = "-adobe-helvetica-medium-r-normal-*-*-180-*-*-p-*-iso8859-1" s = label.get_style().copy() font = gtk.load_font(bold) # or big if you want big. s.font = font label.set_style(s)If you are using pygtk-2, this is much easier, using pango. You can do things like:
label.set_use_markup(gtk.TRUE)
# weights
label.set_markup('normal text, <b>bold text</b>, <i>italic text</i>')
# size; 38000 = 38pt (use pt size * 1000)
label.set_markup('<span size="38000">big text</span>, normal text')
or even:
label = gtk.Label("<b>N</b>ame")
label.set_use_markup(True)
See [developer.gnome.org] for more information on pango's span attributes.
7.4. How do I left, center, right, top, bottom, middle align a GtkLabel?
Use the label's set_alignment feature, which already does everything for you:
l = gtk.Label("Text goes here")
l.set_alignment(xalign=1, yalign=0.5)
If you are using Glade, the labels already come with presets of xalign=0.5, yalign=0.5, and they can be changed in the widget tab of the properties dialog.
7.5. How do I change a Label's background color, or why doesn't my Label receive any signals?
This also happens to other windowless widgets.
If you want to provide such features to a label (or windowless widgets) you need to add the label to a gtk.EventBox in order to assign it a window and thus have some more properties (such as background) and the ability to catch its own signals.
You can even nest gtk.EventBoxes, with some border width, to get colored frames.
See FAQ 4.16 for an example
7.6. How do I render a label in a button or menuitem with an underscore in its label?
gtk.Button("_New order")
will underline the character "N", and will set an accelerator for the N key. If you want to literally print an underscore, use either double underscores:
gtk.Button("Foo__bar")
or set_use_underline(0):
button = gtk.Button("Foo_bar")
button.set_use_underline(0)
The same approach works as expected for menuitems. There is GTK+ documentation covering this at [developer.gnome.org]
(The question remains of why would you want to do such a thing.)
7.7. I set my labels to use_markup in glade-2. Why don't they markup the contents I set?
- always use set_markup() if you want the content you are setting to be parsed as markup -- do NOT use set_text() (it will happily ignore the markup and you will be left in a confused state where will you wander into this FAQ).
- The glade use_markup setting is actually the 'use-markup' gtk.Label GObject property. "use-markup" only controls how to interpret the text given in the 'label' property. label.set_text("foo") is roughly equivalent to:
label.set_property("use-markup", False)
label.set_property("label", "foo")
while label.set_markup("<i>bar</i>") is roughly equivalent to:
label.set_property("use-markup", True)
label.set_property("label", "<i>bar</i>")
7.8. How can I change the appearance of a label without using pango markup?
here is a little example:
import gtk
import pango
w = gtk.Window()
w.connect("destroy", lambda w: gtk.main_quit())
l = gtk.Label("some VERY_BOLD ITALIC text")
k = gtk.Label("some normal text")
PLIST = pango.AttrList()
BOLD = pango.AttrWeight(pango.WEIGHT_HEAVY, 0, -1)
ITALIC = pango.AttrStyle(pango.STYLE_ITALIC, 0, -1)
PLIST.insert(BOLD)
PLIST.insert(ITALIC)
l.set_property("attributes", PLIST)
v = gtk.VBox()
v.pack_start(l)
v.pack_start(k)
w.add(v)
w.show_all()
gtk.main()
You first create a pango.AttrList filled by all the attributes you want to change, then you apply it on the "attributes" property.
8. Images: GtkImage, GtkPixmap, GdkPixbuf
8.1. How do I load an image from a filename into my application UI?
w = gtk.Window()
w.connect("destroy", gtk.main_quit)
image = gtk.Image()
image.set_from_file("logo.xpm")
w.add(image)
w.show_all()
gtk.main()
If you want to change the current image of a GtkPixmap use:
image.set_from_file("logo2.xpm")
8.2. What about loading other image formats besides XPM, like JPEG or PNG?
w = gtk.Window() image = gtk.Image() image.set_from_file(filename) w.add(image) w.show_all()In PyGTK-0 you need to use gdkpixbuf to load non-xpm image formats. gdkpixbuf is a separate module, and you use it create a GdkPixbuf, which can be converted into a GdkPixmap, which can be in turn converted to a GtkPixmap (with its mask if transparent). An example follows:
import gtk
import gdkpixbuf
w=gtk.GtkWindow()
img=gdkpixbuf.new_from_file("images/logo.gif")
gdkpix, mask = img.render_pixmap_and_mask() # Create a GdkPixmap object
gtkpix = gtk.GtkPixmap(gdkpix, mask)
w.add(gtkpix)
w.show_all()
gtk.mainloop()
Note that you can also use GdkPixbufs in PyGTK2. They are useful for manipulating images in-memory; for instance, for scaling and blitting imagedata (with an alpha channel). In that case, to load it into a GtkImage widget, you'd use something like:
pixbuf = gtk.gdk.pixbuf_new_from_file(imagefilename) image = gtk.Image() image.set_from_pixbuf(pixbuf)to get the same results.
8.3. How do I convert a Numeric array to a Pixbuf object?
Assuming that you have a (n,m,3) or (n,m,4) shape 'b' type array of RGB or RGBA values called 'data', you would do this:
w,h = data.shape[:2] hasalpha = data.shape[3] == 4 p = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, hasalpha, 8, w, h) p.pixel_array[:] = data # see belowSpecial note: the pixel_array attribute of the Pixbuf is read-only in the sense that you can't do 'p.pixel_array = data'. But it's not immutable, so you can still change it's contents, which is what the [:] slice assignment above does.
Note however that modifying the pixel data of some GdkPixbufs will cause a segfault (ones that are backed by a const string, such as the stock icons). Pixbufs you create yourself are safe to modify.
(There was a bug which could cause crashes; see [bugzilla.gnome.org] for details -- it was fixed in CVS HEAD in Aug 2003)
(Tim Evans)
8.4. Is there a resource leak? Why do I run out of memory using Pixbuf?
For example, I had some code that looked like this:
for image_path in images:
pb = gtk.gdk.pixbuf_new_from_file(image_path)
pb = pb.scale_simple(thumb_width, thumb_height, gtk.gdk.INTERP_BILINEAR)
thumb_list_model.set_value(thumb_list_model.append(None), 0, pb)
This chewed up an unacceptably large amount of memory for any reasonable image set. Changing the code to look like this fixed the problem:
import gc
for image_path in images:
pb = gtk.gdk.pixbuf_new_from_file(image_path)
pb = pb.scale_simple(thumb_width, thumb_height, gtk.gdk.INTERP_BILINEAR)
thumb_list_model.set_value(thumb_list_model.append(None), 0, pb)
del pb
gc.collect()
8.5. How do I to display an image from data (using a drawable or Image widget)?
The first example uses any gdk.Drawable's draw_rgb_image() method:
# 0,0 are the coordinates for the top left corner; this # renders an image flush at this corner. drawable.draw_rgb_image(gc, 0, 0, width, height, gtk.gdk.RGB_DITHER_NONE, imagedata)Note that draw_rgb_image() has an optional rowstride argument. This argument is the length of *one row* of data in your buffer. See [www.pygtk.org] for more information.
(Ionutz Borcoman)
The next example creates a pixbuf from an Image using the gtk.gdk.pixbuf_new_from_data method. image can be any PIL Image object using RGB or RGBA mode.
image = Image.open('foo.png')
IS_RGBA = image.mode=='RGBA'
gtk.gdk.pixbuf_new_from_data(
image.tostring(), # data
gtk.gdk.COLORSPACE_RGB, # color mode
IS_RGBA, # has alpha
8, # bits
image.size[0], # width
image.size[1], # height
(IS_RGBA and 4 or 3) * image.size[0] # rowstride
)
Note that you need to specify rowstride for this method. Setting rowstride to 3 * width should work for an RGB image. Setting it to 4 * width should work for an RGBA image.
(Tom Hinkle)
The next example uses Numeric (which allows for further image manipulation), and will will work with RGB and RGBA images:
import Numeric, gtk data = Numeric.fromstring(imagedata, 'b') data.shape = (height, width, -1) p = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, i.mode == 'RGBA', 8, w, h) p.pixel_array[:] = data im = gtk.Image() im.set_from_pixbuf(p)(Tim Evans)
8.6. How do I resize a gtk.Image?
im = gtk.Image()
pixbuf = gtk.gdk.pixbuf_new_from_file("my.jpg")
scaled_buf = pixbuf.scale_simple(150,150,gtk.gdk.INTERP_BILINEAR)
im.set_from_pixbuf(scaled_buf)
im.show()
(Jeff Bowden)
8.7. What if I want to add a PIL image to a drawable?
import PIL.Image, Numeric, gtk
i = PIL.Image.open('foo.png')
w, h = i.size
imagestr = i.tostring()
im = gtk.Image()
pixmap = gtk.gdk.Pixmap(self.im.window, width, height, depth)
gc = self.im.style.fg_gc[gtk.STATE_NORMAL]
# 0,0 are the coordinates for the top left corner; this
# renders an image with no border.
pixmap.draw_rgb_image(gc, x, y, w, h, gtk.gdk.RGB_DITHER_NONE, buff)
im.set_from_pixmap(pixmap, None)
To convert back from a GTK+ image type to a PIL Image, see FAQ 8.14.
A simpler method using a StringIO object is described by Sebastian Wilhelmi, see [www.daa.com.au]
import StringIO
import PIL.Image
import gtk
def image_to_pixbuf(image):
fd = StringIO.StringIO()
image.save(fd, "ppm")
contents = fd.getvalue()
fd.close()
loader = gtk.gdk.PixbufLoader("pnm")
loader.write(contents, len(contents))
pixbuf = loader.get_pixbuf()
loader.close()
return pixbuf
image = PIL.Image.open("example.png")
pixbuf = image_to_pixbuf(image)
image = gtk.Image()
image.set_from_pixbuf(pixbuf)
8.8. Does somebody know what all these image/pixmap classes are?
- GdkPixbuf: a client-side object that holds an image. The pixbuf is merely a holder for image data, which allows you to manipulate it, but has no facilities for rendering (being a client-side object, this is quite obvious).
- GdkPixmap: a X server object that contains an image. Can not be rendered in itself, even though the image is stored on the server. Manipulating a GdkPixmap is slower than a pixbuf mainly because of the communication roundtrip with the server.
- GdkDrawable: any X server object you can draw to, i.e. a GdkWindow or a GdkPixmap. A reference of the Drawable API is at [www.pygtk.org]
- GtkImage: a GTK widget that renders an image based on a Pixmap or Pixbuf. The GtkImage differs from a regular Drawable in the sense that it implements an expose-event handler that takes care of redrawing its contents (based on its pixbuf or pixmap) when necessary. When using a Drawable (such as the DrawingArea) it is necessary to handle expose-events yourself.
8.9. How do I flip an image horizontally or vertically?
David Hugh-Jones submitted an [unoptimized] example function that flips a pixbuf:
def flip_pixbuf(pb):
bps = pb.get_bits_per_sample()
rs = pb.get_rowstride()
pix = pb.get_pixels()
newpix = ""
x = rs
pixstride = pb.get_n_channels() * bps/8
while x <= len(pix):
newrow = ""
y = pixstride
row = pix[x - rs: x]
while y <= len(row):
sample = row[y - pixstride: y]
newrow = sample + newrow
y += pixstride
newpix += newrow
x += rs
return gtk.gdk.pixbuf_new_from_data(newpix,
pb.get_colorspace(),
pb.get_has_alpha(),
bps,
pb.get_width(),
pb.get_height(),
rs)
In PyGTK-0, when GdkImlib was compiled in, it was a matter of using flip_image_horizonal() and flip_image_vertical().
8.10. Is it possible to use SVG icons and images in PyGTK?
w = gtk.Window()
pixbuf = gtk.gdk.pixbuf_new_from_file('my_imagefile.svg')
w.set_icon(pixbuf)
Apart from setting icons, you can use all functionality available to GdkPixbufs.
(Dennis Craven)
You can also do:
img = gtk.Image()
img.set_from_file('my_imagefile.svg')
8.11. How do I get a Pixbuf of a stock icon?
pixbuf = dialog.render_icon(gtk.STOCK_FIND, gtk.ICON_SIZE_MENU)
dialog.set_icon(pixbuf)
(Doug Quale)
8.12. How do I register stock icons from an image file?
factory = gtk.IconFactory()
pixbuf = gtk.gdk.pixbuf_new_from_file(filename)
iconset = gtk.IconSet(pixbuf)
factory.add('my-image', iconset)
factory.add_default()
David M. Cook provides us with a way of registering more than one icon at a time and load from a file those that are found not to be stock icons, which is useful to many applications:
def register_iconsets(icon_info):
iconfactory = gtk.IconFactory()
stock_ids = gtk.stock_list_ids()
for stock_id, file in icon_info:
# only load image files when our stock_id is not present
if stock_id not in stock_ids:
pixbuf = gtk.gdk.pixbuf_new_from_file(file)
iconset = gtk.IconSet(pixbuf)
iconfactory.add(stock_id, iconset)
iconfactory.add_default()
register_iconsets([('gnome-stock-mic', 'gnome-stock-mic.png'),
('gnome-stock-midi', 'stock_midi.png')])
8.13. How can I use an image as background in a gtk.Window?
iconsdir = './icons' imagename = 'image.png' win = gtk.Window() path = os.path.join(iconsdir, imagename) pixbuf = gtk.gdk.pixbuf_new_from_file(path) pixmap, mask = pixbuf.render_pixmap_and_mask() width, height = pixmap.get_size() del pixbuf win.resize(width, height) win.shape_combine_mask(mask, 0, 0) # make it transparent, not necessary win.window.set_back_pixmap(pixmap, gtk.FALSE) del pixmap win.invalidate_rect( rect, False )
8.14. How do I convert a pixbuf to a PIL Image?
import gtk
import Image
def pixbuf2Image(pb):
assert(pb.get_colorspace() == gtk.gdk.COLORSPACE_RGB)
dimensions = pb.get_width(), pb.get_height()
stride = pb.get_rowstride()
pixels = pb.get_pixels()
mode = pb.get_has_alpha() and "RGBA" or "RGB"
return Image.frombuffer(mode, dimensions, pixels,
"raw", mode, stride, 1)
pb = gtk.gdk.pixbuf_new_from_file("foo.jpg")
im = pixbuf2Image(pb)
im.save("welldone.jpg", "JPEG", quality=80)
(Johan Dahlin, Danny M)
8.15. How can I get the data of a gtk.Image and save it in an external file?
pixbuf = img.get_pixbuf()
pixbuf.save(filename, "jpeg", {"quality":"100"})
where img is a gtk.Image() of course
8.16. How to show data that I already own from outside, in a gtk.Image?
Some example code:
import urlib
f = urllib.urlopen(url_to_image)
data = f.read()
pbl = gtk.gdk.PixbufLoader()
pbl.write(data)
pbuf = pbl.get_pixbuf()
pbl.close()
img.set_from_pixbuf(pbuf)
where img is an instance of gtk.Image
8.17. How to make a colorful image grayscale without using PIL?
import gtk
pixbuf = gtk.gdk.pixbuf_new_from_file('image.png')
pixbuf2 = pixbuf.copy()
pixbuf.saturate_and_pixelate(pixbuf2, 0.0, False)
pixbuf2.save('image_grayscale.png', 'png')
thanks to federico
8.18. How blend (composite) two images together?
Obligatory example:
pixbuf = gtk.gdk.pixbuf_new_from_file("foo.png")
pixbuf2 = gtk.gdk.pixbuf_new_from_file("bar.png")
pixbuf.composite(pixbuf2, 0, 0, pixbuf.props.width, pixbuf.props.height, 0, 0, 1.0, 1.0, gtk.gdk.INTERP_HYPER, 127)
## now pixbuf2 contains the result of the compositing operation
pixbuf2.save("zbr.png", 'png')
Beware that the destination image has to be at least as large as the first image. Otherwise you might get a cryptic warning like:
python foo.py foo.py:7: GtkWarning?: gdk_pixbuf_composite: assertion `dest_x >= 0 && dest_x + dest_width <= dest->width' failedYou can also do this using just cairo: (PyGTK 2.8+)
import cairo
s1 = cairo.ImageSurface.create_from_png('foo.png')
s2 = cairo.ImageSurface.create_from_png('bar.png')
ctx = cairo.Context(s1)
ctx.set_source_surface(s2, 0, 0)
ctx.paint()
s1.write_to_png('result.png')
8.19. How can I make a stock icon the default icon?
window = gtk.Window() icon = window.render_icon(gtk.STOCK_FIND, gtk.ICON_SIZE_DIALOG) gtk.window_set_default_icon(icon)[1] [www.pygtk.org]
8.20. How do I draw a text [or something else] on a gtk.gdk.pixbuf?
#create a pixmap with the data of the pixbuf
pixmap,_ = pixbuf.render_pixmap_and_mask()
gc = pixmap.new_gc()
p = widget.create_pango_layout('text')
p.set_font_description(pango.fontdescription('Sans 12'))
pixmap.draw_layout(gc, x, y, p)
#draw whatever you want in the pixmap
pixbuf.get_from_drawable(pixmap, pixmap.get_colormap(), 0, 0, 0, 0, -1, -1)
8.21. How can I use an image as background in a widget?
import gtk
IMG = 'image.png'
pixbuf = gtk.gdk.pixbuf_new_from_file(IMG)
def expose(widget, ev):
widget.window.draw_pixbuf(widget.style.bg_gc[gtk.STATE_NORMAL], pixbuf, 0, 0, 0, 0)
if widget.get_child() != None:
widget.propagate_expose(widget.get_child(), ev)
return True
win = gtk.Window()
win.set_size_request(768, 32) # adjust to your image dimensions
win.connect("delete-event", gtk.main_quit)
evbox = gtk.EventBox()
evbox.connect('expose_event', expose)
hbox = gtk.HBox(False, 10)
l1 = gtk.Label("tururu 1")
hbox.pack_start(l1, True, True, 0)
l2 = gtk.Label("tururu 2")
hbox.pack_start(l2, True, True, 0)
l3 = gtk.Label("tururu 3")
hbox.pack_start(l3, True, True, 0)
evbox.add(hbox)
win.add(evbox)
win.show_all()
gtk.main()
