I have an Python3 Tkinter Programm. I have 3 Frames in the Main Window and in one Frame an canvas with scroll Option - now i want resitze the Canvas Area .
Now if i resize it moves the Scroll Bar for Y out the Window and the scrollbar for x works also not as expected (get bigger but slide area don't change)
How i Mange it to resize an Canvas in an grid Layout - The Window must be the same size , the Scrollbas must be updatet and the Canvas Plane must be bigger.
an excerpt from my code:
import tkinter as tk
def menu_build():
caninfo[0] += 10
cangui.configure(width = caninfo[0])
#cangui.configure(scrollregion=cangui.bbox("all"))
def gui():
master = tk.Tk()
master.title( "Easy Switch" )
master.geometry("480x320")
frametop = tk.Frame(master, bg="blue", bd=2)
frametop.grid(column=0,row=0)
frameex = tk.Frame(master, bg="yellow", bd=2)
frameex.grid(column=1,row=1)
framegui = tk.Frame(master, bg="red", bd=2)
framegui.grid(column=0, columnspan=2, row=1)
menu = tk.Menu(master)
master.config(menu=menu)
filemenu = tk.Menu(menu)
menu.add_cascade(label="Config", menu=filemenu)
filemenu.add_command(label="Resize",command=menu_build)
global cangui
cangui = tk.Canvas(framegui, width=385, height=250)
#caninfo = [385,250]
cangui.grid(row=1, column=2)
scroll_x = tk.Scrollbar(framegui, orient="horizontal", command=cangui.xview)
scroll_x.grid(row=2, column=2, sticky="ew")
scroll_y = tk.Scrollbar(framegui, orient="vertical", command=cangui.yview)
scroll_y.grid(row=1, column=3, sticky="ns")
cangui.configure(yscrollcommand=scroll_y.set,xscrollcommand=scroll_x.set)
cangui.configure(scrollregion=cangui.bbox("all"))
cwcb = tk.Checkbutton(framegui, text="ccw").grid(row=2,column=0)
cangui.create_arc(90,90,110,110,style=tk.PIESLICE,width=4,start=0,extent=300)
master.mainloop()
global caninfo
caninfo = [385,250]
if __name__ == "__main__":
gui()
no need to resize the canvas Area
wrote an extra funktion
win = [int(cangui.cget("width")),int(cangui.cget("height"))]
draw_xy = cangui.bbox("all")
swin = (min(0,draw_xy[0]),min(0,draw_xy[1]),max(draw_xy[2],win[0]),max(draw_xy[3],win[1]))
cangui.configure(scrollregion=swin)
reason: canvas.bbox("all") gives only the positon from most upper/left grafic and i want 0/0
Related
How to display a custom Tkinter window (with overrideredirect true) on top of other opened windows when clicking from the taskbar icon? My code below works (maximize not implemented yet) except when this Tkinter window is overlapped by other non-Tkinter windows. For instance, when this Tkinter window is situated below two windows (of other programs) and when called (by clicking the taskbar icon), it will take 2 clicks on that icon before this window will appear on top of those 2 windows. I want to bring my window automatically on top when its taskbar icon clicked.
I based my code from this answer and stitched this workaround for taskbar icon. I tried searching for any Tkinter code that deals on taskbar icon click event but found nothing.
import tkinter as tk
from tkinter import ttk
def get_pos(event):
global xwin
global ywin
xwin = event.x
ywin = event.y
def move_window(event):
root.geometry(f'+{event.x_root - xwin}+{event.y_root - ywin}')
def quit():
root.destroy()
#window contents
root = tk.Tk()
container = tk.Toplevel(root)
root.overrideredirect(True)
#default window dimension
root.geometry('350x150+200+200')
root.minsize(350, 150)
container.attributes("-alpha",0.0)
back_ground = "#2c2c2c"
#minimize btn binding
def onRootIconify(event): root.withdraw()
container.bind("<Unmap>", onRootIconify)
root.bind("<Unmap>", onRootIconify)
def onRootDeiconify(event): root.deiconify()
container.bind("<Map>", onRootDeiconify)
root.bind("<Map>", onRootDeiconify)
#title bar
title_bar = tk.Frame(root, bg=back_ground, bd=1,
highlightcolor=back_ground,
highlightthickness=0)
#minimize btn
minimize_btn = tk.Button(title_bar, text='🗕', bg=back_ground, padx=5, pady=2,
bd=0, font="bold", fg='white', width=2,
activebackground="red",
activeforeground="white",
highlightthickness=0,
command=lambda: container.wm_state('iconic'))
#maximize btn
maximize_btn = tk.Button(title_bar, text='🗖', bg=back_ground, padx=5, pady=2,
bd=0, font="bold", fg='white', width=2,
activebackground="red",
activeforeground="white",
highlightthickness=0,
command=None)
#close btn
close_button = tk.Button(title_bar, text='🗙', bg=back_ground, padx=5, pady=2,
bd=0, font="bold", fg='white', width=2,
activebackground="red",
activeforeground="white",
highlightthickness=0,
command= quit)
#window title
title_window = "Untitled window"
title_name = tk.Label(title_bar, text=title_window, font="Arial 12", bg=back_ground, fg="white")
#main area of the window
window = tk.Frame(root, bg="white", highlightthickness=1, highlightbackground=back_ground)
txt = tk.Label(window, bg='white', text="Prototype window").pack(anchor="center")
# pack the widgets
title_bar.pack(fill='x', side=tk.TOP)
title_name.pack(side='left', padx=5)
close_button.pack(side='right')
maximize_btn.pack(side=tk.RIGHT)
minimize_btn.pack(side=tk.RIGHT)
window.pack(fill='both', expand=True, side=tk.TOP)
# bind title bar motion to the move window function
title_bar.bind("<B1-Motion>", move_window)
title_bar.bind("<Button-1>", get_pos)
#workaround to enable window dragging on window title text
title_name.bind("<B1-Motion>", move_window)
title_name.bind("<Button-1>", get_pos)
minimize_btn.bind('<Enter>', lambda x: minimize_btn.configure(bg='#777777'))
minimize_btn.bind('<Leave>', lambda x: minimize_btn.configure(bg=back_ground))
maximize_btn.bind('<Enter>', lambda x: maximize_btn.configure(bg='#777777'))
maximize_btn.bind('<Leave>', lambda x: maximize_btn.configure(bg=back_ground))
close_button.bind('<Enter>', lambda x: close_button.configure(bg='red'))
close_button.bind('<Leave>',lambda x: close_button.configure(bg=back_ground))
root.mainloop()
The custom window:
After looking for related answers and recommendations of Coder, I finally solved my problem. In my solution, I used the technique from this answer. My finished code does not use any invisible Tkinter window and heavily utilizes ctypes.windll (hence my code is only limited to Windows). The logic for minimize, maximize, and close window are finished as well.
I managed to solve the following:
No random taskbar icon glitches when minimizing/maximizing (results from wrapping invisible window)
No issues when bringing up the custom Tkinter window when behind other windows (like that of my problem of double-clicking the taskbar icon)
#https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowpos
#https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
import tkinter as tk
from tkinter import ttk
from ctypes import windll
def set_appwindow():
global hasstyle
GWL_EXSTYLE=-20
WS_EX_APPWINDOW=0x00040000
WS_EX_TOOLWINDOW=0x00000080
if not hasstyle:
hwnd = windll.user32.GetParent(root.winfo_id())
style = windll.user32.GetWindowLongW(hwnd, GWL_EXSTYLE)
style = style & ~WS_EX_TOOLWINDOW
style = style | WS_EX_APPWINDOW
res = windll.user32.SetWindowLongW(hwnd, GWL_EXSTYLE, style)
root.withdraw()
root.after(10, lambda:root.wm_deiconify())
hasstyle=True
def get_pos(event):
global xwin
global ywin
xwin = event.x
ywin = event.y
def move_window(event):
global previousPosition
root.geometry(f'+{event.x_root - xwin}+{event.y_root - ywin}')
previousPosition = [root.winfo_x(), root.winfo_y()]
def move_window_bindings(*args, status=True):
if status == True:
title_bar.bind("<B1-Motion>", move_window)
title_bar.bind("<Button-1>", get_pos)
title_name.bind("<B1-Motion>", move_window)
title_name.bind("<Button-1>", get_pos)
else:
title_bar.unbind("<B1-Motion>")
title_bar.unbind("<Button-1>")
title_name.unbind("<B1-Motion>")
title_name.unbind("<Button-1>")
def quit():
root.destroy()
#reference: https://programtalk.com/python-examples/ctypes.windll.user32.ShowWindow/
def minimize(hide=False):
hwnd = windll.user32.GetParent(root.winfo_id())
windll.user32.ShowWindow(hwnd, 0 if hide else 6)
def maximizeToggle():
global maximized
global previousPosition
if maximized == False:
#maximize current window
maximize_btn.config(text="❐")
hwnd = windll.user32.GetParent(root.winfo_id())
SWP_SHOWWINDOW = 0x40
windll.user32.SetWindowPos(hwnd, 0, 0, 0, int(root.winfo_screenwidth()), int(root.winfo_screenheight()-48),SWP_SHOWWINDOW)
maximized = True
move_window_bindings(status=False)
else:
#restore down window
maximize_btn.config(text="🗖")
hwnd = windll.user32.GetParent(root.winfo_id())
SWP_SHOWWINDOW = 0x40
windll.user32.SetWindowPos(hwnd, 0, previousPosition[0], previousPosition[1], int(root.minsize()[0]), int(root.minsize()[1]),SWP_SHOWWINDOW)
maximized = False
move_window_bindings(status=True)
#---------------------------------
root = tk.Tk()
root.overrideredirect(True)
#window details
maximized = False
back_ground = "#2c2c2c"
dimension = (300, 300)
#------------------------------
if len(dimension) == 0:
#default window dimension
x = (root.winfo_screenwidth()/2)-(350/2)
y = (root.winfo_screenheight()/2)-(250)
root.geometry(f'350x150+{int(x)}+{int(y)}')
root.minsize(350, 150)
dimension = (350, 150)
previousPosition = [int(x), int(y)]
else:
x = (root.winfo_screenwidth()/2)-(dimension[0]/2)
y = (root.winfo_screenheight()/2)-250
root.geometry(f'{dimension[0]}x{dimension[1]}+{int(x)}+{int(y)}')
root.minsize(dimension[0], dimension[1])
previousPosition = [int(x), int(y)]
#title bar
title_bar = tk.Frame(root, bg=back_ground, bd=1,
highlightcolor=back_ground,
highlightthickness=0)
#window title
title_window = "Untitled window"
title_name = tk.Label(title_bar, text=title_window,
font="Arial 12", bg=back_ground, fg="white")
#minimize btn
minimize_btn = tk.Button(title_bar, text='🗕', bg=back_ground, padx=5, pady=2,
bd=0, font="bold", fg='white', width=2,
activebackground="red",
activeforeground="white",
highlightthickness=0,
command=minimize)
#maximize btn
maximize_btn = tk.Button(title_bar, text='🗖', bg=back_ground, padx=5, pady=2,
bd=0, font="bold", fg='white', width=2,
activebackground="red",
activeforeground="white",
highlightthickness=0,
command=maximizeToggle)
#close btn
close_button = tk.Button(title_bar, text='🗙', bg=back_ground, padx=5, pady=2,
bd=0, font="bold", fg='white', width=2,
activebackground="red",
activeforeground="white",
highlightthickness=0,
command= quit)
#hover effect
minimize_btn.bind('<Enter>', lambda x: minimize_btn.configure(bg='#777777'))
minimize_btn.bind('<Leave>', lambda x: minimize_btn.configure(bg=back_ground))
maximize_btn.bind('<Enter>', lambda x: maximize_btn.configure(bg='#777777'))
maximize_btn.bind('<Leave>', lambda x: maximize_btn.configure(bg=back_ground))
close_button.bind('<Enter>', lambda x: close_button.configure(bg='red'))
close_button.bind('<Leave>',lambda x: close_button.configure(bg=back_ground))
#main area of the window
window = tk.Frame(root, bg="white", highlightthickness=1, highlightbackground=back_ground)
txt = tk.Label(window, bg='white', text="Prototype window").pack(anchor="center")
# pack the widgets
title_bar.pack(fill='x', side=tk.TOP)
title_name.pack(side='left', padx=5)
close_button.pack(side='right')
maximize_btn.pack(side=tk.RIGHT)
minimize_btn.pack(side=tk.RIGHT)
window.pack(fill='both', expand=True, side=tk.TOP)
move_window_bindings(status=True)
#ctype
hasstyle = False
root.update_idletasks()
root.withdraw()
set_appwindow()
root.mainloop()
Demo:
If someone can transform my code into a classful syntax, please comment since I have a hard time in doing so hehe. Code optimizations are very welcomed.
I am trying to display images in my game, which in time will correspond to rooms.
I have three main frames and I want to display images in the one called 'frame 3', but I am not unable to get the picture itself to display!
I made a method called RoomImages which is supposed to handle the roomImages. I have called this method in my constructormethod for the whole App class.
It displays no error messages and therefore I am unsure where the missing logic is.
I have attached a picture of what the output shows:
Output
import tkinter as tk
from Game import Game
from tkinter import messagebox
from PIL import ImageTk, Image
class App():
# Creates a Frame for the application
# and populates the GUI ...
def __init__(self, root):
#super().__init__(master=win)
self.game = Game()
#A menubar with the options Quit' which destroys the window
# and 'about' which displays a message box with the info from the method showAbout
menubar = tk.Menu()
menubar.add_command(label="Quit", command=root.destroy)
menubar.add_command(label="About", command=self.showAbout)
root.config(menu=menubar)
# Create two frames owned by the window root
# In order to use multiple layout managers, the frames
# cannot share a parent frame. Here both frames are owned
# by a top level instance root.
self.frame1 = tk.Frame(root, width=600, height=250, bg='WHITE', borderwidth=2)
self.frame1.pack_propagate(0) # Prevents resizing
self.frame2 = tk.Frame(root, width=600, height=150, bg='LIGHT GREY', borderwidth=2, padx=175)
self.frame2.grid_propagate(0) # Prevents resizing
self.frame3 = tk.Frame(root, width=600, height=250, bg='LIGHT BLUE', borderwidth=2, padx=275)
self.frame3.grid_propagate(0) # Prevents resizing
# This packs both frames into the root window ...
self.frame1.pack()
self.frame2.pack()
self.frame3.pack()
#image canvas for frame3 to display the current room
self.canvas_for_image = tk.Canvas(self.frame3, bg='LIGHT GREY', height=250, width=600, borderwidth=0, highlightthickness=0)
self.canvas_for_image.grid(row=0, column=0, sticky='nesw', padx=0, pady=0)
#self.canvas_for_image.pack(expand=YES, fill=BOTH)
self.frame3.columnconfigure(0, pad=5)
self.frame3.columnconfigure(1, pad=5)
self.frame3.rowconfigure(0, pad=5)
self.frame3.rowconfigure(1, pad=5)
#make a gridstructure for frame2 to be able to precisely place my buttons.
self.frame2.columnconfigure(0, pad=5)
self.frame2.columnconfigure(1, pad=5)
self.frame2.columnconfigure(2, pad=5)
self.frame2.columnconfigure(3, pad=5)
self.frame2.columnconfigure(4, pad=5)
self.frame2.columnconfigure(5, pad=5)
self.frame2.rowconfigure(0, pad=5)
self.frame2.rowconfigure(1, pad=5)
self.frame2.rowconfigure(2, pad=5)
self.frame2.rowconfigure(3, pad=5)
# Now add some useful widgets ...
self.textArea1 = tk.Label(self.frame1, text='')
self.textArea1.pack()
self.cmdArea = tk.Entry(self.frame2, text='')
self.cmdArea.grid(row = 3, column = 1)
self.buildGUI()
self.roomImages()
def showAbout(self):
"""uses the messagebox import to display info about the game"""
messagebox.showinfo("About", "A classic whodunnit where you have to find out who the murder is!")
def buildGUI(self):
self.doCmd = tk.Button(self.frame2, text='Run command',
fg='black', bg='blue',
command=self.doCommand)
self.doCmd.grid(row = 1, column = 1)
self.goDown = tk.Button(self.frame2, text='Down',
fg='black', bg='red',
command=self.processDownCommand)
self.goDown.grid(row=2, column=1)
self.goUp = tk.Button(self.frame2, text='Up',
fg='black', bg='red',
command=self.processUpCommand)
self.goUp.grid(row =0, column=1)
self.goLeft = tk.Button(self.frame2, text='Left',
fg='black', bg='red',
command=self.processLeftCommand)
self.goLeft.grid(row=1,column = 0)
self.goRight = tk.Button(self.frame2, text='Right',
fg='black', bg='red',
command=self.processRightCommand)
self.goRight.grid(row=1, column =2)
self.help = tk.Button(self.frame2, text='Help',
fg='black', bg='green',
command=self.processHelpCommand)
self.help.grid(row=1, column=4)
self.textArea1.configure(text=self.game.printWelcome())
def roomImages(self):
self.imageDict = {'apple': 'apple.png', 'banana': 'banana.png', 'bar': 'bar.png', 'cherries': 'cherries.png',
'grapes': 'grapes.png', 'lemon': 'lemon.png', 'melon': 'melon.png', 'orange': 'orange.png'}
self.apple = 'apple'
self.apple = f'images/{self.imageDict[self.apple]}'
#adding images
self.r1 = ImageTk.PhotoImage(Image.open(self.apple))
self.r1Label = tk.Label(self.frame3, image=self.r1)
def main():
win = tk.Tk() # Create a window
win.title("Adventure World with GUI") # Set window title
win.geometry("700x400") # Set window size
win.resizable(False, False) # Both x and y dimensions ...
# Create the GUI as a Frame
# and attach it to the window ...
myApp = App(win)
# Call the GUI mainloop ...
win.mainloop()
if __name__ == "__main__":
main()
Need your help guys once again, building a GUI project and need to make it dynamically so the button, labels, entry box, background, and everything will resize when I'm changing the window size and fitting to the new window size.
So far this is the code with working background resizing only,
but there is main screen with labels, buttons etc.. and add to that, I need to add more 8 buttons that each one opening new window, on the new windows I will have to make them dynamically too... here an example of code:
from tkinter import *
from PIL import Image, ImageTk
class MainScreen(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.configure(background="black")
self.image = Image.open("bg.jpg")
# label for the background image
self.background = Label(self)
self.background.place(x=0, y=0)
self.bind('<Configure>', self._resize_image)
# Label 1 welcome message
Label(root, text="Welcome", bg="#12355F", fg="white",
font="tahoma 12 bold") .place(x=10, y=10)
# Label 2
Label(root, text="Add:", bg="#164883", fg="white",
font="tahoma 10 bold").place(x=10, y=80)
# Add Button + New Window Open
def openNewWindow():
def close_window():
newWindow.destroy()
newWindow = Toplevel(master)
newWindow.title("New Window")
window_height = 565
window_width = 970
screen_width = newWindow.winfo_screenwidth()
screen_height = newWindow.winfo_screenheight()
x_cordinate = int((screen_width / 2) - (window_width / 2))
y_cordinate = int((screen_height / 2) - (window_height / 2))
newWindow.geometry("{}x{}+{}+{}".format(window_width, window_height, x_cordinate, y_cordinate))
newWindow.configure(background="#071530")
# create a text box
output = Text(newWindow, width=75, height=6, wrap=WORD, background="white")
output.grid(row=2, column=0, columnspan=10, sticky=W, padx=170, pady=30)
# create lable
Label(newWindow, text="BLABLA", bg="#071530", fg="white", font="calibre 20 bold").grid(row=0,
column=0,
sticky=W,
padx=340,
pady=30)
Label(newWindow, text="Subtext.",
bg="black", fg="white", font="calibre 12 bold").grid(row=1, column=0, sticky=W, padx=230, pady=10)
# create lable
Label(newWindow, text="CLICK", bg="black", fg="white", font="calibre 12 bold").grid(row=3,
column=0,
sticky=W,
padx=320,
pady=10)
Label(newWindow, text="EXIT", bg="black", fg="white", font="calibre 12 bold").grid(row=3,
column=0,
sticky=W,
padx=550,
pady=10)
# create a button
Button(newWindow, text="Exit", width=6, command=close_window, bg="orange").grid(row=4, column=0, sticky=W,
padx=570, pady=1)
Button(newWindow, text="View", width=6, bg="orange").grid(row=4, column=0, sticky=W, padx=350, pady=1)
newWindow.mainloop()
# button 1 main menu = ADD
self.button = Button(self, text="Add", width=4, bg="orange", command=openNewWindow)
self.button.place(x=220, y=79.4)
def _resize_image(self,event):
if event.widget is self:
# resize background image to fit the frame size
image = self.image.resize((event.width, event.height))
self.background_image = ImageTk.PhotoImage(image)
self.background.configure(image=self.background_image)
root = Tk()
root.title("GUI")
window_height = 565
window_width = 970
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
x_cordinate = int((screen_width/2) - (window_width/2))
y_cordinate = int((screen_height/2) - (window_height/2))
root.geometry("{}x{}+{}+{}".format(window_width, window_height, x_cordinate, y_cordinate))
e = MainScreen(root)
e.pack(fill=BOTH, expand=1)
root.mainloop()
You can do this by calling grid_remove() of the current frame and then grid() on the new frame. Or, being lazy you can call grid_remove() on everything so that you don't have to remember which page is current.
def _resize_image(self,event)::
'''Show a frame for the given page name'''
for frame in self.frames.values():
frame.grid_remove()
frame = self.frames[page_name]
frame.grid()
Note: the automatic resizing will stop working if you give the main window a fixed size with the geometry method on the root window, or if the user manually resizes the window. This is because tkinter assumes that if something explicitly requests a window size, that size should be honored.
If you always want the window to resize, you should reset the geometry to an empty string. You can add this as the last statement in the show_frame method:
frame.winfo_toplevel().geometry("")
I am trying to make a gui that has two separate text outputs with horizontal and vertical scollbars for each text box that are fixed to the right and bottom edges of each respective text windows. I am struggling with how to do this with the tkinter grid and any help would be appreciated.
import tkinter as tk
class WeatherGUI(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
# Horizontal (x) Scroll bar
self.xscrollbar = tk.Scrollbar(self, orient="horizontal")
self.xscrollbar.grid(column=5, row=10, sticky="we")
# Vertical (y) Scroll Bar
self.yscrollbar = tk.Scrollbar(self)
self.yscrollbar.grid(column=5, row=10, sticky='ns')
self.xscrollbar2 = tk.Scrollbar(self, orient="horizontal")
self.xscrollbar2.grid(column=9, row=10, sticky="we")
# Vertical (y) Scroll Bar
self.yscrollbar2 = tk.Scrollbar(self)
self.yscrollbar2.grid(column=9, row=10, sticky='ns')
self.NSW_actual_text = tk.Text(self, width=50, wrap = "none", xscrollcommand=self.xscrollbar.set, yscrollcommand=self.yscrollbar.set,)
self.NSW_actual_text.grid(column=0, columnspan=4, row= 8,padx=(20, 10))
self.NSW_forecast_text = tk.Text(self, width=50, wrap = "none", xscrollcommand=self.xscrollbar.set, yscrollcommand=self.yscrollbar.set)
self.NSW_forecast_text.grid(column=8, columnspan=4, row= 8,padx=(20, 10))
self.xscrollbar.config(command=self.NSW_actual_text.xview)
self.yscrollbar.config(command=self.NSW_actual_text.yview)
self.xscrollbar2.config(command=self.NSW_forecast_text.xview)
self.yscrollbar2.config(command=self.NSW_forecast_text.yview)
self.btn1 = tk.Button(self, text="Generate NWS Actual", command=self.GenerateNWSActual)
self.btn1.grid(column=1, row=0)
self.btn2 = tk.Button(self, text="Generate NWS Forecast", command=self.GenerateNWSForecast)
self.btn2.grid(column=10, row=0)
def GenerateNWSActual(self):
self.NSW_actual_text.insert('1.0', "This is where actual weather would go")
def GenerateNWSForecast(self):
self.NSW_forecast_text.insert('1.0', "this is where forecast weather would go")
app = WeatherGUI()
app.mainloop()
The following example allows you to attach two functional scrollbars (x, y) to a Text widget
from tkinter import *
# Create Window
root = Tk()
# Create ScrollBars
xScrollbar = Scrollbar(root, orient=HORIZONTAL)
yScrollbar = Scrollbar(root, orient=VERTICAL)
# Create Text Widget with scroll commands
TextWidget = Text(root, xscrollcommand=xScrollbar, yscrollcommand=yScrollbar)
# Package Componets
xScrollbar.pack(side=BOTTOM, fill=X)
yScrollbar.pack(side=RIGHT, fill=Y)
TextWidget.pack(fill=BOTH, expand=20)
# Assign Scrollbars with TextWidget
xScollbar.config(command=TextWidget.xview)
yScollbar.config(command=TextWidget.yview)
You can use this examble for both of your TextWidgets in your weather application.
scrollbar in Top level window created for a canvas is not working and how do I get region of canvas. where canvas size varies with number of buttons in it
I have created frame in tk(root) and one widget in a frame creates Top level window , which has multiple Buttons in a Frame.Number of Button varies with list. That Frame(which has buttons in it) exists in a canvas. My problem is that after putting scroll widget canvas do not moves
from tkinter import *
root = Tk()
root.geometry("500x200")
my_app= Frame(root)
my_app.pack()
my_window = Toplevel(my_app, bg='brown')
my_window.geometry("500x200+300+500")
top_window = Frame(my_window, bd=2, relief=SUNKEN)
top_window.grid_columnconfigure(0, weight=1)
yscrollbar = Scrollbar(top_window)
yscrollbar.grid(row=0, column=1, sticky=N+S)
canvas = Canvas(top_window, bd=0, yscrollcommand=yscrollbar.set)
canvas.config(scrollregion=(0, 0, 500, 1000))
canvas.grid(row=0, column=0, sticky=N+S+E+W)
yscrollbar.config( command = canvas.yview)
top_window.pack()
my_f = Frame(canvas)
def ins_ind(m):
print(m)
results =
["one","two","three","four","five","six","seven","eight","nine","ten"]
ins_list=[]
for ind, result in enumerate(results):
ins=str(result)
ins_list.append(ind)
ins_list[ind] = Button(my_f, text = ins, font='Times 12 bold',
bg='sandy brown',anchor=E, fg="black", command = lambda m=ins:
ins_ind(m) )
ins_list[ind].pack()
my_f.pack()
root.mainloop()
Scroll bar do no moves
For the buttons to move when you scroll the canvas you must put the buttons on the canvas.
Your code puts the buttons on the frame my_f. To put the buttons on the canvas you should use: canvas.create_window(x, y, window=button).