Running Python 3.4.2 and Tkinter 8.6 on a Raspberry Pi. I want to create a Text widget that fills a fixed sized frame using the grid layout manager.
If you run the code below, you'll see the Text widget doesn't fill the 800x600 frame. I realize I could set the Text's width and height attributes to fill the frame, but this would only work default font and wouldn't fill the frame exactly.
from tkinter import *
class Test(Tk):
def __init__(self):
super().__init__()
self.text = frameText(self)
self.geometry('{}x{}'.format(800, 600))
def frameText(frame, **kw):
ysb = Scrollbar(frame)
xsb = Scrollbar(frame, orient = HORIZONTAL)
text = Text(frame, **kw)
ysb.configure(command = text.yview)
xsb.configure(command = text.xview)
text.configure(yscrollcommand = ysb.set, xscrollcommand = xsb.set)
text.grid(row = 0, column = 0, sticky = N+E+S+W)
ysb.grid(row = 0, column = 1, sticky = N+S)
xsb.grid(row = 1, column = 0, sticky = E+W)
return text
if __name__ == '__main__':
Test().mainloop()
You need to configure the grid to give the row and column a nonzero weight so that they expand
from tkinter import *
class Test(Tk):
def __init__(self):
Tk.__init__(self)
self.grid_columnconfigure(0, weight=1)
self.grid_rowconfigure(0, weight=1)
self.text = frameText(self)
self.geometry('{}x{}'.format(800, 600))
def frameText(frame, **kw):
ysb = Scrollbar(frame)
xsb = Scrollbar(frame, orient = HORIZONTAL)
text = Text(frame, **kw)
ysb.configure(command = text.yview)
xsb.configure(command = text.xview)
text.configure(yscrollcommand = ysb.set, xscrollcommand = xsb.set)
text.grid(row = 0, column = 0, sticky = N+E+S+W)
ysb.grid(row = 0, column = 1, sticky = "ns")
xsb.grid(row = 1, column = 0, sticky = E+W)
return text
if __name__ == '__main__':
Test().mainloop()
Related
I want to add a horizontal scroll bar to the particular tree-view table since I have not used Tkinter before so please help!
import tkinter
def __create_tree_view(self):
""" Creates a TreeView Layout with req Headers """
style = it.Style()
style.configure("Custom.Treeview.Heading",foreground="green", relief="flat")
style.map("Custom.Treeview.Heading", relief=[('active','groove'),('pressed','sunken')])
style.configure('Treeview', rowheight=20)
#
self.tree_view = ttk.Treeview(self.right_frame, selectmode ='browse',\
style="Custom.Treeview")
self.tree_view.grid(row=1, column=1, sticky=tk.NSEW)
self.verticalscrollba = ttk.Scrollbar(self.right_frame, orient="vertical", \
command=self.tree_view.view)
self. verticalscrollbar.grid(row=1,column=1,sticky='nse')
self.tree_view.configure(yscrollcommand = self.verscrlbar.set)
# Defining number of columns
self.tree_view["columns"] = ("1", "2", "3", "4")
# Defining heading
self.tree_view['show'] = 'headings'
# Assigning the width and anchor to the respective columns
self.tree_view.column("1", width = int(self.window_width/5), anchor ='ca, stretch=False)
self.tree_view.column("2", width = int(self.window_width/4)-30, anchor ='ca, stretch=False)
self.tree_view.column("3", width = int(self.window_width/6)-30, anchor ='ca, stretch=False)
self.tree_view.column("4", width = int(self.window_width/3), anchor ='ca, stretch=False)
# Assigning the heading names to the respective columns
self.tree_view.heading("1", text ="Brand/Model/Type")
self.tree_view.heading("2", text ="Device_Id")
self.tree_view.heading("3", text ="Device_Ip")
self.tree_view.heading("4", text ="GUID")
where the brand is the brand of the device IP, is IP address and
so here in this code how to add a horizontal scroll bar without overwriting the last line of the treeview table I tried to add the scrollbar but it's displaying on the last row of the table it should display below the last row of the table
Try this an example.
import tkinter as tk
from tkinter import ttk
class Chrisdb1(tk.Frame):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.tvw_results = ttk.Treeview(self, style = 'mystyle.Treeview')
self.insert = self.tvw_results.insert
self.tvw_results.grid(row = 0, column = 0, sticky='nsew')
self.tvw_results.column("#0", minwidth = 1150)
self.tvw_results.heading('#0', text = 'Found results', anchor = tk.W)
# Scrollbars + attach scrollbars to TreeView
sb_vertical = tk.Scrollbar(self, orient = "vertical", command = self.tvw_results.yview)
sb_horizontal = tk.Scrollbar(self, orient = "horizontal", command = self.tvw_results.xview)
self.tvw_results.configure(yscrollcommand = sb_vertical.set, xscrollcommand = sb_horizontal.set)
sb_vertical.grid(row = 0, column = 1, sticky = "ns")
sb_horizontal.grid(row = 1, column = 0, sticky = "ew")
# Configure and position grid for TreeView
self.grid_rowconfigure(0, weight = 1)
self.grid_columnconfigure(0, weight = 1)
def main():
'''test code for Chrisdb1 class'''
root = tk.Tk()
cnt_treeview = Chrisdb1(root)
for i in range(20):
cnt_treeview.insert('', tk.END, text = f'Row {i}: Some very long texxxxxxxt.....'*6)
cnt_treeview.pack(expand=True, fill=tk.BOTH)
root.mainloop()
if __name__ == '__main__':
main()
i'm french so sorry for the translation and i'm beginner on python.
I have a items display problem in canvas. Refering to the following code, the script doesn't work properly if i want generate a high number of items into my canvas.
All items are not displayed properly
2)the script is freezing a little bit
I dont no why...Someone can help me please?
from tkinter import *
from tkinter import ttk
import tkinter as tk
class Main_frame(Frame):
# Init
def __init__(self, fenetre_principale=None):
tk.Frame.__init__(self, fenetre_principale)
self.grid(sticky = "news")
self.main_frame = tk.Frame(self, bg = "blue")
self.main_frame.grid(sticky = "news")
self.frame_canvas = tk.Frame(self.main_frame, bg = "yellow")
self.frame_canvas.grid(row = 2, column = 0, pady = 5, sticky="nw")
self.frame_canvas.grid_rowconfigure(0, weight=1)
self.frame_canvas.grid_columnconfigure(0, weight=1)
self.frame_canvas.grid_propagate(False)
self.canvas = tk.Canvas(self.frame_canvas, bg = "yellow")
self.canvas.grid(row = 0, column = 0, sticky='news')
self.vbar = tk.Scrollbar(self.frame_canvas, orient = "vertical", command = self.canvas.yview)
self.vbar.grid(row = 0, column = 1, sticky = "ns")
self.canvas.configure(yscrollcommand= self.vbar.set)
self.frame_buttons = tk.Frame(self.canvas, bg = "grey")
self.canvas.create_window((0, 0), window=self.frame_buttons, anchor="nw")
self.ajout()
def ajout(self):
self.bu_aj = tk.Button(self.main_frame, text = "Ajout", command = self.update_).grid(row = 0, column= 0, pady = 5, sticky="nw")
def update_(self):
for k in range(2000):
self.bu = tk.Button(self.frame_buttons, text = f"Test{k}")
self.bu.grid(row = k, column= 0, sticky="news")
self.frame_buttons.update_idletasks()
first5columns_width = sum([self.bu.winfo_width() for j in range(0, 15)])
first5rows_height = sum([self.bu.winfo_height() for i in range(0, 5)])
self.frame_canvas.config(width=first5columns_width + self.vbar.winfo_width(),height=first5rows_height)
self.canvas.config(scrollregion=self.canvas.bbox("all"))
print("ok")
if __name__ == "__main__":
root = tk.Tk()
root.grid_rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
root.title("Title")
interface = Main_frame(fenetre_principale=root)
interface.mainloop()
I cannot get x and y scrollbars to work in Tkinter with Python, although I have followed multiple examples:
How to add 2 scrollbars with tkinter in python 3.4
Adding a scrollbar to a group of widgets in tkinter
How to make a proper double scrollbar frame in tkinter
Vertical and Horizontal Scrollbars on Tkinter Widget
Scrolling a Canvas widget horizontally and vertically
The scrollbars appear, but do not activate when the window is smaller than the frame. How can I get this to work (see image below)?
Below is the minimal code that is producing my problem (Python 3.7)
import tkinter as tk
from tkinter import ttk
big_font = ("Arial", 50)
class DoubleScrollbarFrame(ttk.Frame):
def __init__(self,
parent,
*args,
**kwargs):
self.parent = parent
super().__init__(self.parent,
*args,
**kwargs)
#Set widgets to fill main window such that they are
#all the same size
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
self.create_widgets()
self.position_widgets()
def create_widgets(self):
self.canvas = tk.Canvas(self)
self.frame = ttk.Frame(self.canvas)
self.scroll_x = ttk.Scrollbar(self,
orient = tk.HORIZONTAL,
command = self.canvas.xview)
self.scroll_y = ttk.Scrollbar(self,
orient = tk.VERTICAL,
command = self.canvas.yview)
self.canvas.config(xscrollcommand = self.scroll_x.set,
yscrollcommand = self.scroll_y.set)
self.canvas.create_window((0,0),
window = self.frame,
anchor = 'nw')
self.frame.bind('<Configure>',
self.set_scrollregion)
self.sizegrip = ttk.Sizegrip(self)
#Test
self.test1 = tk.Label(self.frame,
text = 'Test 1',
font = big_font)
self.test2 = tk.Label(self.frame,
text = 'Test 2',
font = big_font)
self.test3 = tk.Label(self.frame,
text = 'Test 3',
font = big_font)
def position_widgets(self,
**kwargs):
self.test1.grid(row = 0,
column = 0,
sticky = 'w')
self.test2.grid(row = 1,
column = 0,
sticky = 'w')
self.test3.grid(row = 2,
column = 0,
sticky = 'w')
self.scroll_x.grid(row = 1,
column = 0,
sticky = 'ew')
self.scroll_y.grid(row = 0,
column = 1,
sticky = 'ns')
self.canvas.grid(row = 0,
column = 0,
sticky = 'nsew')
self.frame.grid(row = 0,
column = 0,
sticky = 'nsew')
self.sizegrip.grid(row = 1,
column = 1,
sticky = 'se')
def set_scrollregion(self,
event):
print('Frame Dimensions: {} x {}'.format(self.frame.winfo_width(),
self.frame.winfo_height()))
print('Canvas Dimensions: {} x {}'.format(self.canvas.winfo_width(),
self.canvas.winfo_height()))
self.canvas.configure(scrollregion = self.canvas.bbox('all'))
class MainApp(tk.Tk):
def __init__(self,
*args,
**kwargs):
super().__init__(*args,
**kwargs)
#Set widgets to fill main window such that they are
#all the same size
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
self.create_widgets()
self.position_widgets()
def create_widgets(self):
self.frame = DoubleScrollbarFrame(self)
def position_widgets(self):
self.frame.grid(row = 0,
column = 0,
sticky = 'nsew')
def exit(self):
self.destroy()
if __name__ == '__main__':
#Create GUI
root = MainApp()
#Run program
root.mainloop()
The problem is in these lines of code inside DoubleScrollbarFrame.position_widgets:
self.frame.grid(row = 0,
column = 0,
sticky = 'nsew')
This removes control of the widget from the canvas and gives control to grid. It is no longer a canvas object, so self.canvas.bbox("all") is returning (0, 0, 1, 1). If the scrollregion is set incorrectly, the scrollbars don't know how much to scroll.
The solution is simple: don't call grid on self.frame.
i'm trying to make this simple gui using grid layout where i have in one row a label an entry and a button, but for some reason the first button always takes the rowspan equal to the number of rows in previous column, even if i try to force it to have rowspan 1 it has no effect which makes me really confused.
import tkinter as tk
class MainApplication(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.grid()
#LABELS
self.l1 = tk.Label(self, text = "Source")
self.l1.grid(column = 0, row = 0, sticky = "E")
self.l2 = tk.Label(self, text = "Text files destination")
self.l2.grid(column = 0, row = 1, sticky = "E")
self.l3 = tk.Label(self, text = "Image files destination")
self.l3.grid(column = 0, row = 2, sticky = "E")
#ENTRIES
self.e1 = tk.Entry(self)
self.e1.grid(column = 1, row = 0)
self.e2 = tk.Entry(self)
self.e2.grid(column = 1, row = 1)
self.e3 = tk.Entry(self)
self.e3.grid(column = 1, row = 2)
#BUTTONS
self.b3 = tk.Button(text = "Select dir", command = self.cb2)
self.b3.grid(column = 2, row = 0)
self.b4 = tk.Button(text = "Select dir", command = self.cb2)
self.b4.grid(column = 2, row = 1)
self.b5 = tk.Button(text = "Select dir", command = self.cb2)
self.b5.grid(column = 2, row = 2)
if __name__ == "__main__":
root = tk.Tk()
app = MainApplication(root)
root.mainloop()
output:
http://i.imgur.com/AdWkHwi.png
You don't specify a parent for the buttons, so their parent is the root window. The labels and entries, on the other hand, have their parent attribute set to the frame. What happens is that in the root, the frame is in row zero, and the first button is in row zero, and the height of the row is determined by the height of the frame.
The solution is to make the parent of the buttons be the frame.
self.b3 = tk.Button(self, ...)
self.b4 = tk.Button(self, ...)
self.b5 = tk.Button(self, ...)
I'm trying to make a Tkinter window class that contains a canvas with a scrollbar based on the tkinter Toplevel class. When I run my code I don't receive any errors but the scrollbar in the window is disabled. The Frame or canvas that has the information wont stretch with the window when I stretch it manually after the program is running. Here is the bugged code:
class new_window(Toplevel):
def __init__(self,master):
Toplevel.__init__(self,master)
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
s = Scrollbar(self, orient = VERTICAL)
s.grid(row = 0, column = 1, sticky = NS)
self.can = Canvas(self, yscrollcommand=s.set)
self.can.grid(row = 0, column = 0, sticky = N+S+E+W)
self.win = Frame(self.can)
self.can.create_window(0,0, window = self.win, anchor = NW)
s.config(command = self.can.yview)
size = (self.win.winfo_reqwidth(), self.win.winfo_reqheight())
self.can.config(scrollregion="0 0 %s %s" % size)
self.win.update_idletasks()
self.ca.configure(scrollregion = (1,1,win.winfo_width(),win.winfo_height()))
def create(self):
for i in range (100):
i = Label(self.win, text = str(i))
i.grid()
root = Tk()
win = new_window(root)
win.create()
root.mainloop()
It was working fine before I decided to implement classes:
from Tkinter import *
root = Tk()
window = Toplevel()
window.grid_rowconfigure(0, weight=1)
window.grid_columnconfigure(0, weight=1)
s = Scrollbar(window, orient = VERTICAL)
s.grid(row = 6, column = 1, sticky = NS)
can = Canvas(window, width = 1600, height = 700, yscrollcommand=s.set)
can.grid(row = 6, column = 0, sticky = NSEW)
win = Frame(can)
can.create_window(0,0, window = win, anchor = NW)
s.config(command = can.yview)
for i in range(100):
lbl = Label(win, text = str(i))
lbl.grid()
win.update_idletasks()
can.configure(scrollregion = (1,1,win.winfo_width(),win.winfo_height()))
root.mainloop()
Im not sure where I went wrong in the transition, any help would be greatly appreciated.
I think the issue is coming from here:
self.win.update_idletasks()
self.ca.configure(scrollregion = (1,1,win.winfo_width(),win.winfo_height()))
This is inside the initialization function, when it should be updating after the create function is called. There's still probably a more efficient way to structure this, but this should work in the meantime:
from Tkinter import *
class new_window(Toplevel):
def __init__(self,master):
Toplevel.__init__(self,master)
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
s = Scrollbar(self, orient = VERTICAL)
s.grid(row = 0, column = 1, sticky = NS)
self.can = Canvas(self, yscrollcommand=s.set)
self.can.grid(row = 0, column = 0, sticky = N+S+E+W)
self.win = Frame(self.can)
self.can.create_window(0,0, window = self.win, anchor = NW)
s.config(command = self.can.yview)
size = (self.win.winfo_reqwidth(), self.win.winfo_reqheight())
self.can.config(scrollregion="0 0 %s %s" % size)
def create(self):
for i in range (100):
i = Label(self.win, text = str(i))
i.grid()
self.win.update_idletasks()
self.can.configure(scrollregion = (1,1,self.win.winfo_width(),self.win.winfo_height()))
root = Tk()
win = new_window(root)
win.create()
root.mainloop()