I'm working on an interactive simulator for physics. I want each physical object and the GUI to have their own classes for drawing, and I want to be able to resize the window. The canvas is currently contained in the GUI. How do I move all objects on window resize? All of them are tied to the window center.
My current setup is a frame that holds
- a canvas
- a frame that holds
- two frames that each hold a couple sliders.
I've left in only one slider to show the general idea without too much clutter. Likewise, I only left in one object.
I used the solution offered here, slightly adjusted by me to move objects instead of rescaling them. How to get tkinter canvas to dynamically resize to window width?
I printed the supposed offsets (differences between new and old size, split in half and rounded), but they are constantly negative, regardless of whether I'm expanding or shrinking the window in either direction. Using curr_w = self.winfo_width();
makes the differences 0.
from tkinter import *
import time
import math
def splitterCoords(canv_w, canv_h):
splitterX = round(canv_w/2);
splitterY = round(canv_h/2);
splitterLen = round(round(canv_h/5)*0.5*math.sqrt(2));
return [splitterX + splitterLen, splitterY - splitterLen, splitterX - splitterLen, splitterY + splitterLen];
class ResizingCanvas(Canvas):
def __init__(self,parent,**kwargs):
Canvas.__init__(self,parent,**kwargs)
self.bind("<Configure>", self.on_resize)
def on_resize(self,event):
curr_w = self.winfo_reqwidth();
curr_h = self.winfo_reqheight();
new_w = event.width;
new_h = event.height;
self.config(width = new_w, height = new_h)
self.move("item",round((new_w-curr_w)/2),round((new_h-curr_h)/2))
class GUI:
def __init__(self,master):
frame = Frame(master)
frame.pack(fill = BOTH, expand = 1)
bg = ResizingCanvas(frame, width = 1200, height = 600, background = "#F0F0F0", borderwidth = 3, relief = SUNKEN)
bg.pack(fill = BOTH, expand = 1)
sliders = Frame(frame)
sliders.pack(fill = X, expand = 1)
distSliders = Frame(sliders)
distSliders.pack(fill = X, expand = 1, side = LEFT)
distMirror1Obj = Scale(distSliders, orient=HORIZONTAL)
distMirror1Obj.pack(fill = X, expand = 1)
class Splitter:
def __init__(self, canvas, color):
self.canvas = canvas
canv_w = canvas.winfo_width()
canv_h = canvas.winfo_height()
self.id = canvas.create_line(splitterCoords(canv_w,canv_h), fill = color, tags = "item")
def draw(self):
pass
root = Tk()
gui_r = GUI(root)
root.update()
splitter = Splitter(root.children['!frame'].children['!resizingcanvas'], "black")
while 1:
root.update_idletasks()
root.update()
splitter.draw()
time.sleep(0.01)
What currently happens on running the .py script: the window appears, then smoothly expands until the canvas becomes 1920x1080 (my screen resolution). The slider (or sliders in the full code) does not appear. If I then shrink the window in any way, the created item is moved strictly up and left.
I suspect if I stop the window from resizing, I'd be able to store the center value and update it after moving the object, but I don't know how to do that.