-1

I have setup 2 panels in a frame as so:

frameA = Frame(master)
frameA.pack(side=LEFT, fill=BOTH, expand=YES)
frameB = Frame(master)
frameB.pack(side=RIGHT, fill=BOTH, expand=YES)
recale = 0.4
self.img = ImageTk.PhotoImage(img.resize((int(rescale*width), int(recale*height)), Image.ANTIALIAS)

self.panelA = Label(frameA, image=self.img)
self.pabelA.pack(side=LEFT, fill=BOTH, expand=YES)

self.panelB = Label(frameB, image=self.img)
self.pabelB.pack(side=LEFT, fill=BOTH, expand=YES)

Now, the size of the 2 panels are determined by the image size which I have resized to 0.4 times the original size. How can I dynamically set rescale such that the width of each of the panels takes up the entire width of the master frame when I press the maximize button(this is not a button I made, but rather the little square button next to minimize, and close on the top right) on the GUI?

Jonathan
  • 1,876
  • 2
  • 20
  • 56
  • Could you please provide a [mcve] to illustrate your question? – Jacques Gaudin Apr 30 '19 at 16:25
  • if you create `PhotoImage` in function then you have to assign to class variable (ie. `self.photo = ImageTk.PhotoImage(img)`) because there is bug which removes `PhotoImage` from memory when it is assigned to local variable. See `Note` at the bottom of page [PhotoImage](http://effbot.org/tkinterbook/photoimage.htm) – furas Apr 30 '19 at 17:31
  • you can get screen width `master.winfo_screenwidth()` and set window size `master.geometry('{}x{}'.format(x, y))` – furas Apr 30 '19 at 18:47
  • I've addressed your 1st comment, @furas. For your second comment, how do I use that information to set `rescale` and how do I set this dynamically? – Jonathan Apr 30 '19 at 20:11
  • in question you say nothing about `rescale` but about window size and frame size. It makes difference. You need `window.width` and `bind('", on_resize)` – furas Apr 30 '19 at 20:48
  • Yes, but the frame size is being set based on the image size. Hence, in the question I asked "how can I dynamically set this," where this refers to the resize amount. – Jonathan Apr 30 '19 at 20:56
  • @furas I've editted my question to reflect your comment. – Jonathan Apr 30 '19 at 21:01
  • when you use `pack(fill=BOTH, expand=YES)` then tkinter automatically resize `Frame` and `Label` to fit window - so you don't have to resize it manually. But it will never resize `PhotoImage` or `Image`. So your real problem probably is "how to resize Image when you change window's size". There is example [how to resize single image to window's size](https://stackoverflow.com/questions/24061099/tkinter-resize-background-image-to-window-size) but it may need modifiactions for two images. – furas Apr 30 '19 at 21:28

1 Answers1

1

When you use pack(fill=BOTH, expand=YES) then tkinter automatically resizes Frame and Label to fit window - so you don't have to resize it manually. But it will never resize PhotoImage and Image so it may looks like it doesn't resize Label and Frame. So your real problem probably is "how to resize Image when you change window's size"

Using

root.bind('<Configure>', on_resize)

you can run function when window changed size and then you can generate new image and replace in Label

This function will be executed not only for window but also fro every widget in window so I use str(event.widget) == '.' to resize it only when it is executed for window.

import tkinter as tk
from PIL import Image, ImageTk

def on_resize(event):
    global rescaled_img
    global photo

    #print('[DEBUG] on_resize:', event.widget)

    # resize only when root window changes size
    if str(event.widget) == '.':
        # generate new image
        width  = event.width//2 # -2  # -2*border
        height = event.height   # -2  # -2*border
        rescaled_img = original_img.resize((width, height), Image.ANTIALIAS)
        photo = ImageTk.PhotoImage(rescaled_img)

        # replace images in labels
        label_left['image'] = photo
        label_right['image'] = photo

# ---- main ---

# resize at start
original_img = Image.open('image.jpg')
rescale = 0.4
width = int(rescale * original_img.width)
height = int(rescale * original_img.height)
rescaled_img = original_img.resize((width, height), Image.ANTIALIAS)


root = tk.Tk()

photo = ImageTk.PhotoImage(rescaled_img)

label_left = tk.Label(root, image=photo, border=0) # if border > 0 then you have to use `-2*border` in on_resize
label_left.pack(side='left', fill='both', expand=True)

label_right = tk.Label(root, image=photo, border=0) # if border > 0 then you have to use `-2*border` in on_resize
label_right.pack(side='left', fill='both', expand=True)

# resize when window changed size
root.bind('<Configure>', on_resize)

root.mainloop()

I tried to bind to label as you can see in some code in Tkinter resize background image to window size but it didn't work correctly - at start it makes images bigger and bigger till window fill all screen. Or at start it makes images small and small till window has no size.


if Label has border bigger then 0 then you have to substract 2*border from image size.

furas
  • 134,197
  • 12
  • 106
  • 148