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()
Related
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()
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.
I'm trying to develop an application using Gtk, and I have run into a problem using GtkOverlay. If I have a GtkOverlay with a GtkTextView that was added using the standard container add method, the text is hidden. However, all other widgets, say for example, buttons, appear just fine. Even more odd is the fact that this behavior is only present if at least one widget was adding using add_overlay.
#!/usr/bin/env python
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
USE_OVERLAY = False
win = Gtk.Window()
text_view = Gtk.TextView()
overlay = Gtk.Overlay()
top_button = Gtk.Button()
bottom_button = Gtk.Button()
top_container = Gtk.VBox()
bottom_container = Gtk.VBox()
overlay_str = "( USE_OVERLAY = " + str(USE_OVERLAY) + ")"
win.set_title(overlay_str)
top_button.set_label("I'm a button on top!")
bottom_button.set_label("I'm a button on bottom!")
text_view.get_buffer().set_text("This should be visible")
win.add(overlay)
overlay.add(bottom_container)
bottom_container.pack_start(bottom_button, False, False, 0)
bottom_container.pack_end(text_view, True, True, 0)
if USE_OVERLAY:
overlay.add_overlay(top_container)
top_container.pack_end(top_button, False, False, 0)
win.connect("delete-event", Gtk.main_quit)
overlay.show_all()
win.show_all()
Gtk.main()
I have reason to believe that this is not a python problem, as the actual application is written using haskell-gi, however I figured more people would be familiar with python.
I don't know on what system your a running this example but it is working fine for me. The only caveat is that the top button appears over the bottom button and the TextView widget so I have to manually resize the Window to see the text. You can see a screen cast of my situation in this video: https://youtu.be/xoAH4OuEM0E
Now depending on what you really want there may be few different answers. What I would suggest is putting the TextView inside a ScrolledWindow. This way the TextView will be at least visible before you would need the resize the window. It would also have the consequence to provide scrollbars if the text overflow the visible area.
It could look like this:
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
USE_OVERLAY = True
win = Gtk.Window()
text_view = Gtk.TextView()
overlay = Gtk.Overlay()
top_button = Gtk.Button()
bottom_button = Gtk.Button()
top_container = Gtk.VBox()
bottom_container = Gtk.VBox()
overlay_str = "( USE_OVERLAY = " + str(USE_OVERLAY) + ")"
win.set_title(overlay_str)
top_button.set_label("I'm a button on top!")
bottom_button.set_label("I'm a button on bottom!")
text_view.get_buffer().set_text("This should be visible")
# This is where the text_view is inserted in a ScrolledWindow
scrolled_window = Gtk.ScrolledWindow()
scrolled_window.add(text_view)
win.add(overlay)
overlay.add(bottom_container)
bottom_container.pack_start(bottom_button, False, False, 0)
# The scrolled_window is inserted in the bottom_container
bottom_container.pack_end(scrolled_window, True, True, 0)
if USE_OVERLAY:
overlay.add_overlay(top_container)
top_container.pack_end(top_button, False, False, 0)
win.connect("delete-event", Gtk.main_quit)
overlay.show_all()
win.show_all()
Gtk.main()
You can also see the result on the aforementioned screencast. The only drawback is that the top button won't be able to overlay as much the bottom layer as in your script. But maybe it won't bother you.
I'm writing an app using Gtk3 and Python. I have a revealer as a sidebar to select the content and a webkit webview to display the main content. When the revealer is hidden the webview doesn't fill the entire window space and I don't know why. Any help would be appreciated.
from gi.repository import Gtk, Gio
from gi.repository import WebKit
HEIGHT = 500
WIDTH = 800
class MainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Resolution")
self.set_border_width(0)
self.set_default_size(WIDTH, HEIGHT)
hb = Gtk.HeaderBar()
hb.props.show_close_button = True
hb.props.title = "Resolution"
self.set_titlebar(hb)
button = Gtk.Button()
icon = Gio.ThemedIcon(name="emblem-system-symbolic")
image = Gtk.Image.new_from_gicon(icon, 1)
button.add(image)
button.connect("clicked", self.sidebarShowHide)
button.set_focus_on_click(False)
hb.pack_start(button)
sidebarbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
toplevelbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
self.add(toplevelbox)
self.sidebar = Gtk.Revealer()
self.sidebar.set_transition_duration(0)
self.sidebar.set_reveal_child(False)
toplevelbox.pack_start(self.sidebar, False, False, 0)
self.sidebar.add(sidebarbox)
self.searchentry = Gtk.SearchEntry()
self.searchentry.connect("search-changed", self.search_changed)
sidebarbox.pack_start(self.searchentry, False, False, 0)
label = Gtk.Label("Contents Selector")
sidebarbox.pack_start(label, True, True, 0)
scroller = Gtk.ScrolledWindow()
content = WebKit.WebView()
scroller.add(content)
toplevelbox.pack_start(scroller, True, True, 0)
content.open("/home/oliver/resolution/placeholder.html")
def sidebarShowHide(self, button):
if self.sidebar.get_reveal_child():
self.sidebar.set_reveal_child(False)
else:
self.sidebar.set_reveal_child(True)
def search_changed(self, searchentry):
pass
win = MainWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
Well, i have done some GtkRevealer few months ago and it works. It drive me nuts to see this piece of code was not.
I opened my project again and look inside where that part is, and it turn out the toplevel container where the Gtk.Revealer resides, has to has Gtk.Orientation.VERTICAL.. if you change your "toplevelbox" orientation to that, it will work, but it wont be sidebar. It will coming from top or bottom. It goes the same if you change GtkBox with GtkGrid. If I were to guess it depends on the children default orientation.
Workaround on that, is to use widget hide/show mechanism (believe me, i ransack your code and it works).
from gi.repository import Gtk, Gio
from gi.repository import WebKit
HEIGHT = 500
WIDTH = 800
class MainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Resolution")
self.set_border_width(0)
self.set_default_size(WIDTH, HEIGHT)
hb = Gtk.HeaderBar()
hb.props.show_close_button = True
hb.props.title = "Resolution"
self.set_titlebar(hb)
button = Gtk.Button()
icon = Gio.ThemedIcon(name="emblem-system-symbolic")
image = Gtk.Image.new_from_gicon(icon, 1)
button.add(image)
button.connect("clicked", self.sidebarShowHide)
button.set_focus_on_click(False)
hb.pack_start(button)
sidebarbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
toplevelbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
self.add(toplevelbox)
self.sidebar = Gtk.Box()
toplevelbox.pack_start(self.sidebar, False, False, 0)
self.sidebar.add(sidebarbox)
self.searchentry = Gtk.SearchEntry()
self.searchentry.connect("search-changed", self.search_changed)
sidebarbox.pack_start(self.searchentry, False, False, 0)
label = Gtk.Label("Contents Selector")
sidebarbox.pack_start(label, True, True, 0)
scroller = Gtk.ScrolledWindow()
content = WebKit.WebView()
scroller.add(content)
toplevelbox.pack_start(scroller, True, True, 0)
content.open("/home/oliver/resolution/placeholder.html")
def sidebarShowHide(self, button):
if self.sidebar.get_visible():
self.sidebar.hide ()
else:
self.sidebar.show ()
def search_changed(self, searchentry):
pass
win = MainWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
This smells like a bug.
As a workaround, you could use
def sidebarShowHide(self, button):
self.sidebarbox.set_visible(not self.sidebarbox.get_visible())
but this does not yield any transition animation, but does remove its allocated space for the time being invisible.
Actually the C demo provided within the git repo resizes as expected, so this might in fact have to do something with the child widgets prefered orientation.
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.