Using Glade 3.12 widgets in python - python

Just as some history, I have been using python for about 5 years now and have finally decided to make my first gui app in Glade.
I started with something basic, I have a button, a Gtkentry and gtktextview
This is what I am trying to accomplish:
on button press, take from the text from gtk.entry and have it appended to the gtk.textview
now the main problem I have is that I can not find descent documentation for how to use the widgets, and the examples I find on the Internet reference both a builder variation as well as another variation of glade project which I can only assume has been discontinued. I would like to learn how builder fits into the python / glade collaboration.
my code so far:
import gtk
import pygtk
def onDeleteWindow(self, *args):
Gtk.main_quit(*args)
def hello(button):
text_buffer.set_text(txtinput.get_text())
builder = gtk.Builder()
builder.add_from_file("dagui.glade")
handlers = {
"onDeleteWindow": gtk.main_quit,
"buttondown": hello
}
builder.connect_signals(handlers)
textarea = builder.get_object("textview1")
window = builder.get_object("window1")
txtinput = builder.get_object("entry1")
window.show_all()
gtk.main()
window.show_all()
gtk.main()
now this all works and pressing the button will print what ever is in the gtk.entry but I can not find how to append it to the textview. I also am not sure what to search for to find documentation, I tried "gtk builder gtk.textview" and pygtk build gtk.textview append" and all other variations.
Though knowing how to simply add the text to the text view would be great, having a link to somewhere where I can get in plain english how to use these widgets I would be forever great-full.

Frob the gtk.TextView, you need to get the gtk.TextBuffer by using the textview's buffer property.
From the textbuffer, you need to get the iterator that points to the end of the buffer with the get_end_iter method. With that iterator, and your text, you can use the textbuffer's insert method.
Edit: Since I don't have the dagui.glade file, I couldn't test it, but see the following code:
def hello(button):
global textarea, txtinput
buffer = textarea.get_property('buffer')
i = buffer.get_end_iter()
buffer.insert(i, txtinput.get_text())
# clear the input window after appending the text
txtinput.set_text('')

I figured it out, I have found out the the gtk.textview.get_buffer actually sets the buffer ID and then the textview.set_text(buffer) isall I needed.
here is the full working code, the glade is just a button, an entry and a textview:
#!/usr/bin/python
import os
import sys
import gtk
import pygtk
def onDeleteWindow(self, *args):
Gtk.main_quit(*args)
def hello(button):
textbuffer = textarea.get_buffer()
textbuffer.set_text(txtinput.get_text())
builder = gtk.Builder()
builder.add_from_file("dagui.glade")
handlers = {
"onDeleteWindow": gtk.main_quit,
"buttondown": hello
}
builder.connect_signals(handlers)
textarea = builder.get_object("textview1")
window = builder.get_object("window1")
txtinput = builder.get_object("entry1")
window.show_all()
gtk.main()

Use this to add text :
textarea.set_text('whatever you want')
and this for adding pango markup ( http://goo.gl/94Pkk ) :
textarea.set_markup('<span size="large>Example</span>')
Here's the documentation : http://python-gtk-3-tutorial.readthedocs.org/en/latest/index.html

Related

Standalone Gtk.Menu popup not working without event.time

I'm trying to port a program I made with pygtk, it's a popup menu launched via global shortcut (using keybinder) to run specific programs and commands. There is no main window in this program, the point is have a simple, fast and light "launcher" available anywhere, whenever I need it.
The old menu.popup used to work even when using 0 as event.time (since keybinder doesn't give an event I'd request a time for), but now I'm getting this error:
Warning: The property GtkStatusIcon:stock is deprecated and shouldn't be used anymore. It will be removed in a future version.
self.icon.new_from_stock(Gtk.STOCK_OPEN)
This is an example I made up to show the problem:
from gi.repository import Gtk, Gdk
from gi.repository import Keybinder
menu_shortcut = "<Super>m"
class TestMenu:
def __init__(self):
self.menu = Gtk.Menu()
item = Gtk.MenuItem('various items')
self.menu.add(item)
item = Gtk.MenuItem('Quit')
item.connect('activate', Gtk.main_quit)
self.menu.append(item)
self.menu.show_all()
self.icon = Gtk.StatusIcon()
self.icon.new_from_stock(Gtk.STOCK_OPEN)
self.icon.set_tooltip_text('MyMenu')
self.icon.connect('popup-menu', self.popup, self.menu)
Keybinder.init()
Keybinder.bind(menu_shortcut, self.popup, 0, 0, self)
def popup(self, widget, button, time, menu):
self.menu.popup(None, None, None, None, button, time)
menu = TestMenu()
Gtk.main()
With this example I'm able to click the status icon and get the menu, but the keyboard shortcut just gives me the aforementioned error.
Note: the stock icon doesn't work, I'm still learning the new API.

Pygtk WebKit get source html

Here is my sample code. How do I get the html source code of the current page. It only prints 'GString at 0x8875130' . How to convert it to real text contains html?
from gi.repository import WebKit
from gi.repository import Gtk, Gdk
def get_source(webobj, frame):
print "loading..."
x = web.get_main_frame().get_data_source().get_data()
print x
win = Gtk.Window()
web = WebKit.WebView()
web.open("http://google.com")
web.connect("load-finished", get_source)
win.add(web)
win.show_all()
Gtk.main()
print x.str
Data is available as .str member of GLib.String object. For further details try help(GLib.String) on python prompt after importing libraries.
#Before you can use the require_version() method from gi, you need to import the gi module.
import gi
#Specify versions to import from the repository.
gi.require_version('Gtk','3.0')
gi.require_version('WebKit','3.0')
#Import the modules that will give us a Graphical User Interface (GUI) and a WebKit Browser.
from gi.repository import Gtk,WebKit
#Define your function to handle the WebKit's "load-finished" event. The webobj is a reference to the WebKit that triggered the event. The frame is which frame triggered the event (useful if the loaded page has multiple frames like a frameset.
def ShowSource(webobj,frame):
#What you have printed is what results from this line. This line returns a reference to an object, so when you print it's return value, a description is all Python knows to print.
SourceCodeStringObject=frame.get_data_source().get_data()
#You can get the text the object is carrying from it's "str" member property like I do below.
SourceCodeStringText=SourceCodeStringObject.str
#Send the source code string text to the output stream.
print(SourceCodeStringText)
#Create Window object.
Window=Gtk.Window()
#Set the text to display in the window's caption.
Window.set_title("Test of Python GTK and WebKit")
#Set the starting window size in pixels.
Window.set_default_size(480,320)
#Create the WebView object.
WebBrowser=WebKit.WebView()
#Tell the WebView object to load a website.
WebBrowser.open("https://stackoverflow.com/questions/24119290/pygtk-webkit-get-source-html")
#Set the event handler for the WebView's "load-finished" event to the function we have above.
WebBrowser.connect("load-finished",ShowSource)
#Add the WebView to the window.
Window.add(WebBrowser)
#Set the handler of the window closing to cause GTK to exit. Without this, GTK will hang when it quits, because it's main loop that we start later will still be running. Gtk.main_quit will stop the main loop for GTK.
Window.connect("delete-event",Gtk.main_quit)
#Display the window.
Window.show_all()
#Start GTK's main loop.
Gtk.main()
This way works for me.
#!/usr/bin/env python
import webkit, gtk
def get_source(webobj, frame):
print "loading..."
x = web.get_main_frame().get_data_source().get_data()
print x
win = gtk.Window()
win.set_position(gtk.WIN_POS_CENTER_ALWAYS)
win.resize(1024,768)
win.connect('destroy', lambda w: gtk.main_quit())
win.set_title('Titulo')
vbox = gtk.VBox(spacing=5)
vbox.set_border_width(5)
web = webkit.WebView()
vbox.pack_start(web, fill=True, expand=True)
web = webkit.WebView()
web.open("http://www.google.co.ve")
web.connect("load-finished", get_source)
browser_settings = web.get_settings()
browser_settings.set_property('user-agent', 'Mozilla/5.0 (X11; Linux i586; rv:31.0) Gecko/20100101 Firefox/31.0')
browser_settings.set_property('enable-default-context-menu', True)
browser_settings.set_property('enable-accelerated-compositing', True)
browser_settings.set_property('enable-file-access-from-file-uris', True)
web.set_settings(browser_settings)
win.add(web)
win.show_all()
gtk.main()

How to get the text of a widget/window using python-xlib?

I'm trying to find the whole text that is currently being edited in gedit window. Firstly i tried to find out the current gedit tab that is focused, by using Xlib.display. Now i got an Xlib.display.window object . Now i want to find out the text that is in that particular window/widget using this window object
And my code is like this
import gtk, gobject, Xlib.display
currentFocus=''
def current_focused:
global currentFocus
display = Xlib.display.Display()
window = display.get_input_focus().focus
wmname = window.get_wm_name()
wmclass = window.get_wm_class()
if wmclass is None and wmname is None:
window = window.query_tree().parent
wmname = window.get_wm_name()
if currentFocused!=wmname:
if window.get_wm_class()[0]=='gedit':
print "\nNow you are in : < %s >" % (wmname,)
# Here i have to find the text of the gedit's widget
currentFocused=wmname
return True
gobject.timeout_add(1000, current_focused)
gtk.main()
is there any API to get the text of a specific widget using Xlib.display.window
Please help me. I'm completely new in this area
Thank you
WM_CLASS / WM_NAME properties are only used to provide information to a window manager ( hence WM prefix ) and not usually set on child windows. Check GTK source code if edit widget sets similar properties, but in general it is not possible for external process to read edit control text

Set widget properties using GTKBuilder and Python

I am new with GTKBuilder. I have included a GTKBuilder file in my Python script. I want to change a property of a widget.
For example, if someone clicks on "More Information", on_more_information function gets triggered. I want to change the Label of Label lblConnectionStatus on the trigger.
import gtk
class RoyalBengalWiMAX:
def __init__(self):
filename = "gui.xml"
builder = gtk.Builder()
builder.add_from_file(filename)
builder.connect_signals(self)
def on_window1_destroy(self, widget, data=None):
gtk.main_quit()
def on_information_click(self, widget, data=None):
app = RoyalBengalWiMAX()
gtk.main()
How can I achieve that? (I couldn't include the GTKBuilder XML, stackoverflow says it's too large)
Do you mean somethink along the lines of Label.set_text("new text")? If so, you probably first have to get the widget from the file using gtk.Builder.get_object("objectname").

How do I render *parts* of a svg file?

I want to render parts of a svg file by name but for the life of me I cannot figure out how to do so (using python + gtk).
Here's the svg file in question: http://david.bellot.free.fr/svg-cards/files/SVG-cards-2.0.1.tar.gz (Update: this file no longer exists, but you can track it down at http://svg-cards.sourceforge.net/)
On his site, David, says:
You can draw a card either by
rendering the file onto a pixmap and
clipping each card manually or by
using the card's name through a DOM
interface. All cards are embedded into
a SVG group.
I don't know what he means by a DOM interface. I have done some searching and the best result I found that seems to fit what I want to do is:
QSvgRenderer *renderer = new QSvgRenderer(QLatin1String("SvgCardDeck.svg"));
QGraphicsSvgItem *black = new QGraphicsSvgItem();
QGraphicsSvgItem *red = new QGraphicsSvgItem();
black->setSharedRenderer(renderer);
black->setElementId(QLatin1String("black_joker"));
red->setSharedRenderer(renderer);
red->setElementId(QLatin1String("red_joker"));
Notice however that it is for Qt and is not even written in python.
This is what I have so far:
#!/usr/bin/env python
from __future__ import absolute_import
import cairo
import gtk
import rsvg
from xml import xpath
from xml.dom import minidom
window = gtk.Window()
window.set_title("Foo")
window.set_size_request(256, 256)
window.set_property("resizable", False)
window.set_position(gtk.WIN_POS_CENTER)
window.connect("destroy", gtk.main_quit)
window.show()
document = minidom.parse("cards.svg")
element = xpath.Evaluate("//*[#id='1_club']", document)[0]
xml = element.toxml()
svg = rsvg.Handle()
svg.write(xml)
pixbuf = svg.get_pixbuf()
image = gtk.Image()
image.set_from_pixbuf(pixbuf)
image.show()
window.add(image)
gtk.main()
It doesn't work, of course.
What am I missing?
The GTK library for rendering SVG is called RSVG. It has python bindings, but they are undocumented, and they don't wrap the rsvg_handle_get_pixbuf_sub() and rsvg_handle_render_cairo_sub() functions which you would normally use for that purpose in C. Here's what you have to do as far as I can tell. You extract the XML node as Adam Crossland suggested. To render it, you have to do something like this:
import gtk
import rsvg
handle = rsvg.Handle()
handle.write(buffer=xml_data)
# xml_data is the XML string for the object you want
image = gtk.Image()
image.set_from_pixbuf(handle.get_pixbuf())
That's if you want it in a gtk.Image, otherwise do something else with the pixbuf. You can also render it to a Cairo context with handle.render_cairo(cr) where cr is your Cairo context.
EDIT:
Sorry, I didn't read the python bindings closely enough at first. The _sub() functions are implemented using the id= argument, so your program can boil down to this:
#!/usr/bin/env python
import gtk
import rsvg
window = gtk.Window()
window.set_title("Foo")
window.connect("destroy", gtk.main_quit)
window.show()
svg = rsvg.Handle(file='cards.svg')
pixbuf = svg.get_pixbuf(id='#3_diamond')
image = gtk.Image()
image.set_from_pixbuf(pixbuf)
image.show()
window.add(image)
gtk.main()
I tested this and it works. However, the window is the size of the entire SVG canvas, and is clipped to the screen size (which is why I rendered the 3 of diamonds instead of the ace of clubs which is up in the corner.) So you'll still have to find some way to crop the pixbuf around the card that you want, but that shouldn't be too hard.
Here's my answer to the cropping blank space problem. It's a rough hack but it worked great. This would also serve as a good starting point to get cards for anyone making a card game in python.
import gtk
import rsvg
svg = rsvg.Handle(file="/usr/share/gnome-games-common/cards/gnomangelo_bitmap.svg")
w, h = 202.5, 315
card_names = map(str, range(1,11)) + ["jack", "queen", "king"]
suites = ["club", "diamond", "heart", "spade"]
specials = [{"name":"black_joker","x":0, "y":4}, {"name":"red_joker","x":1, "y":4}, {"name":"back","x":2, "y":4}]
for suite_number, suite in enumerate(suites):
for card_number, card in enumerate(card_names):
print "processing", suite, card, '#'+card+'_'+suite
pixbuf = svg.get_pixbuf(id='#'+card+'_'+suite)
pixbuf.subpixbuf(int(w*card_number), int(h*suite_number), int(w), int(h)).save("./"+card+"_"+suite+".png","png", {})
for special in specials:
print "processing", special["name"]
pixbuf = svg.get_pixbuf(id='#'+special["name"])
card_number = special["x"]
suite_number = special["y"]
pixbuf.subpixbuf(int(w*card_number), int(h*suite_number), int(w), int(h)).save("./"+special["name"]+".png","png", {})
Grave-digging a little bit here, but the answer by ptomato from 2010 also works now in 2019 for Gtk3 with some slight modifications. The below code will render only the 3 of diamonds svg id.
#!/usr/bin/env python
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Rsvg', '2.0')
from gi.repository import Gtk, Rsvg
svg = Rsvg.Handle.new_from_file('svg-cards.svg')
pixbuf = svg.get_pixbuf_sub('#3_diamond')
image = Gtk.Image()
image.set_from_pixbuf(pixbuf)
image.show()
window = Gtk.Window()
window.set_title("Foo")
window.connect("destroy", Gtk.main_quit)
window.show()
window.add(image)
Gtk.main()
I believe that what he means by 'through a DOM interface' is that since SVG is XML, you could load the SVG file in minidom, or some other Python XML parser, and extract the XML node with the specific name that you are looking for. That XML node should represent an item that can be rendered.
You can do it by editing the tag. Edit width and height, set the viewBox attribute on the main svg element to the rectangle you want, render, repeat.
See How to show a subsection or "slice" of an SVG graphic? and http://dingoskidneys.com/~dholth/svg/

Categories

Resources