I'm trying to setup a window with a notebook and some pages. Within the pages, there will be some entries (see example code).
I'd like to handle the tab key and arrow keys on my own. I don't want the arrow up key to jump to the page title, I don't want the arrow left / right key to cycle through the pages. I don't want the tab key to cycle through the entries.
Connecting to the key-press signal and checking for tab or arrow keys does not really work.
I tried to change the focus chain, but it still focusses on the page title or cycles through the pages with left / rigth arrow.
Any help / idea is highly appreciated.
#!/usr/bin/env python
import pygtk
import gtk
class NotebookExample:
def __init__(self):
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_size_request(200,200)
notebook = gtk.Notebook()
notebook.set_tab_pos(gtk.POS_TOP)
notebook.show()
hbox1 = gtk.HBox()
notebook.append_page(hbox1, gtk.Label("Page1"))
hbox2 = gtk.HBox()
notebook.append_page(hbox2, gtk.Label("Page2"))
window.add(notebook)
entry1 = gtk.Entry()
entry2 = gtk.Entry()
entry3 = gtk.Entry()
entry1.set_width_chars(5)
entry2.set_width_chars(5)
entry3.set_width_chars(5)
hbox1.pack_start(entry1, False, False, 10)
hbox1.pack_start(entry2, False, False, 10)
hbox1.pack_start(entry3, False, False, 10)
hbox1.set_focus_chain([entry2, entry3])
window.show_all()
def main():
gtk.main()
return 0
if __name__ == "__main__":
NotebookExample()
main()
Found it.
Listening to the key-press-event and returning "True to stop other handlers from being invoked for the event. False to propagate the event further.
window.connect("key-press-event", self.do_key_press)
def do_key_press(self, widget, event):
if gtk.gdk.keyval_name(event.keyval) == 'Tab':
print "tab"
return True
if gtk.gdk.keyval_name(event.keyval) == 'Left' or gtk.gdk.keyval_name(event.keyval) == 'Right':
print "cursor"
return True
return
Related
I want to switch pages with the help of buttons in Gtk.Stack. There are 3 pages, and the title bar of the application has one forward and one back button. I want it to go to the next page when the forward button is pressed, and to go to the previous page when the back button is pressed. Its current state can only switch between page 1 and page 2.
import gi, os
gi.require_version("Gtk", "3.0")
gi.require_version("Handy", "1")
from gi.repository import Gtk, Handy
Handy.init()
class MyWindow(Handy.Window):
def __init__(self):
super().__init__(title="Hello World")
self.set_default_size(500, 300)
# WindowHandle
self.handle = Handy.WindowHandle()
self.add(self.handle)
# Box
self.winbox = Gtk.Box(spacing=6, orientation=Gtk.Orientation.VERTICAL)
self.handle.add(self.winbox)
# Headerbar
self.hb = Handy.HeaderBar()
self.hb.set_show_close_button(True)
self.hb.props.title = "Stack Example"
self.winbox.pack_start(self.hb, False, True, 0)
# Stack
self.stack = Gtk.Stack()
self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT)
self.winbox.pack_start(self.stack, True, True, 0)
# Labels
self.label = Gtk.Label(label="Page 1")
self.stack.add_titled(self.label, "page0", "Label")
self.label = Gtk.Label(label="Page 2")
self.stack.add_titled(self.label, "page1", "Label")
self.label = Gtk.Label(label="Page 3")
self.stack.add_titled(self.label, "page2", "Label")
# Headerbar button 1
self.button = Gtk.Button()
self.button = Gtk.Button.new_from_icon_name("pan-start-symbolic", Gtk.IconSize.MENU)
self.hb.pack_start(self.button)
self.button.connect('clicked', self.on_button1_clicked)
# Headerbar button 2
self.button2 = Gtk.Button()
self.button2 = Gtk.Button.new_from_icon_name("pan-end-symbolic", Gtk.IconSize.MENU)
self.hb.pack_start(self.button2)
self.button2.connect("clicked", self.on_button2_clicked)
def on_button1_clicked(self, widget):
self.stack.set_visible_child_name("page1")
def on_button2_clicked(self, widget):
self.stack.set_visible_child_name("page2")
win = MyWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()
I don't know if there's an easy way to make visible the next child in a GtkStack or if another container has this functionality apart from GtkAssistant.
Nevertheless there's multiple ways you can implement this yourself. Either like so:
def on_button1_clicked(self, widget):
pages = self.stack.get_children()
cur_page = self.stack.get_visible_child()
i = pages.index(cur_page)
if i == 0: return
self.stack.set_visible_child(pages[i-1])
def on_button2_clicked(self, widget):
pages = self.stack.get_children()
cur_page = self.stack.get_visible_child()
i = pages.index(cur_page)
if i == len(pages) - 1: return
self.stack.set_visible_child(pages[i+1])
where you get the stack's children with GtkContainer.get_children(), find the index of the current visible child and then plus/minus one to get the next/prev page.
Caveat: I'm not sure if get_children() always returns the child widgets in the order they are added.
Alternatively in your __init__() function, you can create a list to store your page names/widgets e.g. self.page_names = ['page0', 'page1', 'page2']. And then you can do:
def on_button1_clicked(self, widget):
cur_page_name = self.stack.get_visible_child_name()
i = self.page_names.index(cur_page_name)
if i == 0: return
self.stack.set_visible_child_name(self.page_names[i-1])
Or maybe you extract the page number from the child name (e.g. 0 from page0) using RegEx and generate the next page's name. There's many ways to accomplish this, I personally would keep a variable of all the pages and use that to determine which page is next/prev.
I want my application to toggle fullscreen every time you click on the menu item. So if you click once, it becomes fullscreen, if you click again, it becomes normal again. I tried the following but after I clicked it again, it wouldn't switch.
def Fullscreen(self):
self.fullscreen = False
if not self.fullscreen:
self.root.wm_attributes("-fullscreen", True)
else:
self.root.wm_attributes("-fullscreen", False)
You are missing a key part here. Nothing changes full screen back to True.
Here is a simple example of what you could do to toggle full screen.
import tkinter as tk
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
tk.Button(self, text="Toggle Fullscreen", command=self.fullscreen_toggle).pack()
self.fullscreen = False
def fullscreen_toggle(self):
if self.fullscreen == False:
self.wm_attributes("-fullscreen", True)
self.fullscreen = True
else:
self.wm_attributes("-fullscreen", False)
self.fullscreen = False
app = App()
app.mainloop()
I am using Gtk 3.18 on Windows 10 through Python 3.4. I wrote the following script to press a button to add a new Gtk.ListBoxRow() to the self.listbox in my MyWindow class. It happens in the function add_item(self, whatevs).
I clearly mention there
self.listbox.add(row)
Then why doesn't it work still? The function is being invoked when I press the "Add Item" button. But the list does not get another row. Why so any idea?
Nothing happens. Not even any error is displayed. Can someone please tell me what it is I am doing wrong here? Any help is appreciated.
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title = "Win win win")
self.set_border_width(3)
self.set_default_size(300, 250)
box = Gtk.Box(orientation = Gtk.Orientation.VERTICAL, spacing = 6)
self.add(box)
self.listbox = Gtk.ListBox()
self.listbox.set_selection_mode(Gtk.SelectionMode.SINGLE)
box.pack_start(self.listbox, True, True, 0)
row = Gtk.ListBoxRow()
hbox = Gtk.Box()
row.add(hbox)
hbox.pack_start(Gtk.Label("Here is an Item"), True, True, 0)
self.listbox.add(row)
hbox = Gtk.Box()
button_add_item = Gtk.Button(label = "Add Item", valign = Gtk.Align.CENTER)
button_add_item.connect("clicked", self.add_item)
hbox.pack_start(button_add_item, True, True, 0)
button_remove_item = Gtk.Button(label = "Remove Item", valign = Gtk.Align.CENTER)
button_remove_item.connect("clicked", self.remove_item)
hbox.pack_start(button_remove_item, True, True, 0)
box.pack_start(hbox, False, True, 0)
def add_item(self, whatevs):
row = Gtk.ListBoxRow()
hbox = Gtk.Box()
row.add(hbox)
item_label = Gtk.Label("Here is another Item")
hbox.pack_start(item_label, True, True,0)
self.listbox.add(row)
def remove_item(self, whatevs):
self.listbox.remove(self.listbox.remove.get_row_at_y(-1))
win = MyWindow()
win.connect('delete-event', Gtk.main_quit)
win.show_all()
Gtk.main()
By the way can someone tell me why it is that I have to include that other parameter, the one other than "self" in the "connected" functions to the buttons? Any idea how I could use them?
I found out what was wrong. I was supposed to use the Gtk.ListBox.show_all() function of the self.listbox object in my program. Hop this helps someone in the future.
As #shaan-repswal already said, you can call Gtk.ListBox.show_all() after adding the widget(s) to the list.
Remember although that if your row contains widgets that you want to keep not visible, you have to, depending on how you manage the widget:
call your_widget.set_no_show_all(True);
set the attribute props.no_show_all of the widget to True.
add the line
<property name="no_show_all">True</property>
to the object tag of your widget in the glade file.
source: https://stackoverflow.com/a/29130873/9402438
I was originally looking for this problem, regarding C. However I stumbled across this question, so the respective function in C is called:
gtk_widget_show_all(your_list_box);
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 editted the code so that the 3 buttons now show up .Can someone please tell me how to make it so that when I click the button that says Helloworld and application called Helloworld.py will pop-up in another window.Same for the other 2 buttons
!/usr/bin/env python
# menu.py
import pygtk
pygtk.require('2.0')
import gtk
class MenuExample:
def __init__(self):
# create a new window
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_size_request(200, 100)
window.set_title("GTK Menu Test")
window.connect("delete_event", lambda w,e: gtk.main_quit())
# Init the menu-widget, and remember -- never
# show() the menu widget!!
# This is the menu that holds the menu items, the one that
# will pop up when you click on the "Root Menu" in the app
menu = gtk.Menu()
# Next we make a little loop that makes three menu-entries for
# "test-menu". Notice the call to gtk_menu_append. Here we are
# adding a list of menu items to our menu. Normally, we'd also
# catch the "clicked" signal on each of the menu items and setup a
# callback for it, but it's omitted here to save space.
for i in range(3):
# Copy the names to the buf.
buf = "Test-undermenu - %d" % i
# Create a new menu-item with a name...
menu_items = gtk.MenuItem(buf)
# ...and add it to the menu.
menu.append(menu_items)
# Do something interesting when the menuitem is selected
menu_items.connect("activate", self.menuitem_response, buf)
# Show the widget
menu_items.show()
# This is the root menu, and will be the label
# displayed on the menu bar. There won't be a signal handler attached,
# as it only pops up the rest of the menu when pressed.
root_menu = gtk.MenuItem("Root Menu")
root_menu.show()
# Now we specify that we want our newly created "menu" to be the
# menu for the "root menu"
root_menu.set_submenu(menu)
# A vbox to put a menu and a button in:
vbox = gtk.VBox(False, 0)
window.add(vbox)
vbox.show()
# Create a menu-bar to hold the menus and add it to our main window
menu_bar = gtk.MenuBar()
vbox.pack_start(menu_bar, False, False, 2)
menu_bar.show()
# Create a button to which to attach menu as a popup
button = gtk.Button("HelloWorld")
button.connect_object("event", self.button_press, menu)
vbox.pack_end(button, True, True, 2)
button.show()
button2 = gtk.Button("Scrible")
button2.connect_object("event", self.button_press, menu)
vbox.pack_end(button2, True, True, 2)
button2.show()
button3 = gtk.Button("Final")
button3.connect_object("event", self.button_press, menu)
vbox.pack_end(button3, True, True, 2)
button3.show()
# And finally we append the menu-item to the menu-bar -- this is the
# "root" menu-item I have been raving about =)
menu_bar.append (root_menu)
# always display the window as the last step so it all splashes on
# the screen at once.
window.show()
# Respond to a button-press by posting a menu passed in as widget.
#
# Note that the "widget" argument is the menu being posted, NOT
# the button that was pressed.
def button_press(self, widget, event):
if event.type == gtk.gdk.BUTTON_PRESS:
widget.popup(None, None, None, event.button, event.time)
# Tell calling code that we have handled this event the buck
# stops here.
return True
# Tell calling code that we have not handled this event pass it on.
return False
def button2_press(self, widget, event):
if event.type == gtk.gdk.BUTTON2_PRESS:
widget.popup(None, None, None, event.button, event.time)
return True
return False
def button3_press(self, widget, event):
if event.type == gtk.gdk.BUTTON3_PRESS:
widget.popup(None, None, None, event.button, event.time)
return True
return False
# Print a string when a menu item is selected
def menuitem_response(self, widget, string):
print "%s" % string
def main():
gtk.main()
return 0
if __name__ == "__main__":
MenuExample()
main()
You could do something like this. I'm assuming you just want to execute your .py files, e.g. helloworld.py etc. I'm using Popen from subprocess to execute python (not assuming the py files are executable) scripts. Note that I've edited the script to only have one button, this is just to show you the idea.
import pygtk
pygtk.require('2.0')
import gtk
import subprocess
class Example:
def __init__(self):
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_size_request(200, 100)
window.set_title("GTK Menu Test")
window.connect("delete_event",
lambda w,e: gtk.main_quit())
vbox = gtk.VBox(False, 0)
window.add(vbox)
vbox.show()
button = gtk.Button("HelloWorld")
button.connect("clicked", self.clicked_helloworld)
vbox.pack_end(button, True, True, 2)
button.show()
window.show_all()
def clicked_helloworld(self, widget):
subprocess.Popen(["python", "helloworld.py"])
def main(self):
gtk.main()
return 0
Example().main()