I've been trying out panedWindows for my app layout, but I'm having issues when the window resizes. This is the layout I've started out with:
The panes drag as I want them too, but I want to specify what panes expand to fill the root window, and which ones stay a specific width. For example, when I drag the window to the right or left, the pane on the expanding size extends to fill the extra space. I want only the centre pane to expand, and the right and left only when the sash is dragged:
like this:
When the panes were managed with the pack geometry manager, I could tell the edge panes to stay a specific width, and tell the centre pane to expand. How can I achieve a similar layout with paned windows?
Heres a minimal working example:
import tkinter
root = tkinter.Tk()
root.geometry("480x200+200+200")
root.title("Paned Window Example")
main = tkinter.PanedWindow()
main.pack(expand = 1, fill = "both")
pane1 = tkinter.Frame(width = 90, bg = "red")
pane2 = tkinter.Frame(width = 310, bg = "blue")
pane3 = tkinter.Frame(width = 90, bg = "red")
for pane in pane1, pane2, pane3 : main.add(pane)
root.mainloop()
You can use the stretch option when adding the panes to the PanedWindow. It takes the following values: 'always', 'first', 'last', 'middle', and 'never'.
You can get a more complete description in the tcl/tk documentation.
In your case, use 'never' for the side panes and 'always' for the middle one:
import tkinter
root = tkinter.Tk()
root.geometry("480x200+200+200")
root.title("Paned Window Example")
main = tkinter.PanedWindow()
main.pack(expand=True, fill="both")
pane1 = tkinter.Frame(width=90, bg="red")
pane2 = tkinter.Frame(width=310, bg="blue")
pane3 = tkinter.Frame(width=90, bg="red")
main.add(pane1, stretch='never')
main.add(pane2, stretch='always')
main.add(pane3, stretch='never')
root.mainloop()
Note that the above solution works only for tkinter.PanedWindow and not for ttk version of the widget. The .add() method of ttk.PanedWindow accepts only one option: weight. But we can achieve the same result by setting the side panes' weight to 0 and the middle pane's to 1:
import tkinter
from tkinter import ttk
root = tkinter.Tk()
root.geometry("480x200+200+200")
root.title("Paned Window Example")
main = ttk.PanedWindow(orient='horizontal')
main.pack(expand=True, fill="both")
pane1 = tkinter.Frame(width=90, bg="red")
pane2 = tkinter.Frame(width=310, bg="blue")
pane3 = tkinter.Frame(width=90, bg="red")
main.add(pane1, weight=0)
main.add(pane2, weight=1)
main.add(pane3, weight=0)
root.mainloop()
Related
I am trying to position my buttons using the grid manager, by altering the column and row arguments of the .grid() function. However, whenever I input values > 1, there seems to be no change in position of my widgets. Why is this?
import tkinter as tk
window = tk.Tk()
window.geometry("500x500")
window.rowconfigure(0,weight=1)
window.columnconfigure(0,weight=1)
f1 = tk.Frame(window,bg="black")
f1.grid(row=0,column=0,sticky="nsew")
btn1 = tk.Button(f1,text="button")
btn1.grid(row=0,column=0,padx=5,pady=5)
lbl = tk.Label(f1,text="label")
lbl.grid(row=3,column=3)
window.mainloop()
EDIT: I found the solution! My xorg settings were all wacky because I have an ultrawide monitor, and it had no idea what size (and therefore dpi) my monitor was. Explicitly setting the display and font dpi in X's settings fixed the rendering in all GUI's.
ORIGINAL:
When I run any tkinter program, many of the widgets render at around 1/2 size, especially text. Why is this happening? My window manager is Window Maker, and I'm running the latest version of Tcl/Tk.
Any help will be greatly appreciated!
My code:
import tkinter as tk
window = tk.Tk()
label = tk.Label(text="Name")
entry = tk.Entry()
button = tk.Button(text="Submit")
label.pack()
entry.pack()
button.pack()
window.mainloop()
Window manager: Window Maker 0.95.0
Tk: tk 8.6.10-2
Screenshot:
In tkinter you can only change the size of a label with the font atribute, and same goes for the text inside the button. The button size can be changed with the width and height atribute.
from tkinter import *
window = Tk()
label = Label(text="Name", font='Helvetica 15')
entry = Entry()
button = Button(text="Submit",font ='Helvetica 15', height="3", width="10")
label.pack(pady = 5) # add pady inside the pack
entry.pack()
button.pack(pady = 5)
window.mainloop()
I'm learning Tkinter at the moment. From my book, I get the following code for producing a simple vertical scrollbar:
from tkinter import * # Import tkinter
class ScrollText:
def __init__(self):
window = Tk() # Create a window
window.title("Scroll Text Demo") # Set title
frame1 = Frame(window)
frame1.pack()
scrollbar = Scrollbar(frame1)
scrollbar.pack(side = RIGHT, fill = Y)
text = Text(frame1, width = 40, height = 10, wrap = WORD,
yscrollcommand = scrollbar.set)
text.pack()
scrollbar.config(command = text.yview)
window.mainloop() # Create an event loop
ScrollText() # Create GUI
which produces the following nice output:
enter image description here
However, when I then try to change this code in the obvious way to get a horizontal scrollbar, it's producing a weird output. Here's the code I'm using
from tkinter import * # Import tkinter
class ScrollText:
def __init__(self):
window = Tk() # Create a window
window.title("Scroll Text Demo") # Set title
frame1 = Frame(window)
frame1.pack()
scrollbar = Scrollbar(frame1)
scrollbar.pack(side = BOTTOM, fill = X)
text = Text(frame1, width = 40, height = 10, wrap = WORD,
xscrollcommand = scrollbar.set)
text.pack()
scrollbar.config(command = text.xview)
window.mainloop() # Create an event loop
ScrollText() # Create GUI
and here's what I get when I run this:
enter image description here
You're assigning horizontal scrolling, xscrollcommand, to a vertical scrollbar. You need to modify Scrollbar's orient option to 'horizontal' which is by default 'vertical'.
Try replacing:
scrollbar = Scrollbar(frame1)
with:
scrollbar = Scrollbar(frame1, orient='horizontal')
here is a picture of what i want to be:
scrollbar
Actual code:
lb = Listbox(self.master, width=120, height=6)
scrollbar = Scrollbar(self.master, orient="vertical",command=lb.yview)
scrollbar.pack(side="right", fill="y")
lb.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=lb.yview)
lb.place(x=5,y=5)
Thanks!
You can create a new frame with listbox and scrollbar in it:
from tkinter import *
root = Tk()
root.geometry('500x300')
frame = Frame(root)
frame.place(x = 5, y = 5) # Position of where you would place your listbox
lb = Listbox(frame, width=70, height=6)
lb.pack(side = 'left',fill = 'y' )
scrollbar = Scrollbar(frame, orient="vertical",command=lb.yview)
scrollbar.pack(side="right", fill="y")
lb.config(yscrollcommand=scrollbar.set)
for i in range(10):
lb.insert(END, 'test'+str(i))
root.mainloop()
or since you're using place (which is not recommended), you can simply calculate the position of the scrollbar. grid would be the best layout manager in this case.
The problem is if you use only the 'place' positioning, the scrollbar doesn't appear.
The solution is to make two frames - one master frame with a widget scrollbar and
a second frame inside the master frame, where you can get the listbox. The frames can be positioned with place, the widget inside the frames with pack or grid.
Below is my source code, what works perfectly.
from tkinter import *
root = Tk()
root.geometry('500x300')
frame1 = Frame(root)
frame1.place(x = 10, y = 5,width=100,height=100) # Position of where you would place your listbox
frame1a=Frame(master=frame1)
frame1a.place(x=0,y=0,height=100,width=100)
lb = Listbox(frame1a, width=50, height=6)
lb.grid(row=0,column=0 )
scrollbar = Scrollbar(frame1, orient="vertical",command=lb.yview)
scrollbar.pack(side="right", fill="y")
lb.config(yscrollcommand=scrollbar.set)
for i in range(10):
lb.insert(END, 'test'+str(i))
root.mainloop()
I am new to tkinter and python3. I have worked on creating a scrollbar for a frame that is a child of a canvas which is also a child of Toplevel(). The scrollbar buttons function well but the bar/box itself stretches from top to bottom and cannot move. Furthermore, using the scroll buttons, the user can scroll way beyond the content (where there nothing to view).
Here is the code.
#! /usr/bin/env python3
from tkinter import *
from filegroups import typeGroups
app = Tk()
types_window = Toplevel(app)
types_window.wm_title('Types')
yscrollbar = Scrollbar(types_window, orient=VERTICAL)
yscrollbar.grid(row=0, column=1, sticky=N+S)
canvas = Canvas(types_window,
width = 300,
height = 500,
yscrollcommand=yscrollbar.set)
canvas.grid(row=0,column=0)
canvas.config(scrollregion=canvas.bbox("all"))
yscrollbar.config(command=canvas.yview)
frame = Frame(canvas)
canvas.create_window(0,0,anchor=NW,window=frame)
for key in sorted(typeGroups.keys()):
options_frame = LabelFrame(frame, text=key)
options_frame.grid(padx=5, pady=10)
for item in typeGroups[key]:
item_button = Checkbutton(options_frame,
text=item)
item_button.grid()
app.mainloop()
You need to update the canvas scrollregion after filling the frame with labels by adding these two lines just before app.mainloop():
canvas.update_idletasks()
canvas.config(scrollregion=canvas.bbox("all"))
The call to update_idletasks is needed to ensure that the canvas content is updated before we ask for the bounding box.