I want to make a lot of notebook tabs, and I want to put them in canvas and to add a horizontal scrollbar so that I can scroll trough them.
I set the canvas size, but canvas size keep changing when I add new tab. Also, scrollbar does not work, can you tell me what am I doing wrong?
The program does not show me any error. This is the code:
from tkinter import *
from tkinter import ttk
myApp = Tk()
myApp.title(" Program ")
myApp.geometry("900x500")
CanvasTabs = Canvas(myApp, width=50, height=50)
CanvasTabs.grid(row=0,column=0)
tabs = ttk.Notebook(CanvasTabs, width=100, height=100)
tab1 = ttk.Frame(tabs)
tabs.add(tab1,text=" Tab 1 ")
tab2 = ttk.Frame(tabs)
tabs.add(tab2,text=" Tab 2 ")
tab3 = ttk.Frame(tabs)
tabs.add(tab3,text=" Tab 3 ")
tab4 = ttk.Frame(tabs)
tabs.add(tab4,text=" Tab 4 ")
hbar=Scrollbar(CanvasTabs,orient=HORIZONTAL)
hbar.pack(side=TOP,fill=X)
hbar.config(command=CanvasTabs.xview)
CanvasTabs.config(xscrollcommand=hbar.set)
tabs.pack(expand=1, fill="both")
myApp.mainloop()
I code a widget to fix the problem. Here is a real solution:
https://github.com/muhammeteminturgut/ttkScrollableNotebook
# -*- coding: utf-8 -*-
# Copyright (c) Muhammet Emin TURGUT 2020
# For license see LICENSE
from tkinter import *
from tkinter import ttk
class ScrollableNotebook(ttk.Frame):
def __init__(self,parent,*args,**kwargs):
ttk.Frame.__init__(self, parent, *args)
self.xLocation = 0
self.notebookContent = ttk.Notebook(self,**kwargs)
self.notebookContent.pack(fill="both", expand=True)
self.notebookTab = ttk.Notebook(self,**kwargs)
self.notebookTab.bind("<<NotebookTabChanged>>",self._tabChanger)
slideFrame = ttk.Frame(self)
slideFrame.place(relx=1.0, x=0, y=1, anchor=NE)
leftArrow = ttk.Label(slideFrame, text="\u25c0")
leftArrow.bind("<1>",self._leftSlide)
leftArrow.pack(side=LEFT)
rightArrow = ttk.Label(slideFrame, text=" \u25b6")
rightArrow.bind("<1>",self._rightSlide)
rightArrow.pack(side=RIGHT)
self.notebookContent.bind( "<Configure>", self._resetSlide)
def _tabChanger(self,event):
self.notebookContent.select(self.notebookTab.index("current"))
def _rightSlide(self,event):
if self.notebookTab.winfo_width()>self.notebookContent.winfo_width()-30:
if (self.notebookContent.winfo_width()-(self.notebookTab.winfo_width()+self.notebookTab.winfo_x()))<=35:
self.xLocation-=20
self.notebookTab.place(x=self.xLocation,y=0)
def _leftSlide(self,event):
if not self.notebookTab.winfo_x()== 0:
self.xLocation+=20
self.notebookTab.place(x=self.xLocation,y=0)
def _resetSlide(self,event):
self.notebookTab.place(x=0,y=0)
self.xLocation = 0
def add(self,frame,**kwargs):
if len(self.notebookTab.winfo_children())!=0:
self.notebookContent.add(frame, text="",state="hidden")
else:
self.notebookContent.add(frame, text="")
self.notebookTab.add(ttk.Frame(self.notebookTab),**kwargs)
def forget(self,tab_id):
self.notebookContent.forget(tab_id)
self.notebookTab.forget(tab_id)
def hide(self,tab_id):
self.notebookContent.hide(tab_id)
self.notebookTab.hide(tab_id)
def identify(self,x, y):
return self.notebookTab.identify(x,y)
def index(self,tab_id):
return self.notebookTab.index(tab_id)
def insert(self,pos,frame, **kwargs):
self.notebookContent.insert(pos,frame, **kwargs)
self.notebookTab.insert(pos,frame,**kwargs)
def select(self,tab_id):
self.notebookContent.select(tab_id)
self.notebookTab.select(tab_id)
def tab(self,tab_id, option=None, **kwargs):
return self.notebookTab.tab(tab_id, option=None, **kwargs)
def tabs(self):
return self.notebookContent.tabs()
def enable_traversal(self):
self.notebookContent.enable_traversal()
self.notebookTab.enable_traversal()
Taking Bryan's example on this post and modifying it to include your Notebook code we get a functioning scrollbar that will allow you to scroll over your Notebook widget if it exceeds the limit of the window.
Bryan's example uses the pack() geometry manager however I personally find grid() easier to visualize so I replace pack with grid() in my example.
UPDATE:
import tkinter as tk
import tkinter.ttk as ttk
class Example(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.canvas = tk.Canvas(self, borderwidth=0)
self.frame = tk.Frame(self.canvas)
self.vsb = tk.Scrollbar(self, orient="horizontal", command=self.canvas.xview)
self.vsb.grid(row=1, column=0, sticky="nsew")
self.canvas.configure(xscrollcommand=self.vsb.set)
self.canvas.grid(row=0, column=0, sticky="nsew")
self.canvas.create_window((3,2), window=self.frame, anchor="nw", tags="self.frame")
self.frame.bind("<Configure>", self.frame_configure)
self.populate()
def populate(self):
tabs = ttk.Notebook(self.frame, width=100, height=100)
for tab in range(50):
tabs.add(ttk.Frame(tabs), text=" Tab {} ".format(tab))
tabs.grid(row=0, column=0, sticky="ew")
def frame_configure(self, event):
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
if __name__ == "__main__":
app = Example()
app.mainloop()
Updated results:
Per your request in the comments here is a Non-OOP example:
import tkinter as tk
import tkinter.ttk as ttk
root = tk.Tk()
canvas = tk.Canvas(root, borderwidth=0)
frame = tk.Frame(canvas)
vsb = tk.Scrollbar(root, orient="horizontal", command=canvas.xview)
vsb.grid(row=1, column=0, sticky="nsew")
canvas.configure(xscrollcommand=vsb.set)
canvas.grid(row=0, column=0, sticky="nsew")
canvas.create_window((3,2), window=frame, anchor="nw", tags="frame")
tabs = ttk.Notebook(frame, width=100, height=100)
for tab in range(50):
tabs.add(ttk.Frame(tabs), text=" Tab {} ".format(tab))
tabs.grid(row=0, column=0, sticky="ew")
def frame_configure(event):
global canvas
canvas.configure(scrollregion=canvas.bbox("all"))
frame.bind("<Configure>", frame_configure)
root.mainloop()
Related
Hi guys i'm having trouble with a scrollbar, in the photo you can see the grey box that is a simple listbox, how to put the scrollbar in that red specific position, and not in the right or bottom end of the screen just like te normal scollbar? Thanks!
adding code:
from tkinter import *
from ctypes import windll
def inserisci_spesa():
global lista_spese
global testo_nuova_spesa
if testo_nuova_spesa.get() != "":
lista_spese.insert(0,testo_nuova_spesa.get())
def invio_aggiungi_spesa(e):
window.bind("<Return>",illumina_aggiungi_spesa)
def illumina_aggiungi_spesa(e):
bottone_inserisci_spesa.config(bg="#052b4d")
window.after(200,illumina_aggiungi_spesa2)
def illumina_aggiungi_spesa2():
bottone_inserisci_spesa.config(bg="#1e476b")
window.after(0,inserisci_spesa)
def invio_descrivi_spesa(e):
window.bind("<Return>",illumina_descrivi_spesa)
def illumina_descrivi_spesa(e):
global bottone_inserisci_descrizione
bottone_inserisci_descrizione.config(bg="#052b4d")
window.after(200,illumina_descrivi_spesa2)
def illumina_descrivi_spesa2():
global bottone_inserisci_descrizione
bottone_inserisci_descrizione.config(bg="#1e476b")
windll.shcore.SetProcessDpiAwareness(1)
window = Tk()
frame = Frame (window)
frame.pack(padx=150, pady=150)
window.geometry("1500x770")
window.title ("Gestione spese")
window.call('wm', 'iconphoto', window._w, PhotoImage(file="trasparente.png"))
sfondo = PhotoImage(file="soldi.png")
etichetta_sfondo = Label(window,image=sfondo)
etichetta_sfondo.place(x=0,y=0)
testo_nuova_spesa = Entry(window,borderwidth=5,font=("Ink Free",20),width=9,bg="#f2f2f2")
testo_nuova_spesa.place(x=36,y=80)
testo_nuova_spesa.bind("<FocusIn>",invio_aggiungi_spesa)
descrizione_testo_nuova_spesa = Label(window,text="Nuova spesa",bg="#64d981",font=("Ink Free",19),relief="solid",borderwidth=1)
descrizione_testo_nuova_spesa.place(x=40,y=28)
testo_descrivi_spesa = Entry(window,borderwidth=5,font=("Ink Free",20),width=22,bg="#f2f2f2")
testo_descrivi_spesa.place(x=300,y=80)
testo_descrivi_spesa.bind("<FocusIn>",invio_descrivi_spesa)
descrizione_testo_descrivi_spesa = Label(window,text="Descrizione",bg="#64d981",font=("Ink Free",19),relief="solid",borderwidth=1)
descrizione_testo_descrivi_spesa.place(x=304.5,y=28)
bottone_inserisci_spesa = Button(window,text="Inserisci",font=("Ink Free",15),bg="#1e476b",fg="white",activebackground="#052b4d",activeforeground="white",command=inserisci_spesa)
bottone_inserisci_spesa.place(x=36,y=140)
bottone_inserisci_descrizione = Button(window,text="Inserisci",font=("Ink Free",15),bg="#1e476b",fg="white",activebackground="#052b4d",activeforeground="white")
bottone_inserisci_descrizione.place(x=300,y=140)
lista_spese = Listbox(frame)
lista_spese.pack(side=LEFT)
lista_spese.configure(font=('Courier 20 '), width=21, height=9, bg="#4a4a4a", fg="#dedede",relief="solid",borderwidth=4)
etichetta_lista_spese = Label(window,text="Lista delle spese",bg="#64d981",font=("Ink Free",19),relief="solid",borderwidth=1)
etichetta_lista_spese.place(x=720,y=270)
scrollbar = Scrollbar(frame,command=lista_spese.yview)
scrollbar.pack(side=RIGHT,fill=Y)
lista_spese.config(yscrollcommand=scrollbar.set)
window.mainloop()
Simply put both (Listbox and Scrollbar) in the same Frame to group them.
Minimal working code
import tkinter as tk
root = tk.Tk()
root['bg'] = '#ff8080'
# - create -
frame = tk.Frame(root)
frame.pack(padx=150, pady=150)
listbox = tk.Listbox(frame)
listbox.pack(side='left', fill='both', expand=True)
scrollbar = tk.Scrollbar(frame, orient='vertical', command=listbox.yview)
scrollbar.pack(side='right', fill='y')
#scrollbar.pack(side='left', fill='y') # `left` also works
listbox.config(yscrollcommand=scrollbar.set)
# - add some values to listbox for scrolling -
for i in range(50):
listbox.insert('end', str(i))
# - start -
root.mainloop()
Result:
EDIT:
You may also use Frame to create own widget ScrolledListbox and then you can reuse it many times.
import tkinter as tk
class ScrolledListbox(tk.Frame):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.listbox = tk.Listbox(self)
self.listbox.pack(side='left', fill='both', expand=True)
self.scrollbar = tk.Scrollbar(self, orient='vertical', command=self.listbox.yview)
self.scrollbar.pack(side='right', fill='y')
#self.scrollbar.pack(side='left', fill='y') # `left` also works
self.listbox.config(yscrollcommand=self.scrollbar.set)
# - main -
root = tk.Tk()
root['bg'] = '#ff8080'
# - create -
lb1 = ScrolledListbox(root)
lb1.pack(side='left', fill='both', expand=True, padx=25, pady=25)
lb2 = ScrolledListbox(root)
lb2.pack(side='left', fill='both', expand=True, padx=25, pady=25)
lb3 = ScrolledListbox(root)
lb3.pack(side='left', fill='both', expand=True, padx=25, pady=25)
# - add some values to listbox for scrolling -
for i in range(50):
lb1.listbox.insert('end', str(i))
lb2.listbox.insert('end', str(i+100))
lb3.listbox.insert('end', str(i+200))
# - start -
root.mainloop()
I'm trying to make a sub window for configuration settings. But the text in the sub window is invisible. I am reading correctly but I cannot see the text. Below is my sample code with the problem:
import tkinter as tk
from tkinter import ttk
from tkinter import Menu
class Frames:
def __init__(self):
self.port_com = None
def main_frame(self, win):
# Main Frame
main = ttk.LabelFrame(win, text="")
main.grid(column=0, row=0, sticky="WENS", padx=10, pady=10)
return main
def dut_configuration_frame(self, win):
# Configuration Frame
dut_config_frame = ttk.LabelFrame(win, text="Config")
dut_config_frame.grid(column=0, row=0, sticky='NWS')
# Port COM
ttk.Label(dut_config_frame, text="Port COM").grid(column=0, row=0)
self.port_com = tk.StringVar()
ttk.Entry(dut_config_frame, width=12, textvariable=self.port_com).grid(column=0, row=1, sticky=tk.EW)
self.port_com.set(value="COM7")
print(self.port_com.get())
class ConfigFrames:
def __init__(self):
self.port_com = None
def main_frame(self, win):
# Main Frame
main = ttk.LabelFrame(win, text="")
main.grid(column=0, row=0, sticky="WENS", padx=10, pady=10)
return main
def configuration_frame(self, win):
# Configuration Frame
dut_config_frame = ttk.LabelFrame(win, text="Config")
dut_config_frame.grid(column=0, row=0, sticky='NWS')
# Port COM
ttk.Label(dut_config_frame, text="Port COM").grid(column=0, row=0)
self.port_com = tk.StringVar()
ttk.Entry(dut_config_frame, width=12, textvariable=self.port_com).grid(column=0, row=1, sticky=tk.EW)
self.port_com.set(value="COM5")
print(self.port_com.get())
def menu_bar(win):
def _config():
config_frame = ConfigFrames()
config_window = tk.Tk()
config_window.title("Sub window")
config_window.geometry("200x200")
config_window.resizable(0, 0)
main = config_frame.main_frame(config_window)
config_frame.configuration_frame(main)
config_window.mainloop()
# Menu
menuBar = Menu(win)
win.config(menu=menuBar)
settingsMenu = Menu(menuBar, tearoff=0)
settingsMenu.add_command(label="Config", command=_config)
menuBar.add_cascade(label="Settings", menu=settingsMenu)
frames = Frames()
win = tk.Tk()
win.title("Main window")
win.geometry("200x200")
win.resizable(0, 0)
menu_bar(win)
main = frames.main_frame(win)
frames.dut_configuration_frame(win)
win.mainloop()
As you can see in main window it is visible, but in sub window it is invisible.
And printing in console is correct:
When i want to layout my frames the Labels don't show up. I can't seem to solve it. For some reason it does show op the entries that i've made. Can somebody please help me.
import tkinter as tk
from tkinter import *
from tkinter import filedialog
from PIL import ImageTk, Image
class main_screen():
def __init__(self, master):
self.master = master
self.master.title("Roboframe")
self.master.geometry("650x650")
self.create_frames()
self.create_entries()
def create_frames(self):
self.top = Frame(self.master).grid(row=0,column=0)
self.bottom = Frame(self.master).grid(row=0, column=0)
self.set_paths = LabelFrame(self.master, text="Set Path", padx=10, pady=10).grid(row=0,column=0)
self.options = LabelFrame(self.master, text="Options", padx=10, pady=10).grid(row=0,column=0)
def create_entries(self):
python_path = StringVar(self.set_paths, "C:/Python37/python.exe")
robot_path = StringVar(self.set_paths, "C:/ws/cmge.automation/RobotFrameworkCMGE")
self.set_path_python = Entry(self.set_paths, width=60, textvariable=python_path).grid(row=0,column=0)
self.set_path_robot = Entry(self.set_paths, width=60, textvariable=robot_path).grid(row=1, column=0)
root = tk.Tk()
app = main_screen(root)
root.mainloop()
Output of code shown above
The thing i'm rewritting the code for because it is a mess
The second picture i've also made myself. But the code is a giant mess.
You have to make an object of the widget not the grid function of the widget. Grid returns nothing so naturally none of them will show up. I believe this is what you wanted:
import tkinter as tk
from tkinter import *
from tkinter import filedialog
from PIL import ImageTk, Image
class main_screen():
def __init__(self, master):
self.master = master
self.master.title("Roboframe")
self.master.geometry("650x650")
self.create_frames()
self.create_entries()
def create_frames(self):
# you have grided all of your frames and label frames on the same row and column
self.top = Frame(self.master)
self.top.grid(row=0,column=0)
self.bottom = Frame(self.master)
self.bottom.grid(row=0, column=0)
self.set_paths = LabelFrame(self.master, text="Set Path", padx=10, pady=10)
self.set_paths.grid(row=0,column=0)
self.options = LabelFrame(self.master, text="Options", padx=10, pady=10)
self.options.grid(row=0,column=0)
def create_entries(self):
python_path = StringVar(self.set_paths, "C:/Python37/python.exe")
robot_path = StringVar(self.set_paths, "C:/ws/cmge.automation/RobotFrameworkCMGE")
self.set_path_python = Entry(self.set_paths, width=60, textvariable=python_path)
self.set_path_python.grid(row=0,column=0)
self.set_path_robot = Entry(self.set_paths, width=60, textvariable=robot_path)
self.set_path_robot.grid(row=1, column=0)
root = tk.Tk()
app = main_screen(root)
root.mainloop()
Also a couple of things:
You have imported tkinter twice in two different ways, just use one of them
You are griding both of the LabelFrames and frames on the same row and column but since "self.options" does not contain anything it is not going to show up, be careful later on
This will display both LabelFrames, the second with a dummy Entry widget.
import tkinter as tk
from tkinter import *
from tkinter import filedialog
from PIL import ImageTk, Image
class main_screen():
def __init__(self, master):
self.master = master
self.master.title("Roboframe")
self.master.geometry("650x650")
self.create_frames()
self.create_entries()
def create_frames(self):
self.set_paths = LabelFrame(self.master, text="Set Path", padx=10, pady=10)
self.set_paths.grid(row=0,column=0)
self.options = LabelFrame(self.master, text="Options", padx=10, pady=10)
self.options.grid(row=1,column=0)
def create_entries(self):
python_path = StringVar(self.set_paths, "C:/Python37/python.exe")
robot_path = StringVar(self.set_paths, "C:/ws/cmge.automation/RobotFrameworkCMGE")
self.set_path_python = Entry(self.set_paths, width=60, textvariable=python_path)
self.set_path_python.grid(row=0,column=0)
self.set_path_robot = Entry(self.set_paths, width=60, textvariable=robot_path)
self.set_path_robot.grid(row=1, column=0)
self.test = Entry(self.options, width=60)
self.test.grid(row=1, column=1)
root = tk.Tk()
app = main_screen(root)
root.mainloop()
I'm creating a console that has a single Label packing into a frame. I'm using pack and not grid or place.
Currently the label is placed into the frame, and is configured to expand. However the expansion doesn't stretch to expand to every edge. Also, when the window is resized, the Label widget doesn't resize together with the frame.
#!/usr/bin/python3
import tkinter as tk
import time as t
class app(tk.Tk):
def __init__(self):
super().__init__()
self.canvas=tk.Canvas(self,bg="black")
self.frame=tk.Canvas(self.canvas,bg="black")
self.scrollbar=tk.Scrollbar(self,orient="vertical",command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.scrollbar.set)
self.title("label insert and scrollbar test")
self.geometry("900x400")
self.scrollbar.pack(side=tk.RIGHT,fill=tk.Y)
self.canvas.pack(fill=tk.X,expand=1)
self.frame.pack(fill=tk.X,expand=1)
self.canvas.create_window((0,0),anchor='n',window=self.frame)
self.frame.bind("<Configure>",self.onFrameConfigure)
def onFrameConfigure(self,event):
pass
def run(self):
ntime=t.asctime(t.gmtime())
n=tk.Label(self.frame,text=ntime,anchor="nw",justify=tk.LEFT)
n.config(bg="black",fg="white",font=("Courier",12))
n.pack(fill=tk.BOTH,expand=1,padx=0)
self.after(800,self.run)
if __name__=="__main__":
m=app()
m.run()
m.mainloop()
How do i get this to work such that the Label fills the entire frame?
There are a couple of reason why your frame is not expanding to fit the canvas. You have a few issues that we need to correct first.
self.frame=tk.Canvas(self.canvas,bg="black") is not actually a frame.
onFrameConfigure is not doing anything and this is an important part to getting the frame to resize.
self.frame.bind() should be self.canvas.bind() as we are using the even that the canvas has changed in some way to trigger the function to resize the frame.
self.canvas.create_window((0,0),anchor='n',window=self.frame) needs a tag set for the frame so we can configure it in the function later.
See below code example and let me know if you have any questions.
import tkinter as tk
import time as t
class App(tk.Tk):
def __init__(self):
super().__init__()
self.canvas = tk.Canvas(self, bg="black")
self.frame = tk.Frame(self.canvas, bg="black")
self.scrollbar = tk.Scrollbar(self, orient="vertical", command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.scrollbar.set)
self.title("label insert and scrollbar test")
self.geometry("900x400")
self.scrollbar.pack(side='right', fill='y')
self.canvas.pack(fill='x', expand=True)
self.frame.pack(fill='x', expand=True)
self.canvas.create_window((0, 0), anchor='n', window=self.frame, tags='my_frame')
self.canvas.bind("<Configure>", self.onFrameConfigure)
self.run()
def onFrameConfigure(self, event):
width = event.width
self.canvas.itemconfigure(my_frame, width=width)
self.canvas.config(scrollregion=self.canvas.bbox("all"))
def run(self):
ntime = t.asctime(t.gmtime())
n = tk.Label(self.frame, text=ntime, anchor="nw", justify='left')
n.config(bg="black", fg="white", font=("Courier", 12))
n.pack(fill='both', expand=True, padx=0)
self.after(800, self.run)
if __name__ == "__main__":
App().mainloop()
Update:
The below example changes some background colors and padding so you can see where exactly things are expanding.
import tkinter as tk
import time as t
class App(tk.Tk):
def __init__(self):
super().__init__()
self.canvas = tk.Canvas(self, bg="black")
self.frame = tk.Frame(self.canvas, bg='darkblue',)
self.scrollbar = tk.Scrollbar(self, orient="vertical", command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.scrollbar.set)
self.title("label insert and scrollbar test")
self.geometry("900x400")
self.scrollbar.pack(side='right', fill='y')
self.canvas.pack(fill='x', expand=True)
self.frame.pack(fill='both', expand=True)
self.canvas.create_window((0, 0), anchor='n', window=self.frame, tags='my_frame')
self.canvas.bind("<Configure>", self.on_canvas_configure)
self.run()
def on_canvas_configure(self, event):
self.canvas.itemconfigure("my_frame", width=event.width, height=event.height)
self.canvas.config(scrollregion=self.canvas.bbox("all"))
def run(self):
ntime = t.asctime(t.gmtime())
tk.Label(self.frame, bg='black', fg='white', text=ntime,
font=("Courier", 12)).pack(fill='both', expand=True , padx=5, pady=5)
self.canvas.config(scrollregion=self.canvas.bbox('all'))
self.after(800, self.run)
if __name__ == "__main__":
App().mainloop()
Example results:
Just to answer my question:
'''
self.canvas.pack(fill=tk.BOTH,expand=1)
self.frame.pack(fill=tk.BOTH,expand=1,padx=1)
'''
Would expand both canvas and frame to fit the entire window. The original code only had fill=tk.X, which expands only in the X direction. For some reason i could have sworn the documentation said tk.X meant in both directions.
I want to create a GUI program base on tkinter. One of the widgets is Text. I want to add a horizontal scrollbar in it, but it didn't work.
Where did I make a mistake?
from Tkinter import *
import tkFont
class DpWin(object):
def run(self):
root=Tk()
root.geometry('768x612')
title='dp'
root.title(title)
xscrollbar = Scrollbar(root, orient=HORIZONTAL)
xscrollbar.pack(side=BOTTOM, fill=X)
yscrollbar = Scrollbar(root)
yscrollbar.pack(side=RIGHT, fill=Y)
text = Text(root,xscrollcommand=xscrollbar.set,yscrollcommand=yscrollbar.set)
text.pack()
xscrollbar.config(command=text.xview)
yscrollbar.config(command=text.yview)
text.insert(END,'a'*999)
mainloop()
def start(self):
self.b_start.config(state=DISABLED)
self.b_stop.config(state=ACTIVE)
def stop(self):
self.b_stop.config(state=DISABLED)
self.b_start.config(state=ACTIVE)
if __name__=='__main__':
win=DpWin()
win.run()
I've modified your code according to here. There are 2 main differences.
I made it so the textbox doesn't wrap. If you wrap text, there is nothing for the horizontal scrollbar to scroll to.
I used the grid geometry manager on a frame to keep the scrollbars and text widgets together. The advantage to using .grid is that you actually get scrollbars which are the correct width/height (something you can't achieve with pack).
...
from Tkinter import *
import tkFont
class DpWin(object):
def run(self):
root=Tk()
root.geometry('768x612')
title='dp'
root.title(title)
f = Frame(root)
f.pack()
xscrollbar = Scrollbar(f, orient=HORIZONTAL)
xscrollbar.grid(row=1, column=0, sticky=N+S+E+W)
yscrollbar = Scrollbar(f)
yscrollbar.grid(row=0, column=1, sticky=N+S+E+W)
text = Text(f, wrap=NONE,
xscrollcommand=xscrollbar.set,
yscrollcommand=yscrollbar.set)
text.grid(row=0, column=0)
xscrollbar.config(command=text.xview)
yscrollbar.config(command=text.yview)
text.insert(END, 'a'*999)
mainloop()
def start(self):
self.b_start.config(state=DISABLED)
self.b_stop.config(state=ACTIVE)
def stop(self):
self.b_stop.config(state=DISABLED)
self.b_start.config(state=ACTIVE)
if __name__=='__main__':
win=DpWin()
win.run()
There is one comment regarding making both x and y scrollbars work within the pack framework. Here is a minimal example:
import tkinter as tk
from tkinter import X, Y, BOTTOM, RIGHT, LEFT, Y, HORIZONTAL
class TextExample(tk.Frame):
def __init__(self, master=None):
super().__init__()
sy = tk.Scrollbar(self)
sx = tk.Scrollbar(self, orient=HORIZONTAL)
editor = tk.Text(self, height=500, width=300, wrap='none')
sx.pack(side=BOTTOM, fill=X)
sy.pack(side=RIGHT, fill=Y)
editor.pack(side=LEFT, fill=Y)
sy.config(command=editor.yview)
sx.config(command=editor.xview)
self.pack()
def main():
root = tk.Tk()
root.geometry("800x500+0+0")
app = TextExample(master=root)
root.mainloop()
if __name__ == '__main__':
main()