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.
Related
In my Tkinter app I have a button that opens a Toplevel Window which dispays an event log. There are a few things I need the Toplevel Window to be able to do:
Show previous log entries when opened, as well as update with new ones.
Disable the user's ability to move the window around the while also making the user able to close the window
Have the window always be anchored with it's top right corner being at the root window's top right corner
I have figured out #1. I am able to have the window open and display previous entries as well as update those entries while the window is open. My problem is with #2 and #3.
For #2 I am not sure how to disable the user's ability to move the window. I am assuming this may also disable the user's ability to close the window so I am not sure how to keep that functionality intact. Maybe a button with self.quit() as it's command?
As for #3, I have no idea how to go about doing this. Maybe I suck as Googling but I can't seem to find out how to accomplish this.
This is the code I have at the moment, which is able to properly implement feature #1.
import tkinter as tk
class guiapp(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.master = master
self.value = 0.0
self.alive = True
self.list_for_toplevel = []
btn = tk.Button(self.master, text = "Click", command = self.TextWindow)
btn.pack()
def TextWindow(self):
self.textWindow = tk.Toplevel(self.master)
self.textFrame = tk.Frame(self.textWindow)
self.textFrame.pack()
self.textArea = tk.Text(self.textWindow, height = 10, width = 30)
self.textArea.pack(side = "left", fill = "y")
bar = tk.Scrollbar(self.textWindow)
bar.pack(side = "right", fill = "y")
bar.config(command = self.textArea.yview)
self.alive = True
self.timed_loop()
def timed_loop(self):
if self.alive == True and tk.Toplevel.winfo_exists(self.textWindow):
self.master.after(1000, self.timed_loop)
self.value += 1
self.list_for_toplevel.append(self.value)
self.textArea.delete(1.0, "end-1c")
for item in self.list_for_toplevel:
self.textArea.insert('end', "{}\n".format(item))
self.textArea.see('end')
else:
self.alive = False
if __name__ == "__main__":
root = tk.Tk()
root.geometry("800x480")
myapp = guiapp(root)
root.mainloop()
We can remove the tool bar from the top of the toplevel window and prevent the user from moving the window with self.textWindow.overrideredirect(True).
Then we can make sure that the toplevel window is positioned in the top right corner by getting the root windows location and then setting the toplevel window to the same location with self.master.winfo_x() and self.master.winfo_y().
Last I would add a button that closes the window because we no longer have the tool bar for the toplevel window.
UPDATE: I have added the ability for the toplevel window to stay on top of the root window and to move around with the root window when root is dragged.
we can use bind() to track when the root window is moved and then have a function that will update the toplevel windows position to match the root windows.
We can also use self.textWindow.attributes("-topmost", True) to tell tkinter to keep out toplevel window on top of all other windows.
Take a look at the modified version of your code below. Let me know what you think or if you have any questions.
import tkinter as tk
class guiapp(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.master = master
self.textWindow = None
self.master.bind("<Configure>", self.move_me)
self.value = 0.0
self.list_for_toplevel = []
btn = tk.Button(self.master, text = "Click", command = self.TextWindow)
btn.pack()
def TextWindow(self):
x = self.master.winfo_x()
y = self.master.winfo_y()
self.textWindow = tk.Toplevel(self.master)
self.textFrame = tk.Frame(self.textWindow)
self.textWindow.overrideredirect(True)
self.textFrame.pack()
self.textWindow.attributes("-topmost", True)
self.textWindow.geometry('+{}+{}'.format(x+10, y+30))
self.close_toplevel = tk.Button(self.textWindow, text = "close", command = self.close_textWindow)
self.close_toplevel.pack()
self.textArea = tk.Text(self.textWindow, height = 10, width = 30)
self.textArea.pack(side = "left", fill = "y")
bar = tk.Scrollbar(self.textWindow)
bar.pack(side = "right", fill = "y")
bar.config(command = self.textArea.yview)
self.alive = True
self.timed_loop()
def close_textWindow(self):
self.textWindow.destroy()
self.textWindow = None
def move_me(self, event):
if self.textWindow != None:
x = self.master.winfo_x()
y = self.master.winfo_y()
self.textWindow.geometry('+{}+{}'.format(x+10, y+30))
def timed_loop(self):
if self.textWindow != None:
self.master.after(1000, self.timed_loop)
self.value += 1
self.list_for_toplevel.append(self.value)
self.textArea.delete(1.0, "end-1c")
for item in self.list_for_toplevel:
self.textArea.insert('end', "{}\n".format(item))
self.textArea.see('end')
if __name__ == "__main__":
root = tk.Tk()
root.geometry("800x480")
myapp = guiapp(root)
root.mainloop()
I have made a small application with tkinter and Python 3 which has four buttons on the top of the window to form a menu. It works fine but I want to know how to make the buttons appear along the window over a period of time starting from a single button in the center when first started rather than being statically placed in the center.
Here is my script so far:
import tkinter as tk
class utilities(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.pack()
self.window()
def window(self):
self.pluginrun = tk.Button(self)
self.pluginrun["text"] = "Run Existing Plugin"
self.pluginrun["command"] = self.run_plugin
self.pluginrun.pack(side="left")
self.owning = tk.Button(self)
self.owning["text"] = "Add A New Plugin"
self.owning["command"] = self.plugin
self.owning.pack(side="left")
self.webpage = tk.Button(self)
self.webpage["text"] = "Webpage"
self.webpage["command"] = self.web
self.webpage.pack(side="left")
self.more_info = tk.Button(self)
self.more_info["text"] = "More"
self.more_info["command"] = self.more
self.more_info.pack(side="left")
def run_plugin(self):
print('Running Plugin')
def plugin(self):
print('Available Extensions')
def web(self):
print("Opening Webpage To Python.org")
def more(self):
print('Made Entirely In Python')
root = tk.Tk()
root.geometry('500x500')
show = utilities(master=root)
show.mainloop()
Which gives this result:
When first opened I would like it to look like this:
and over a period of time for more buttons to appear alongside one at a time until it looks like the first image.
How can this be done?
You can add all your buttons to a list and then use a repeating timed method to pack each button in the list one at a time at a set interval.
I created a counter that we can use to keep track of what button is going to be packed next from the list.
I also created a new list to store all the buttons in.
Then I modified your window() method to add each button to the list instead.
The last thing was to create a timed method that would use the self.counter attribute I created to keep track of what button is to be packed next.
In tkinter the best method to use to keep a timed loop or set a timer for anything is to use after(). Using sleep() or wait() in tkinter will only cause the entire tkinter app to freeze.
Take a look at the below code.
import tkinter as tk
class utilities(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.pack()
self.list_of_buttons = []
self.counter = 0
self.window()
def window(self):
for count in range(4):
self.list_of_buttons.append(tk.Button(self))
pluginrun = self.list_of_buttons[0]
pluginrun["text"] = "Run Existing Plugin"
pluginrun["command"] = self.run_plugin
owning = self.list_of_buttons[1]
owning["text"] = "Add A New Plugin"
owning["command"] = self.plugin
webpage = self.list_of_buttons[2]
webpage["text"] = "Webpage"
webpage["command"] = self.web
more_info = self.list_of_buttons[3]
more_info["text"] = "More"
more_info["command"] = self.more
self.timed_buttons()
def timed_buttons(self):
if self.counter != len(self.list_of_buttons):
self.list_of_buttons[self.counter].pack(side ="left")
self.counter +=1
root.after(1500, self.timed_buttons)
def run_plugin(self):
print('Running Plugin')
def plugin(self):
print('Available Extensions')
def web(self):
print("Opening Webpage To Python.org")
def more(self):
print('Made Entirely In Python')
root = tk.Tk()
root.geometry('500x500')
show = utilities(master=root)
show.mainloop()
Add the Buttons inside a Frame, which you centre, and then as you add more Buttons, the Frame should centre them. If not, you may need to call root.update(), to re-centre the Frame.
probably I'm less than a newbie in both python and GTK. Here my problem:
I've created a class to display a windows with a search bar and a treeview.
I fill the tree reading from an SQLITEDB.
Fine.
I'd like to use the search bar in order to select an item in the treeview (so performing, a db search and fill the treeview with the result)
I'm blocked on the callback since I cannot understand how to pass the user inserted data to a specific function.
Below some lines from my (STUPID) code.
class SecondWin:
def __init__(self):
self.win = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.win.connect("delete_event", self.delete_event)
self.win.set_title("Gmail Phonebook")
self.win.set_size_request(600, 300) #Larghez1za, Altezza
self.win.set_border_width(8)
self.win.set_position(gtk.WIN_POS_CENTER)
self.win.connect("destroy", self.destroy)
self.table = gtk.Table(8, 8,True)
self.cerca_bottone = gtk.Button("Cerca")
self.cerca_bottone.set_size_request(70, 30) #Larghezza, Altezza
self.cerca_bottone.connect( "clicked", self.cercainrubrica) #Call back sul bottone
self.table.attach(self.cerca_bottone, 0, 1, 0, 1,gtk.SHRINK,gtk.SHRINK)
# Search BAR
self.hbox = gtk.HBox()
self.entry = gtk.Entry(30)
self.entry.connect("activate", self.cercainrubrica) #call back su enter
self.hbox.pack_end(self.entry)
self.table.attach(self.hbox, 1, 8, 0, 1,gtk.EXPAND|gtk.FILL|gtk.SHRINK,
gtk.EXPAND|gtk.FILL|gtk.SHRINK,0,0)
self.vbox = gtk.VBox(False, 8)
self.sw = gtk.ScrolledWindow()
self.sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
self.sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.vbox.pack_start(self.sw, True, True, 0)
self.table.attach(self.vbox, 1, 8, 1, 9,gtk.EXPAND|gtk.FILL|gtk.SHRINK,
gtk.EXPAND|gtk.FILL|gtk.SHRINK,10,10)
rubrica=mydb.find_record_complex("%", colonne_test[0])
store = self.create_model(rubrica) #THIS WORK FINE DISPLAYING THE SELECTION
HERE MY FUNCION
self.cercainrubrica ??
treeView=gtk.TreeView(store)
treeView.connect("row-activated", self.on_activated)
treeView.set_rules_hint(True)
self.sw.add(treeView)
self.create_columns(treeView,nomi_colonne)
self.statusbar = gtk.Statusbar()
self.win.add(self.table)
self.win.show_all()
THIS IS MY CALL BACK
def cercainrubrica( self, w, data=None):
name = self.entry.get_text()
capperi=mydb.find_record_complex(name, colonne_test[0])
store = self.create_model(capperi)
return store
def delete_event(self, widget, event, data=None):
return gtk.FALSE
def destroy(self, widget, data=None):
return gtk.main_quit()
def main(self):
gtk.main()
def create_model(self,records):
store = gtk.ListStore(str, str, str,str)
for record in records:
store.append([record[1], record[2], record[3],record[4]])
return store
def create_columns(self, treeView,intestazione_colonne):
i = 0
for nomecolonna in intestazione_colonne:
rendererText = gtk.CellRendererText()
column = gtk.TreeViewColumn(intestazione_colonne[i], rendererText, text=i)
column.set_sort_column_id(i)
treeView.append_column(column)
i += 1
def on_activated(self, widget, row, col):
model = widget.get_model()
text = model[row][0] + ", " + model[row][1] + ", " + model[row][2]
self.statusbar.push(0, text)
if __name__ == "__main__":
second = SecondWin()
second.main()
ANY HELP IS REALLY APPRECIATED
Not 100% sure what you want to do but if you want to filter what the treeview is showing based on the entered text, you should take a look at GtkTreeModelFilter. You can use it as a TreeModel and set your own VisibleFunc that decides if a row should be visible or not based on the entered text. When the text changes, just call refilter(): that will call VisibleFunc() for every row.
Sorry for not having a python example or docs for you, I hope that still helps...
What is the proper way to interact with a button without actually clicking on it?
I have a button "button", that can, upon click :
Call the method "the_method" that will print what argument (here "filename") has been passed to it
toggle its own attributes, here its icon.
And I have a treeview, whose rows must, upon double click :
Call the method "the_method" that will print what argument (here "filename") has been passed to it
toggle "button"'s attributes, here its icon.
And only the 1st part works. The "foo" function is called (via a callback for the button, directly for the treeview item) and the argument ("filename") is retrieved OK, but how to execute part 2 of the job (changing "button"'s attributes, here its icon)?
import gtk
class Lister(object):
def __init__(self):
self.hbox = gtk.HBox()
liststore = gtk.ListStore(str)
liststore.append(["foo"])
liststore.append(["bar"])
treeview = gtk.TreeView(liststore)
self.hbox.pack_start(treeview, False)
cell = gtk.CellRendererText()
col = gtk.TreeViewColumn("Column 1")
col.pack_start(cell, True)
col.set_attributes(cell,text=0)
treeview.connect('row-activated', self.open_file)
treeview.append_column(col)
def open_file(self, button, *args):
Buttons().the_method(self, "foo")
class Buttons(object):
OPEN_IMAGE = gtk.image_new_from_stock(gtk.STOCK_ADD, gtk.ICON_SIZE_BUTTON)
CLOSED_IMAGE = gtk.image_new_from_stock(gtk.STOCK_REFRESH, gtk.ICON_SIZE_BUTTON)
def __init__(self):
self.button = gtk.Button() # THIS is the button to modify
self.hbox = gtk.HBox()
self.hbox.pack_start(self.button, False)
self.button.set_image(self.OPEN_IMAGE)
self.button.connect('clicked', self.the_method, "plop")
self.toggled = True
def the_method(self, button, filename):
print filename
print vars(self)
if self.toggled:
self.button.set_image(self.CLOSED_IMAGE)
self.toggled = False
else:
self.button.set_image(self.OPEN_IMAGE)
self.toggled = True
class GUI(object):
def delete_event(self, widget, event, data=None):
gtk.main_quit()
return False
def __init__(self):
self.window = gtk.Window()
self.window.set_size_request(100, 150)
self.window.connect("delete_event", self.delete_event)
vbox = gtk.VBox()
vbox.pack_start(Buttons().hbox, False, False, 1)
vbox.pack_start(Lister().hbox)
self.window.add(vbox)
self.window.show_all()
return
def main():
gtk.main()
if __name__ == "__main__":
GUI()
main()
I strongly disagree with user1146332 answer. This is not a GTK+ issue, nor a strong design issue, just an object oriented programming issue. The cause of your bug is that you call the_method like this:
Buttons().the_method(self, "foo")
This can't work, because you're mixing up two different fundamental things: a class, and an instance of a class. When you call Buttons(), you're creating a new instance of the Buttons class. Thus, as this class is not a singleton, you're in fact creating a new instance, with a new GtkButton, and end up not interacting with the button you previously created.
The solution here is to make the Lister object aware of what it needs to modify, which means storing around the Buttons instance you previously created, for example in self.button, and calling the_method on it.
self.button.the_method("foo")
Here's a slightly modified version of your code. The important thing is that the Lister instance is now aware of the Buttons instance it needs to modify.
import gtk
class Lister(object):
def __init__(self, button):
self.hbox = gtk.HBox()
self.button = button
liststore = gtk.ListStore(str)
liststore.append(["foo"])
liststore.append(["bar"])
treeview = gtk.TreeView(liststore)
self.hbox.pack_start(treeview, False)
cell = gtk.CellRendererText()
col = gtk.TreeViewColumn("Column 1")
col.pack_start(cell, True)
col.set_attributes(cell,text=0)
treeview.connect('row-activated', self.open_file)
treeview.append_column(col)
def open_file(self, button, *args):
self.button.the_method("foo")
class Buttons(object):
OPEN_IMAGE = gtk.image_new_from_stock(gtk.STOCK_ADD, gtk.ICON_SIZE_BUTTON)
CLOSED_IMAGE = gtk.image_new_from_stock(gtk.STOCK_REFRESH, gtk.ICON_SIZE_BUTTON)
def __init__(self):
self.button = gtk.Button() # THIS is the button to modify
self.hbox = gtk.HBox()
self.hbox.pack_start(self.button, False)
self.button.set_image(self.OPEN_IMAGE)
self.button.connect('clicked', self.the_method, "plop")
self.toggled = True
def the_method(self, filename):
print filename
print vars(self)
if self.toggled:
self.button.set_image(self.CLOSED_IMAGE)
self.toggled = False
else:
self.button.set_image(self.OPEN_IMAGE)
self.toggled = True
class GUI(object):
def delete_event(self, widget, event, data=None):
gtk.main_quit()
return False
def __init__(self):
self.window = gtk.Window()
self.window.set_size_request(100, 150)
self.window.connect("delete_event", self.delete_event)
vbox = gtk.VBox()
buttons = Buttons()
vbox.pack_start(buttons.hbox, False, False, 1)
vbox.pack_start(Lister(buttons).hbox)
self.window.add(vbox)
self.window.show_all()
return
def main():
gtk.main()
if __name__ == "__main__":
GUI()
main()
However, there's still lots of room for improvement. I suggest you don't use the __init__ function to create your widgets, but a create method that will return the toplevel widget of your widget tree. This is because you can't return anything in __init__, so it's easier to use a different method instead of raising exceptions there.
b = Buttons()
vbox.pack_start(b.create(), False, False, 1)
l = Lister(b)
vbox.pack_start(l.create(), False, False, 1)
Other improvement might be (sorry, i'm using the C naming here for GTK classes/functions, which I know better than the python one):
using a GtkToggleButton instead of tracking the button state yourself
using gtk_button_set_use_stock to tell the button to interpret the label you will set in the button as the stock id for the button (this may print the associated text too, not sure about this)
switching to GTK 3 (uses pyGObject), as this is GTK 2 code (uses pyGTK), unless you want Windows compatibility
See you on linuxfr :-)
First of all i don't know anything about python but i have some experiences with gtk+ and i'm more or less familiar with its concepts.
The first thing i noticed is that you define a class called GUI and two separate classes called Buttons and Lister. For me such approach makes only sense if you design the two last mentioned classes in a way that they are a kind of (composite) widget theirselves. So that you can instantiate them at a higher level for example in the GUI class. This would be a generic approach and makes perfectly sense if you want to reuse these new widgets.
The way you did it doesn't make sense to me. From what i have gathered so far the actual aim of Buttons and Lister is to populate your main application window with widgets, to connect callbacks to signals of those widgets and to define these callbacks as methods.
I think you limit the flexibility of gtk if you make it this way. For example you connect signals to callbacks at a point where in principle you aren't able to access all the widgets of your interface. In contrast, I prefer a common place in the code at which i connect signals to callbacks and at which i can principally pass all widgets of interest to a specific callback.
In fact one often have to act upon several widgets from inside a callback. So you have to consider to implement the callbacks as methods of your GUI class where they can principally access all elements of your user interface.
Also you should consider to design your interface with glade. That way your code would be much more legible.
Supplement (after some code pushing):
import gtk
class GUI(object):
OPEN_IMAGE = gtk.image_new_from_stock(gtk.STOCK_ADD, gtk.ICON_SIZE_BUTTON)
CLOSED_IMAGE = gtk.image_new_from_stock(gtk.STOCK_REFRESH, gtk.ICON_SIZE_BUTTON)
toggled = True
def __init__(self):
self.window = gtk.Window()
self.window.set_size_request(100, 150)
self.window.connect("delete_event", gtk.main_quit)
vbox = gtk.VBox()
self.button = gtk.Button() # THIS is the button to modify
self.button.set_image(self.OPEN_IMAGE)
liststore = gtk.ListStore(str)
liststore.append(["foo"])
liststore.append(["bar"])
self.treeview = gtk.TreeView(liststore)
cell = gtk.CellRendererText()
col = gtk.TreeViewColumn("Column 1")
col.pack_start(cell, True)
col.set_attributes(cell,text=0)
self.treeview.append_column(col)
vbox.pack_start(self.button, False, False, 1)
vbox.pack_start(self.treeview, False, False, 1)
self.treeview.connect('row-activated', self.the_method_wrapper, "plop")
self.button.connect('clicked', self.the_method, "plop")
self.window.add(vbox)
self.window.show_all()
return
def the_method_wrapper(self, button, *args):
self.the_method(self, "foo")
def the_method(self, button, filename):
print filename
print vars(self)
if self.toggled:
self.button.set_image(self.CLOSED_IMAGE)
self.toggled = False
else:
self.button.set_image(self.OPEN_IMAGE)
self.toggled = True
def main():
gtk.main()
if __name__ == "__main__":
GUI()
main()
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.