Consider this Python program which uses PyGtk and Hippo Canvas to display a clickable text label. Clicking the text label replaces it with a Hippo CanvasEntry widget which contains the text of the label.
import pygtk
pygtk.require('2.0')
import gtk, hippo
def textClicked(text, event, row):
input = hippo.CanvasEntry()
input.set_property('text', text.get_property('text'))
parent = text.get_parent()
parent.insert_after(input, text)
parent.remove(text)
def main():
canvas = hippo.Canvas()
root = hippo.CanvasBox()
canvas.set_root(root)
text = hippo.CanvasText(text=u'Some text')
text.connect('button-press-event', textClicked, text)
root.append(text)
window = gtk.Window()
window.connect('destroy', lambda ignored: gtk.main_quit())
window.add(canvas)
canvas.show()
window.show()
gtk.main()
if __name__ == '__main__':
main()
How can the CanvasEntry created when the text label is clicked be automatically focused at creation time?
Underneath the CanvasEntry, there's a regular old gtk.Entry which you need to request the focus as soon as it's made visible. Here's a modified version of your textClicked function which does just that:
def textClicked(text, event, row):
input = hippo.CanvasEntry()
input.set_property('text', text.get_property('text'))
entry = input.get_property("widget")
def grabit(widget):
entry.grab_focus()
entry.connect("realize", grabit)
parent = text.get_parent()
parent.insert_after(input, text)
parent.remove(text)
Related
I'm trying to change the highlight color for a gtk.EventBox. It has a certain background color, and I want to draw a line around it with its complementary color. I have found drag_highlight, which draws a line around the widget, but I have not figured out how to change the color: it's always black. Any ideas?
To make the line around the EventBox, it is possible to put it into the Frame or another EventBox (in this case it is possible to set the width of the "border"), here is how it looks:
And here is the code (it is a modified EventBox example):
#!/usr/bin/env python
# example eventbox.py
import pygtk
pygtk.require('2.0')
import gtk
class EventBoxExample:
def __init__(self):
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_title("Event Box")
window.connect("destroy", lambda w: gtk.main_quit())
window.set_border_width(10)
# Create an EventBox and add it to our toplevel window
frame = gtk.EventBox() # gtk.Frame()
window.add(frame)
frame.show()
frame.set_border_width(2)
frame.modify_bg(gtk.STATE_NORMAL,
frame.get_colormap().alloc_color("blue"))
event_box = gtk.EventBox()
frame.add(event_box)
event_box.set_border_width(10)
event_box.show()
# Create a long label
label = gtk.Label("Click here to quit, quit, quit, quit, quit")
event_box.add(label)
label.show()
# Clip it short.
label.set_size_request(110, 20)
# And bind an action to it
event_box.set_events(gtk.gdk.BUTTON_PRESS_MASK)
event_box.connect("button_press_event", lambda w,e: gtk.main_quit())
# More things you need an X window for ...
event_box.realize()
event_box.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND1))
# Set background color to green
event_box.modify_bg(gtk.STATE_NORMAL,
event_box.get_colormap().alloc_color("green"))
window.show()
def main():
gtk.main()
return 0
if __name__ == "__main__":
EventBoxExample()
main()
I've used Wnck to check whether a window has been created like this:
screen = Wnck.Screen.get_default()
screen.force_update() # recommended per Wnck documentation
window_list = screen.get_windows()
for window in window_list:
print(window.get_name())
if window.has_name():
if window.get_name() == self.xld_main_window.get_title():
window_found = True
break
assert window_found, 'The Gtk.Window named {window_name} has not been found.'\
.format(window_name=self.xld_main_window.get_title())
# clean up Wnck (saves resources, check documentation)
window = None
screen = None
However, since dialogs don't show up in the list of tasks, I can't find them that way. What is an appropriate way of checking whether they're displayed (and modal / not modal)?
The Wnck.Screen.get_windows method returns all windows including dialogs. There is no distinction as the function returns any Wnck.Window that is currently mapped. The source goes like this:
* The #WnckScreen represents a physical screen. A screen may consist of
* multiple monitors which are merged to form a large screen area. The
* #WnckScreen is at the bottom of the libwnck stack of objects: #WnckWorkspace
* objects exist a #WnckScreen and #WnckWindow objects are displayed on a
* #WnckWorkspace.
*
* The #WnckScreen corresponds to the notion of
* <classname>GdkScreen</classname> in GDK.
GList*
wnck_screen_get_windows (WnckScreen *screen)
{
g_return_val_if_fail (WNCK_IS_SCREEN (screen), NULL);
return screen->priv->mapped_windows;
}
where screen->priv points to a struct containing some lists of the windows (mapped, stacked), a pointer to the active window, etc. Some WnckWindow can have WNCK_WINDOW_DIALOG set and be a dialog.
The WnckWindow class also provides a function transient_is_most_recently_activated() to know if the focus should go to a transient child window when selected in a WnckTaskList or to minimize the transient window with its parent. For example, to know wether My Application window has a most recently activated transient:
screen = Wnck.Screen.get_default()
screen.force_update() # recommended per Wnck documentation
window_list = screen.get_windows()
for window in window_list:
if window.get_name() == 'My Application':
print(window.transient_is_most_recently_activated())
The script below catches the dialogs as other mapped windows (no matter if they are modal/non-modal or the application they are from).
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Wnck', '3.0')
from gi.repository import Gtk, Wnck
class DialogExample(Gtk.Dialog):
def __init__(self, parent):
Gtk.Dialog.__init__(self, "My Dialog", parent, 0, #or Gtk.DialogFlags.MODAL
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
Gtk.STOCK_OK, Gtk.ResponseType.OK))
self.set_default_size(100, 100)
label = Gtk.Label("This is a dialog to display additional information")
box = self.get_content_area()
box.add(label)
self.show_all()
class DialogWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Dialog Example")
self.set_border_width(6)
button = Gtk.Button("Open dialog")
button.connect("clicked", self.on_button_clicked)
self.add(button)
def on_button_clicked(self, widget):
dialog = DialogExample(self)
response = dialog.run()
if response == Gtk.ResponseType.OK:
print("The OK button was clicked")
elif response == Gtk.ResponseType.CANCEL:
print("The Cancel button was clicked")
screen = Wnck.Screen.get_default()
screen.force_update() # recommended per Wnck documentation
window_list = screen.get_windows()
for window in window_list:
print(window.get_name())
window, window_list = (None,)*2
screen = None
dialog.destroy()
win = DialogWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
window = None
screen = None
Gtk.main()
Using Gdk instead of Wnck, you are doing the same thing at a slightly lower level.
Taking partially from this answer by Eye of Hell that says how to get the open windows, you can do this:
from gtk import gdk
name = "MyDialog"
root = gdk.get_default_root_window()
matches = []
for id in root.property_get("_NET_CLIENT_LIST"):
window = gdk.window_foreign_new(id)
if window and window.property_get("WM_NAME")[2] == name:
matches.append(window)
for match in matches:
print(match, match.get_modal_hint())
I'd like to keep focus on the entry text widget, which will pass whatever's entered into a separate display text widget. I have that part working.
I can't figure out how to make it so that when someone clicks on the display text widget the line clicked is highlighted (or the line changes background color) but focus is returned to the entry widget. I also need to store a reference to that line so that i can manipulate it with other Widgets.
Here's some sample code so you can see how I have it so far. I have a lot more widgets and code in GUI right now but I only posted the relevant code to my issue:
from Tkinter import *
class GUI:
def __init__(self,root):
Window = Frame(root)
self.OutWidget = Text(Window, state='disabled')
self.InWidget = Text(Window,bg='black',bd=3,fg='white',exportselection=0,height=1,wrap=WORD,insertofftime=0,insertbackground="white")
self.OutWidget.pack()
self.InWidget.pack()
Window.pack()
self.InWidget.focus_set()
self.OutWidget.bind("<Button 1>",self.Select)
self.InWidget.bind("<Return>", self.Post)
def Post(self,event):
text = self.InWidget.get(1.0,2.0)
self.InWidget.delete(1.0,2.0)
self.OutWidget['state'] = ['normal']
self.OutWidget.insert('end',text)
self.OutWidget['state'] = ['disabled']
return ("break")
def Select(self,event):
#highlight the CURRENT line
#store a reference to the line
#return focus to InWidget
self.InWidget.focus()
return ("break")
if __name__ == '__main__':
root = Tk()
App = GUI(root)
root.mainloop()
You can get the index of the start of the line where you clicked by using something like this:
line_start = self.OutWidget.index("#%s,%s linestart" % (event.x, event.y))
You can add highlighting by applying a tag to that line with something like this:
line_end = self.OutWidget.index("%s lineend" % line_start)
self.OutWidget.tag_remove("highlight", 1.0, "end")
self.OutWidget.tag_add("highlight", line_start, line_end)
You can set the color for the item with the "highlight" tag with something like this:
self.OutWidget.tag_configure("highlight", background="bisque")
You can move the focus back to the other window with something like this:
self.InWidget.focus_set()
How could I have a scrollbar inside a gtk.Layout.
For example, in my code I have:
import pygtk
pygtk.require('2.0')
import gtk
class ScrolledWindowExample:
def __init__(self):
self.window = gtk.Dialog()
self.window.connect("destroy", self.destroy)
self.window.set_size_request(300, 300)
self.scrolled_window = gtk.ScrolledWindow()
self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.window.vbox.pack_start(self.scrolled_window, True, True, 0)
self.layout = gtk.Layout()
self.scrolled_window.add(self.layout)
self.current_pos = 0
self.add_buttom()
self.window.show_all()
def add_buttom(self, widget = None):
title = str(self.current_pos)
button = gtk.ToggleButton(title)
button.connect_object("clicked", self.add_buttom, None)
self.layout.put(button, self.current_pos, self.current_pos)
button.show()
self.current_pos += 20
def destroy(self, widget):
gtk.main_quit()
if __name__ == "__main__":
ScrolledWindowExample()
gtk.main()
What I really want is to find some way to make the scroll dynamic. See the example that I put above, when you click any button, another button will be added. But the scrollbar doesn't work.
What can I do to get the scroll bars working?
Does it works if you either use gtk.Window() instead of gtk.Dialog(); or execute self.window.run() after self.window.show_all()?
The difference between Dialog and common Window is that Dialog has its own loop which processes events. As you do not run its run() command, this loop never gets the chance to catch the events, so ScrolledWindow does not receives them, and does not change its size.
I create a combo box using PyGTK:
fileAttrCombo = gtk.ComboBox();
I want to attach a signal handler for this combo box. This signal handler handles when user change selection in the combo box.
What is be the best approach to do this ?
The combobox has a "changed" signal.
This is a nice minimal example of using it.
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk
class ComboBoxExample:
def __init__(self):
window = gtk.Window()
window.connect('destroy', lambda w: gtk.main_quit())
combobox = gtk.combo_box_new_text()
window.add(combobox)
combobox.append_text('Select a pie:')
combobox.append_text('Apple')
combobox.append_text('Cherry')
combobox.append_text('Blueberry')
combobox.append_text('Grape')
combobox.append_text('Peach')
combobox.append_text('Raisin')
combobox.connect('changed', self.changed_cb)
combobox.set_active(0)
window.show_all()
return
def changed_cb(self, combobox):
model = combobox.get_model()
index = combobox.get_active()
if index:
print 'I like', model[index][0], 'pie'
return
def main():
gtk.main()
return
if __name__ == "__main__":
bcb = ComboBoxExample()
main()
try to replace "if index:" by "if index != None:" for getting the 1st value of combobox which has index equal to 0