Change the cursor to an hour glass using python in Gtk3 - python

Can somebody provide a code snippet that can be used under Gtk3 to change the cursor to a hour glass using python..?

The following Window implementation does that:
import time
from gi.repository import Gdk, Gtk, GObject
class MainWindow(Gtk.Window):
"""Example window."""
def __init__(self):
"""Create new instance."""
super(MainWindow, self).__init__()
self.set_title('Test Windows')
box = Gtk.VBox()
label = Gtk.Label("Just a label....")
box.pack_start(label, True, True, 0)
button = Gtk.Button(" and a button")
box.pack_start(button, True, True, 0)
self.add(box)
self.connect("destroy", Gtk.main_quit)
self.show_all()
def set_watch(self):
"""Set the mouse to be a watch."""
watch = Gdk.Cursor(Gdk.CursorType.WATCH)
gdk_window = self.get_root_window()
gdk_window.set_cursor(watch)
def long_call(self):
"""Perform a long call."""
time.sleep(10) # your time consuming operation here
arrow = Gdk.Cursor(Gdk.CursorType.ARROW)
gdk_window = self.get_root_window()
gdk_window.set_cursor(arrow)
window = MainWindow()
window.set_watch()
GObject.idle_add(window.long_call)
Gtk.main()
It is important that you do set the pointer to be a watch OUTSIDE the idel_add call otherwise it won't be set.

Related

Python3 Gtk new tab

I'm just playing with Gtk currently, but was wondering if someone has an example code of a window that has a notebook in it, and with a click of a button or event, it opens a new tab with a Gtk (for example) entry in it and is accessible from further code.
I can't find any working code like that on the web or on this website.
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
class MyWindow(Gtk.Window):
def __init__(self):
super().__init__(title="Simple Notebook Example")
self.set_border_width(3)
self.box = Gtk.VBox(spacing=6)
self.add(self.box)
self._add_tab_button = Gtk.Button(label="Add Tab")
self._add_tab_button.connect("clicked", self.add_tabs)
self.box.pack_start(self._add_tab_button, False, False, 5)
self.counter = 1
self.notebook = Gtk.Notebook()
self.box.pack_start(self.notebook, True, True, 5)
# add two tabs
self.add_tabs(None)
self.add_tabs(None)
def add_tabs(self, button):
page = Gtk.Box()
page.set_border_width(10)
page.add(Gtk.Label(label="Page %s content" % self.counter))
self.notebook.append_page(
page, Gtk.Label(label="Page %s" % self.counter))
page.show_all()
self.counter += 1
win = MyWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

Python Gtk Notebook making a new tab open from a button

I'm pretty new to OOP and gtk programming, so sorry if the answer my question is really obvious, but I can't find a solution. I am trying to make a browser-like interface using the Gtk notebook. I wrote a method to add tabs, and it seems to work, becasue when I call it in the init, it works, and adds a new tab. Here the method is:
def create_page(self, button):
print("creating a new page")
print(self)
self.newpage = Gtk.Box()
self.newpage.set_border_width(50)
self.newpage.add(Gtk.Label.new("add notes here"))
self.notebook.append_page(self.newpage, Gtk.Label.new("new page"))
The reason the method has to have the button parameter is becasue I want it to be called by a button, and for that to happen, it has to have a button parameter.
When the button calls the parameter, the print statment works, and it prints its self <main.MyWindow object at 0x7efd64e52a80 (main+MyWindow at 0xe60270)>. It prints the exact same output as when I call it from the init.The problem is that it never actually adds the new notebook tab for some reason. Here my full code is:
import gi
# Since a system can have multiple versions
# of GTK + installed, we want to make
# sure that we are importing GTK + 3.
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title ="Stickies Hub")
#self.set_border_width(70)
# Create Notebook
self.notebook = Gtk.Notebook.new()
self.add(self.notebook)
#create buttons
self.new_tab = Gtk.Button(label=("button"))
self.new_tab.connect("clicked", self.create_page)
# Create pages
self.page1 = Gtk.Box()
self.page1.set_border_width(50)
self.page1.add(Gtk.Label.new("Welcome to Geeks for Geeks"))
self.notebook.append_page(self.page1, Gtk.Label.new("Click Here"))
self.page2 = Gtk.Box()
self.page2.set_border_width(50)
self.page2.add(Gtk.Label.new("A computer science portal for geeks"))
self.page2.add(self.new_tab)
self.notebook.append_page(self.page2, Gtk.Label.new("Click Here"))
self.create_page(self.new_tab)
self.create_page(self.new_tab)
def create_page(self, button):
print("creating a new page")
print(self)
self.newpage = Gtk.Box()
self.newpage.set_border_width(50)
self.newpage.add(Gtk.Label.new("new page"))
self.notebook.append_page(self.newpage, Gtk.Label.new("new page"))
win = MyWindow()
win.connect("destroy", Gtk.main_quit)
# Display the window.
win.show_all()
# Start the GTK + processing loop
Gtk.main()
How can I add a new notebook tab from a button?
Thanks so much for help!
As jackw11111 said, the solution was to add self.show_all() at the end of create_page function. Thanks so much!
I made an answer so anyone with this same problem could easily find the answer.
Helloo, Here is my code. I think this will work for you.
from gi.repository import Gdk
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class MyWindow(Gtk.Window):
notebook = Gtk.Notebook()
def __init__(self):
Gtk.Window.__init__(self)
self.set_default_size(750, 500)
self.connect("destroy", Gtk.main_quit)
self.list_view()
def list_view(self):
self.table = Gtk.Table(n_rows=3, n_columns=3, homogeneous=True)
listbox = Gtk.ListBox()
self.add(self.table)
self.add(listbox)
self.two_d_array = {'Hello' : 'Hi', 'Example' : 'Merhaba'}
for i in self.two_d_array.keys():
## label yerine buton oluşturduk
items = Gtk.Button.new_with_label(i)
items.connect("button-press-event",self.button_clicked)
listbox.add(items)
self.table.attach(listbox,0,1,0,3)
self.add(self.notebook)
self.table.attach(self.notebook,1,3,0,3)
self.notebook.show_all()
self.page1 = Gtk.Box()
self.page1.set_border_width(10)
self.page1.add(Gtk.Label(label="Merhaba bu ilk sayfa."))
self.notebook.append_page(self.page1, Gtk.Label(label="Default Page"))
def context_menu(self):
menu = Gtk.Menu()
menu_item = Gtk.MenuItem("New Page")
menu.append(menu_item)
menu_item.connect("activate", self.on_click_popup)
menu.show_all()
return menu
## Buton sağ click ise context menu açtı
def button_clicked(self,listbox_widget,event):
if event.type == Gdk.EventType.BUTTON_PRESS and event.button == 3:
menu = self.context_menu()
## Tıklanan objenin labelini print ediyor
print(listbox_widget.get_label())
self.labelmenu = listbox_widget.get_label()
menu.popup( None, None, None,None, event.button, event.get_time())
return True
def on_pop_menu(self, widget, event):
if event.button == 3:
widget.popup(None, None, None, None, event.button, event.time)
def on_click_popup(self, action):
## Yeni sayfa oluştur
self.new_page = Gtk.Box()
self.new_page.set_border_width(10)
self.new_page.add(Gtk.Label(label=self.two_d_array[self.labelmenu]))
self.notebook.append_page(self.new_page, Gtk.Label(label="New Page"))
self.close_button = Gtk.Button()
self.close_button.set_image(Gtk.Image(Gtk.STOCK_CLOSE,Gtk.IconSize))
self.close_button.connect('clicked')
self.close_button.show()
self.notebook.show_all()
window = MyWindow()
window.show_all()
Gtk.main()

Why does deleting the widgets in a window and then creating them again yield strange error messages in PyGObject?

I have a window and I want a change to a value in one widget to change another widget; hence in the event handler for the widget, I "refresh" the window by deleting its widgets and creating them again. In my actual code, I have several widgets and this was my workaround to "update" them. Feel free to let me know if there is a better way to update other widgets if one of the values used to generate them changes.
In the below example, however, the widget seems to go blank and I get this message:
(test4.py:19274): Gtk-CRITICAL **: gtk_container_remove: assertion
'_gtk_widget_get_parent (widget) == GTK_WIDGET (container) ||
GTK_IS_ASSISTANT (container) || GTK_IS_ACTION_BAR (container) ||
GTK_IS_POPOVER_MENU (container)' failed
(test4.py:19274): Gtk-CRITICAL **: gtk_adjustment_get_value: assertion
'GTK_IS_ADJUSTMENT (adjustment)' failed
(test4.py:19274): Gtk-CRITICAL **: gtk_widget_has_focus: assertion
'GTK_IS_WIDGET (widget)' failed
(test4.py:19274): Gtk-CRITICAL **: gtk_widget_has_focus: assertion
'GTK_IS_WIDGET (widget)' failed
test4.py:69: Warning: g_object_ref: assertion 'G_IS_OBJECT (object)' failed
Gtk.main()
[...]
I have attached my code here:
import sys
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
# Documentation: https://graph-tool.skewed.de/static/doc/index.html
class SpecialBox(Gtk.Box):
def __init__(self, GUI):
Gtk.Box.__init__(self)
self.GUI = GUI
self.liststore = Gtk.ListStore(str, int, int)
self.liststore.append(["Apple", 0, 100])
self.liststore.append(["Pear", 0, 100])
self.liststore.append(["Orange", 0, 100])
treeview = Gtk.TreeView(model=self.liststore)
filter_name = Gtk.CellRendererText()
column_text = Gtk.TreeViewColumn("Fruit is good", filter_name, text=0)
treeview.append_column(column_text)
self.filter_low = Gtk.CellRendererSpin()
self.filter_low.connect("edited", self.low_on_amount_edited)
self.filter_low.set_property("editable", True)
low_adjustment = Gtk.Adjustment(0, 0, 99, 1, 10, 0)
self.filter_low.set_property("adjustment", low_adjustment)
low_spin = Gtk.TreeViewColumn("Random Number", self.filter_low, text=1)
treeview.append_column(low_spin)
self.add(treeview)
def low_on_amount_edited(self, widget, path, value):
value = int(value)
self.liststore[path][1] = value
self.GUI.restart_window(str(value))
class GUI:
def __init__(self):
self.win = Gtk.Window()
self.window_grid = Gtk.Grid()
self.special_box = Gtk.Box(spacing=10)
self.label = Gtk.Label("Number label")
self.win.connect("delete-event", Gtk.main_quit)
self.start_window()
def start_window(self):
self.special_box.pack_start(SpecialBox(self), True, True, 0)
self.window_grid.add(self.special_box)
self.window_grid.add(self.label)
self.win.add(self.window_grid)
self.win.show_all()
def restart_window(self, label="Number"):
self.window_grid.destroy()
self.window_grid = Gtk.Grid()
self.special_box = Gtk.Box(spacing=10)
self.label = Gtk.Label(label)
self.start_window()
def main():
app = GUI()
Gtk.main()
if __name__ == "__main__":
sys.exit(main())
The above code generates the error but for some reason the below code works fine (I essentially just replaced the above widget with a button):
import sys
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
# Documentation: https://graph-tool.skewed.de/static/doc/index.html
class SpecialButton(Gtk.Box):
def __init__(self, GUI):
Gtk.Box.__init__(self)
self.GUI = GUI
self.set_border_width(10)
self.message = "Special Text"
button = Gtk.Button.new_with_label(self.message)
button.connect("clicked", self.on_click)
self.pack_start(button, True, True, 0)
def on_click(self, widget):
self.GUI.restart_window(self.message)
class GUI:
def __init__(self):
self.win = Gtk.Window()
self.window_grid = Gtk.Grid()
self.box = Gtk.Box(spacing=10)
self.label = Gtk.Label("Default label")
self.win.connect("delete-event", Gtk.main_quit)
self.start_window()
def start_window(self):
self.box.pack_start(SpecialButton(self), True, True, 0)
self.window_grid.add(self.box)
self.window_grid.add(self.label)
self.win.add(self.window_grid)
self.win.show_all()
def restart_window(self, label="Default label"):
self.window_grid.destroy()
self.window_grid = Gtk.Grid()
self.box = Gtk.Box(spacing=10)
self.label = Gtk.Label(label)
self.start_window()
def main():
app = GUI()
Gtk.main()
if __name__ == "__main__":
sys.exit(main())
The problem here is that you're destroying a widget while an event handler of that widget is running. That widget is your CellRendererSpin.
When the value of this Spinbutton changes, it triggers low_on_amount_edited):
self.filter_low.connect("edited", self.low_on_amount_edited)
which calls GUI.restart_window:
self.GUI.restart_window(str(value))
which destroys the SpecialBox widget and all its child widgets, including the Spinbutton:
self.window_grid.destroy()
It's no surprise that destroying a widget while it's doing something is a bad idea.
To fix this, you just have to postpone the call to GUI.restart_window until the Spinbutton's event handler has finished. To do this, you can use idle_add, which queues a callback to be executed by the Gtk mainloop:
from gi.repository import Gtk, Gdk, GLib
class SpecialBox(Gtk.Box):
def low_on_amount_edited(self, widget, path, value):
value = int(value)
self.liststore[path][1] = value
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT, self.GUI.restart_window, str(value))

PyGi: How to use a GTKListBox with a GTKListStore?

I am very new to GTK and Gnome app development, so apologies for my naiveté. (My development language is Python). I would like to use a ListBox to display some data, and the individual row views will be quite complicated (i.e. composed of multiple different widgets). As a result I would prefer not to use a TreeView, because that will require a bunch of custom drawing/event handling. I noticed that ListBox has a bind_model method, but it appears I can't use it to bind a ListStore model, even thought ListStore implements the ListModel interface. Does anybody know how to accomplish this?
A simple exampe:
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio, GObject
import sys
class Item(GObject.GObject):
text = GObject.property(type = str)
def __init__(self):
GObject.GObject.__init__(self)
class GUI:
def __init__(self):
item1 = Item()
item1.text = "Hello"
item2 = Item()
item2.text = "World"
liststore = Gio.ListStore()
liststore.append(item1)
liststore.append(item2)
listbox=Gtk.ListBox()
listbox.bind_model(liststore, self.create_widget_func)
window = Gtk.Window()
window.add(listbox)
window.connect("destroy", self.on_window_destroy)
window.show_all()
def create_widget_func(self,item):
label=Gtk.Label(item.text)
return label
def on_window_destroy(self, window):
Gtk.main_quit()
def main():
app = GUI()
Gtk.main()
if __name__ == "__main__":
sys.exit(main())
This is condensed code from my open source accounting program.
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GdkPixbuf, Gdk
import os, sys
class GUI :
def __init__(self):
listbox = Gtk.ListBox()
employee_name_label = Gtk.Label("Henry", xalign=1)
combo = Gtk.ComboBoxText()
combo.set_property("can-focus", True)
for name in ["bar", "foo", "python"]:
combo.append('0', name)
list_box_row = Gtk.ListBoxRow()
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
list_box_row.add(hbox)
switch = Gtk.Switch()
switch.props.valign = Gtk.Align.CENTER
project_time_label = Gtk.Label("0:00:00", xalign=1 )
project_time_label.set_property('width-chars', 8)
hbox.pack_start(employee_name_label, True, False, 5)
hbox.pack_end(project_time_label, False, False, 5)
hbox.pack_end(switch, False, False, 5)
hbox.pack_end(combo, False, False, 5)
listbox.add(list_box_row)
window = Gtk.Window()
window.add(listbox)
window.connect("destroy", self.on_window_destroy)
window.show_all()
def on_window_destroy(self, window):
Gtk.main_quit()
def main():
app = GUI()
Gtk.main()
if __name__ == "__main__":
sys.exit(main())
It may not answer your question exactly, but it does work and it shows a way to use ListBox. ListBox is a very good choice for complicated setups. In my case I was doing so much operations every second that it crashed Treeviews.

Action during button pressed in Python

I am a beginner when it gomes to GUI programming with Python so I am guessing my problem has a simple solution even if I have not found a solution searching with google, wikis, documentation, examples ...
What I am trying to achive is that a value in an entry widget should constantly increase up to a max value as long as a button is pressed.
I have tried using callback for the event "button-press-event" but get the same response as with callback for the signal "clicked".
When connecting to "clicked" the application works as expected, e.g. the value is incremented each click but when I use a connection to the event "button-press-event" I still only get increment for each click (press and release)
I am using this with Python3.2 (on a Raspberry Pi 2)
Below is the working code that acts on each click:
#!/usr/bin/python
from gi.repository import Gtk, Gdk
from time import sleep
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="ST")
MAX_SPD = 3000
self.set_default_size(100,100)
self.set_size_request(100,100)
self.set_resizable(False)
spdEntry = Gtk.Entry()
spdEntry.set_has_frame(True)
spdEntry.set_text("0")
spdEntry.connect("activate", self.inputSpd, MAX_SPD)
start = Gtk.Button("Start")
start.connect("clicked", self.clicked_start)
stop = Gtk.Button("Stop")
stop.connect("clicked", self.clicked_stop)
inc = Gtk.Button("inc")
inc.connect("clicked", self.pressed_inc, spdEntry, MAX_SPD)
fixed = Gtk.Fixed()
fixed.put(start, 0, 0)
fixed.put(spdEntry, 0, 40)
fixed.put(stop, 0, 70)
fixed.put(inc, 120, 0)
self.add(fixed)
def clicked_start(self, widget):
self.set_title("GO")
def clicked_stop(self, widget):
self.set_title("ST")
def pressed_inc(self, widget, entry, maxSpd):
speed = int(entry.get_text())
speed = speed+1
if speed > maxSpd:
speed = maxSpd
entry.set_text(str(speed))
def inputSpd(self, entry, maxSpd):
speed = int(entry.get_text())
if speed > maxSpd:
speed = maxSpd
entry.set_text(str(speed))
win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
This is the non working code that should increment as long button is pressed:
#!/usr/bin/python
from gi.repository import Gtk, Gdk
from time import sleep
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="ST")
MAX_SPD = 3000
self.set_default_size(100,100)
self.set_size_request(100,100)
self.set_resizable(False)
spdEntry = Gtk.Entry()
spdEntry.set_has_frame(True)
spdEntry.set_text("0")
spdEntry.connect("activate", self.inputSpd, MAX_SPD)
start = Gtk.Button("Start")
start.connect("clicked", self.clicked_start)
stop = Gtk.Button("Stop")
stop.connect("clicked", self.clicked_stop)
inc = Gtk.Button("inc")
inc.connect("button-press-event", self.pressed_inc, spdEntry, MAX_SPD)
inc.connect("button-release-event", self.left_inc)
fixed = Gtk.Fixed()
fixed.put(start, 0, 0)
fixed.put(spdEntry, 0, 40)
fixed.put(stop, 0, 70)
fixed.put(inc, 120, 0)
self.add(fixed)
def clicked_start(self, widget):
self.set_title("GO")
def clicked_stop(self, widget):
self.set_title("ST")
def pressed_inc(self, widget, event, entry, maxSpd):
if event.type == Gdk.EventType.BUTTON_PRESS:
speed = int(entry.get_text())
speed = speed+1
if speed > maxSpd:
speed = maxSpd
entry.set_text(str(speed))
return True
def left_inc(self, widget, event):
if event.type == Gdk.EventType.BUTTON_RELEASE:
return True
def inputSpd(self, entry, maxSpd):
speed = int(entry.get_text())
if speed > maxSpd:
speed = maxSpd
entry.set_text(str(speed))
win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
You can do this by using GLib.timeout_add(). However, I agree to gianmt that it is better to just use a Gtk.SpinButton
#!/usr/bin/python
from gi.repository import Gtk, Gdk, GLib
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="ST")
self.MAXSPEED = 3000
self.set_default_size(100,100)
self.set_resizable(False)
self.entry = Gtk.Entry()
self.entry.set_text("0")
start = Gtk.Button(label="Start")
start.connect("clicked", self.clicked_start)
stop = Gtk.Button(label="Stop")
stop.connect("clicked", self.clicked_stop)
inc = Gtk.Button(label="inc")
inc.connect("button-press-event", self.pressed_inc)
inc.connect("button-release-event", self.left_inc)
fixed = Gtk.Fixed()
fixed.put(start, 0, 0)
fixed.put(self.entry, 0, 40)
fixed.put(stop, 0, 70)
fixed.put(inc, 120, 0)
self.add(fixed)
def clicked_start(self, widget):
self.set_title("GO")
def clicked_stop(self, widget):
self.set_title("ST")
def pressed_inc(self, widget, event):
self.inc_id = GLib.timeout_add(100, self.increase)
def left_inc(self, widget, event,):
GLib.source_remove(self.inc_id)
def increase(self):
speed = int(self.entry.get_text()) + 1
if speed > self.MAXSPEED:
self.entry.set_text(str(self.MAXSPEED))
else:
self.entry.set_text(str(speed))
return True
win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
There was also a from time import sleep as an import on top of your code. It was not used and I do not know about the rest of your application but using time.sleep(), while you are not in a thread, will block the Gtk.main() loop and make your application unresponsive.

Categories

Resources