Add new TabControls inside another TabControl - python

I have a Main TabControl (Cronaca). Inside I have a second TabControl (Incident).
I would like to insert a third new TabControl called "Example" into Incident. The new Tabcontrol "Example" will have to contain elements such as those comboboxes (those that were previously contained in Incident, then remove them from Incident). How can I do?
Can you show me this simple code? I know, I have already plugged a Tabcontrol into another Tabcontrol, but I am currently confused and in the early stages of Pyhon. Help will be useful to me
P.S: OPTIONAL: My code is probably written in an unordered way. If it is possible, can some good person also make order in the staves? (the staves that come before and the staves that come after). Thank you
from tkinter import *
from tkinter import ttk
import tkinter as tk
window=Tk()
window.attributes('-zoomed', True)
window.configure(bg='#f3f2f2')
style = ttk.Style(window)
style.theme_use('clam')
#######################
tabControl = ttk.Notebook(window, style='Custom.TNotebook', width=700, height=320)
cronaca = ttk.Notebook(tabControl)
politica = ttk.Notebook(tabControl)
gossip = ttk.Notebook(tabControl)
tabControl.add(cronaca, text ='Cronaca')
tabControl.add(politica, text ='Politica')
tabControl.add(gossip, text ='Gossip')
tabControl.place(x=1, y=1)
#CRONACA
a = ttk.Frame(cronaca)
canvas = tk.Canvas(a)
scrollbar = ttk.Scrollbar(a, orient="vertical", command=canvas.yview)
scrollable_frame = ttk.Frame(canvas, width = 500, height = 500)
scrollable_frame.bind(
"<Configure>",
lambda e: canvas.configure(
scrollregion=canvas.bbox("all")
)
)
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)
#Incidente
a.pack()
cronaca.add(a, text="Incidente")
combo1=ttk.Combobox(scrollable_frame, width = 18)
combo1.place(x=20, y=20)
combo1['value'] = ["text1", "text2"]
combo2=ttk.Combobox(scrollable_frame, width = 18)
combo2.place(x=20, y=80)
combo2['value'] = ["text1", "text2"]
combo3=ttk.Combobox(scrollable_frame, width = 18)
combo3.place(x=20, y=140)
combo3['value'] = ["text1", "text2"]
combo4=ttk.Combobox(scrollable_frame, width = 18)
combo4.place(x=20, y=200)
combo4['value'] = ["text1", "text2"]
canvas.pack(side="left", fill="both", expand=True)
scrollbar.pack(side="right", fill="y")
b = ttk.Frame(cronaca)
cronaca.add(b, text="Microcriminalità")
c = ttk.Frame(cronaca)
cronaca.add(c, text="Criminalità")
d = ttk.Frame(cronaca)
cronaca.add(d, text="Disagi")
#tab 2
c = ttk.Frame(politica)
d = ttk.Frame(politica)
window.mainloop()

You can create another Notebook inside "Incidente" tab and put the scrollable frame inside a "Example" tab inside the new Notebook.
...
#CRONACA
#-- create a Notebook widget inside "cronaca"
incident = ttk.Notebook(cronaca)
#-- add the notebook into the "Incidente" tab
cronaca.add(incident, text="Incidente")
#Incidente
#-- create the scrollable frame inside the "Incidente" tab instead
a = ttk.Frame(incident)
#-- add the scrollable frame into a tab named "Example" inside "Incident" notebook
incident.add(a, text="Example")
...
Below is the updated code:
# avoid using wildcard import
#from tkinter import *
from tkinter import ttk
import tkinter as tk
window = tk.Tk() # changed from Tk() to tk.Tk()
window.attributes('-zoomed', True)
window.configure(bg='#f3f2f2')
style = ttk.Style(window)
style.theme_use('clam')
#######################
tabControl = ttk.Notebook(window, style='Custom.TNotebook', width=700, height=320)
cronaca = ttk.Notebook(tabControl)
politica = ttk.Notebook(tabControl)
gossip = ttk.Notebook(tabControl)
tabControl.add(cronaca, text ='Cronaca')
tabControl.add(politica, text ='Politica')
tabControl.add(gossip, text ='Gossip')
tabControl.place(x=1, y=1) # suggest to use pack() instead of place()
#CRONACA
#-- create a Notebook widget inside "cronaca"
incident = ttk.Notebook(cronaca)
#-- add the notebook into the "Incidente" tab
cronaca.add(incident, text="Incidente")
#Incidente
#-- create the scrollable frame inside the "Incident" notebook instead
a = ttk.Frame(incident)
#-- add the scrollable frame into a tab named "Example" inside "Incident" notebook
incident.add(a, text="Example")
canvas = tk.Canvas(a)
scrollbar = ttk.Scrollbar(a, orient="vertical", command=canvas.yview)
scrollable_frame = ttk.Frame(canvas, width = 500, height = 500)
scrollable_frame.bind(
"<Configure>",
lambda e: canvas.configure(
scrollregion=canvas.bbox("all")
)
)
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)
combo1=ttk.Combobox(scrollable_frame, width = 18)
combo1.place(x=20, y=20)
combo1['value'] = ["text1", "text2"]
combo2=ttk.Combobox(scrollable_frame, width = 18)
combo2.place(x=20, y=80)
combo2['value'] = ["text1", "text2"]
combo3=ttk.Combobox(scrollable_frame, width = 18)
combo3.place(x=20, y=140)
combo3['value'] = ["text1", "text2"]
combo4=ttk.Combobox(scrollable_frame, width = 18)
combo4.place(x=20, y=200)
combo4['value'] = ["text1", "text2"]
canvas.pack(side="left", fill="both", expand=True)
scrollbar.pack(side="right", fill="y")
b = ttk.Frame(cronaca)
cronaca.add(b, text="Microcriminalità")
c = ttk.Frame(cronaca)
cronaca.add(c, text="Criminalità")
d = ttk.Frame(cronaca)
cronaca.add(d, text="Disagi")
#tab 2
c = ttk.Frame(politica)
d = ttk.Frame(politica)
window.mainloop()

Related

Tkinter scrollbar not moving [duplicate]

This question already has answers here:
Adding a scrollbar to a group of widgets in Tkinter
(3 answers)
Closed 4 months ago.
I have a bunch of checkboxes instantiated in Tkinter, and I would like to scroll through the window because all of them cannot be fit in one frame. I see the scrollbar, but there is no effect on using it, and the window stays stationary. How can I fix it? This is my code -
root = Tk()
scroll = Scrollbar(root)
scroll.pack(fill=Y,side=RIGHT)
l = []
for checkBoxName in all_files:
var = IntVar()
c = Checkbutton(root, text=checkBoxName, variable=var, onvalue=1, offvalue=0)
c.pack()
l.append(var)
root.mainloop()
After some searches from the internet, I found what you need.
Note: Everything below is not mine, all the source I will put below.
So, this is what you need:
# Create A Main frame
main_frame = Frame(root)
main_frame.pack(fill=BOTH, expand=1)
# Create Frame for X Scrollbar
sec = Frame(main_frame)
sec.pack(fill=X, side=BOTTOM)
# Create A Canvas
my_canvas = Canvas(main_frame)
my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
# Add A Scrollbars to Canvas
scrollbar = ttk.Scrollbar(main_frame, orient=VERTICAL, command=my_canvas.yview)
scrollbar.pack(side=RIGHT, fill=Y)
# Configure the canvas
my_canvas.configure(yscrollcommand=scrollbar.set)
my_canvas.bind("<Configure>", lambda e: my_canvas.config(scrollregion=my_canvas.bbox(ALL)))
# Create Another Frame INSIDE the Canvas
second_frame = Frame(my_canvas)
# Add that New Frame a Window In The Canvas
my_canvas.create_window((0, 0), window=second_frame, anchor="nw")
and the full code is:
from tkinter import *
from tkinter import ttk
all_files = [str(i) for i in range(100)] # your list
root = Tk()
# Create A Main frame
main_frame = Frame(root)
main_frame.pack(fill=BOTH, expand=1)
# Create Frame for X Scrollbar
sec = Frame(main_frame)
sec.pack(fill=X, side=BOTTOM)
# Create A Canvas
my_canvas = Canvas(main_frame)
my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
# Add A Scrollbars to Canvas
scrollbar = ttk.Scrollbar(main_frame, orient=VERTICAL, command=my_canvas.yview)
scrollbar.pack(side=RIGHT, fill=Y)
# Configure the canvas
my_canvas.configure(yscrollcommand=scrollbar.set)
my_canvas.bind("<Configure>", lambda e: my_canvas.config(scrollregion=my_canvas.bbox(ALL)))
# Create Another Frame INSIDE the Canvas
second_frame = Frame(my_canvas)
# Add that New Frame a Window In The Canvas
my_canvas.create_window((0, 0), window=second_frame, anchor="nw")
#==========
l = []
for checkBoxName in all_files:
var = IntVar()
c = Checkbutton(second_frame, text=checkBoxName, variable=var, onvalue=1, offvalue=0)
c.pack()
l.append(var)
#==========
root.mainloop()
There is also an another shorter way:
from tkinter import *
from tkinter.tix import *
all_files = [str(i) for i in range(100)] # your list
root = Tk()
frame = Frame(width="500",height="500")
frame.pack()
swin = ScrolledWindow(frame, width=500, height=500)
swin.pack()
win = swin.window
#==========
l = []
for checkBoxName in all_files:
var = IntVar()
c = Checkbutton(win, text=checkBoxName, variable=var, onvalue=1, offvalue=0)
c.pack()
l.append(var)
#==========
root.mainloop()
To be honest, I'm not too good at tkinter, and I just have a little experience about it, so I don't really understand how they could make this code.
Sources:
First Way
Video Tutorial (1st way)
Another Way

Create scrollbar in tKinter without displacing widgets to the left (python)

I'm creating a program by learning from youtube tutorials (I'm a complete beginner) and I have come to some difficulties. This time, I'm trying to create a scrollbar, and I want my widgets to stay on the center of my window, not the left (I'm following the Codemy.com tutorial on scrollbars).
Here is the current aspect of my program:
with scrollbar
And here is how I want it to look:
without scrollbar
This is my code right now:
import tkinter as tk
root = tk.Tk()
root.geometry("600x400")
my_canvas = tk.Canvas(root)
my_canvas.pack(side = "left", fill = "both", expand = 1)
my_scrollbar = tk.Scrollbar(root, orient = "vertical", command = my_canvas.yview)
my_scrollbar.pack(side = "right", fill = "y")
my_canvas.configure(yscrollcommand = my_scrollbar.set)
my_canvas.bind("<Configure>", lambda e: my_canvas.configure(scrollregion = my_canvas.bbox("all")))
my_frame = tk.Frame(my_canvas)
for i in range(100):
my_label = tk.Label(my_frame, text = "Label")
my_label.pack()
my_canvas.create_window((0,0), window = my_frame, anchor = "nw")
root.mainloop()
Include width = 600, anchor = "nw" in my_canvas declaration.
my_canvas.create_window((0,0), window = my_frame, width = 600, anchor = "nw")

How to resize the width of the canvas dynamically

I have this code here. Like you see if the text in one of the button is long, it will not all apper. Is there a solution to resize the width of the canvas which is now defined equal to 300 so that it will show all the text in in the buttons. I don't want to do it manually because in the futur the text will be get from an external file and the data can change.
Any ideas
from tkinter import *
from tkinter.ttk import *
from tkinter import messagebox
from time import strftime
import csv
import xmlrpc.client as xmlrpclib
root = Tk()
frame = Frame(root)
container = Frame(root)
canvas = Canvas(container, borderwidth = 0, highlightthickness = 0, width=300, height=500, bg = "white")
#scrollbar = Scrollbar(container, orient="vertical", command=canvas.yview)
vertibar=Scrollbar(
container,
orient=VERTICAL
)
vertibar.pack(side=RIGHT,fill=Y)
vertibar.config(command=canvas.yview)
horibar=Scrollbar(
container,
orient=HORIZONTAL
)
horibar.pack(side=BOTTOM,fill=X)
horibar.config(command=canvas.xview)
scrollable_frame = Frame(canvas)
# setting the minimum size of the root window
root.geometry("300x650")
# Adding widgets to the root window
Label(root, text='my app',
font=('Verdana', 15)).pack(pady=10)
# tell the canvas how large the frame will be, so that it knows how much it can scroll:
scrollable_frame.bind(
"<Configure>",
lambda e: canvas.configure(
scrollregion=canvas.bbox("all")
)
)
frame_id =canvas.create_window((0, 0), window=scrollable_frame, anchor='nw')
canvas.bind("<Configure>",canvas.itemconfig(frame_id, width=canvas.winfo_reqwidth()))
#canvas.configure(yscrollcommand=scrollbar.set)
canvas.config(
xscrollcommand=horibar.set,
yscrollcommand=vertibar.set
)
# rechner_full = str(rechner[row])
# print(rechner_full)
Button(scrollable_frame, text="text1").pack(fill="both", side="top")
Button(scrollable_frame, text="text2").pack(fill="both", side="top")
Button(scrollable_frame, text="text3").pack(fill="both", side="top")
Button(scrollable_frame, text="longtexxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxt").pack(fill="both", side="top")
# print(button.cget('text'))
container.pack()
canvas.pack(side="left", fill="both")
#scrollbar.pack(side="right", fill="both")
# Button for closing
exit_button = Button(root, text="Beenden", command=root.destroy)
exit_button.pack(pady=20)
root.mainloop()
Since scrollable_frame will be resized to show the longest button, so you can expand canvas inside the callback bound to <Configure> event on scrollable_frame:
...
scrollable_frame = Frame(canvas)
frame_id =canvas.create_window((0, 0), window=scrollable_frame, anchor='nw')
def on_frame_resized(event):
canvas_width = canvas.winfo_reqwidth()
if event.width > canvas_width:
# expand canvas to the width of scrollable_frame
canvas.configure(width=event.width)
else:
# expand scrollable_frame to the width of canvas
canvas.itemconfigure(frame_id, width=canvas_width)
canvas.configure(scrollregion=canvas.bbox("all"))
# tell the canvas how large the frame will be, so that it knows how much it can scroll:
scrollable_frame.bind("<Configure>", on_frame_resized)
...
However you need to remove root.geometry(...) because it will block the main window from expanding due to resize of canvas. Also you need to remove canvas.bind("<Configure>", ...) because it will mess up the work done by on_frame_resized().
...
#root.geometry("300x650")
...
#canvas.bind("<Configure>",canvas.itemconfig(frame_id, width=canvas.winfo_reqwidth()))
...

Why isn't this frame in tkinter centered correctly?

I want this entry bar and other contents I'll add to the frame later to be centred correctly, I received this code that supposedly should work but it isn't.
import tkinter as tk
import math
import time
root = tk.Tk()
root.geometry()
root.attributes("-fullscreen", True)
exit_button = tk.Button(root, text = "Exit", command = root.destroy)
exit_button.place(x=1506, y=0)
frame = tk.Frame(root)
main_entry = tk.Entry(root, width = 100, fg = "black")
main_entry.place(x=50, y=50)
frame.place(relx=.5,rely=.5, anchor='center')
root.mainloop()
As you can see the frame isn't centred so how can I fix this?
In order to achieve widget centering on a fullscreen I've had to use grid manager.
The code below works but the exact positioning requires some fiddling with frame padding.
frame padx = w/2-300 and pady = h/2-45 are arbitrary values found using a bit of trial and error.
import tkinter as tk
root = tk.Tk()
root.attributes( '-fullscreen', True )
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
frame = tk.Frame( root )
main_entry = tk.Entry( frame, width = 100 )
main_entry.grid( row = 0, column = 0, sticky = tk.NSEW )
frame.grid( row = 0, column = 0, padx = w/2-300, pady = h/2-45, sticky = tk.NSEW )
exit_button = tk.Button( frame, text = 'Exit', command = root.destroy )
exit_button.grid( row = 1, column = 0, sticky = tk.NSEW )
tk.mainloop()
Frame automatically changes size to size of objects inside Frame (when you use pack()) but you have nothing inside Frame. You put all widgets directly in root - so Frame has no size (width zero, height zero) and it is not visible.
When I use tk.Frame(root, bg='red', width=100, height=100) then I see small red frame in the center.
You have two problems:
(1) you put Entry in wrong parent - it has to be frame instead of root,
(2) you use place() which doesn't resize Frame to its children and it has size zero - so you don't see it. You would have to set size of Frame manully (ie. tk.Frame(..., width=100, height=100)) or you could use pack() and it will resize it automatically.
I add colors for backgrounds to see widgets. blue for window and red for frame.
import tkinter as tk
root = tk.Tk()
root['bg'] = 'blue'
root.attributes("-fullscreen", True)
exit_button = tk.Button(root, text="Exit", command=root.destroy)
exit_button.place(x=1506, y=0)
frame = tk.Frame(root, bg='red')
frame.place(relx=.5, rely=.5, anchor='center')
main_entry = tk.Entry(frame, width=100, fg="black")
main_entry.pack(padx=50, pady=50) # with external margins 50
root.mainloop()

Python tkinter grid layout problems

I'm creating a very simple UI using Tkinter and python, but I'm having trouble sizing GUI elements and using the grid format to place them correctly. Here's a first-order approximation of what I'm trying to have:
Here's the code I have so far. I keep getting close, but I don't think I really understand what I'm doing. Any help is much appreciated!
#User interface
root = Tk()
window_width = root.winfo_screenwidth()
window_height = root.winfo_screenheight()
root.geometry ("%dx%d"%(window_width,window_height))
menu_bar = Menu(root)
menu = Menu(menu_bar, tearoff=0)
menu.add_command(label="Open", command = open_file)
menu.add_command(label="Save", command = save)
menu.add_separator()
menu.add_command(label="Quit", command = exit)
menu_bar.add_cascade(label="File",menu=menu)
root.config(menu=menu_bar)
#textbox is the window in which the code is written
textbox = Text(root, width=50, height = window_height/20+4)
#canvas is where the car will go
canvas_frame= Frame(root, width = window_width/1.5, height = window_height-200)
canvas_frame.configure(borderwidth=1.5,background='black')
canvas = Canvas(canvas_frame, width = window_width/1.5, height = window_height-200)
#console to print to
console = Text(root, width = int(window_width/1.5), height = 10)
run_button = Button(root, text = "Run", command = lambda:generate_program(textbox.get(1.0,END)))
clear_button = Button(root, text = "Clear text", command = clear)
#add them to frame
textbox.grid(row=0, column=0, rowspan=20, columnspan=10)
run_button.grid(row=21,column=0)
clear_button.grid(row=21,column=1)
canvas_frame.grid(row=0,rowspan=10,column=21,columnspan=25)
canvas.grid(row=0, rowspan=1, column=21, columnspan=25)
console.grid(row = 1, rowspan=1, column = 21, columnspan=25)
root.mainloop()
In my opinion, this is layout can be much easier with the pack geometry manager. One of the problems is that you are trying to make the width and the height of each widget fit in its place with rowspan and columspan options. Also, since canvasis inside a frame, you have to think that it is like inside a new window, so a simple call to canvas.grid() would be enough.
However, with pack() you just have to put textbox, run_button and clear_button inside a new frame:
left_frame = Frame(root)
textbox = Text(left_frame, ...)
run_button = Button(left_frame, ...)
clear_button = Button(left_frame, ...)
canvas_frame= Frame(root, ...)
canvas_frame.configure(borderwidth=1.5,background='black')
canvas = Canvas(canvas_frame, ...)
console = Text(root, ...)
left_frame.pack(side=LEFT)
textbox.pack()
run_button.pack(side=LEFT)
clear_button.pack()
canvas_frame.pack()
canvas.pack()
console.pack()

Categories

Resources