Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何防止图像在调整大小时填充整个Tkinter窗口?_Python_Image_Python 3.x_Tkinter_Image Resizing - Fatal编程技术网

Python 如何防止图像在调整大小时填充整个Tkinter窗口?

Python 如何防止图像在调整大小时填充整个Tkinter窗口?,python,image,python-3.x,tkinter,image-resizing,Python,Image,Python 3.x,Tkinter,Image Resizing,基于,我想在主图像下面添加第二个小部件 当用户调整此图像的大小时,该图像将适合该窗口 请参见@Marcin的示例: 问题是,如果我在窗口中添加任何小部件,就会发生奇怪的事情(这里有一个文本): 图像逐渐增长,直到填满整个窗口,第二个窗口小部件消失 这是我的密码: from tkinter import * from PIL import Image, ImageTk from io import BytesIO import base64 root = Tk() root.title("T

基于,我想在主图像下面添加第二个小部件

当用户调整此图像的大小时,该图像将适合该窗口

请参见@Marcin的示例:

问题是,如果我在窗口中添加任何小部件,就会发生奇怪的事情(这里有一个文本):

图像逐渐增长,直到填满整个窗口,第二个窗口小部件消失

这是我的密码:

from tkinter import *
from PIL import Image, ImageTk
from io import BytesIO
import base64

root = Tk()
root.title("Title")
root.geometry("600x600")


class ImageFrame(Frame):
    def __init__(self, master, *pargs):
        Frame.__init__(self, master, *pargs)


        self.black_pixel = BytesIO(base64.b64decode("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="))
        self.image = Image.open(self.black_pixel)

        self.img_copy= self.image.copy()


        self.background_image = ImageTk.PhotoImage(self.image)

        self.background = Label(self, image=self.background_image)
        self.background.pack(fill=BOTH, expand=YES)
        self.background.bind('<Configure>', self._resize_image)

        self.width = 1
        self.height = 1

    def _resize_image(self,event):

        new_width = event.width
        new_height = event.height

        if new_width != self.width or new_height != self.height:
            self.width = new_width
            self.height = new_height

            self.image = self.img_copy.resize((new_width, new_height))

            self.background_image = ImageTk.PhotoImage(self.image)
            self.background.configure(image =  self.background_image)


img = ImageFrame(root)
txt = Text(root)

img.pack(fill=BOTH, expand=YES)
txt.pack()

root.mainloop()
从tkinter导入*
从PIL导入图像,ImageTk
从io导入字节io
导入base64
root=Tk()
根标题(“标题”)
根部几何形状(“600x600”)
类图像帧(帧):
定义初始值(自、主、参数):
帧。初始帧(自、主、*pargs)
self.black_pixel=BytesIO(base64.b64解码(“r0lgodlhaqabaaaauebaaacwaaaqaabaacakqbads=”))
self.image=image.open(self.black\u像素)
self.img_copy=self.image.copy()
self.background\u image=ImageTk.PhotoImage(self.image)
self.background=标签(self,image=self.background\u image)
self.background.pack(fill=BOTH,expand=YES)
self.background.bind(“”,self.\u调整大小\u图像)
self.width=1
自我高度=1
def_resize_图像(自身、事件):
新建宽度=event.width
新高度=事件高度
如果是新宽度!=自宽或新高度!=身高:
self.width=新宽度
self.height=新高度
self.image=self.img\u copy.resize((新宽度、新高度))
self.background\u image=ImageTk.PhotoImage(self.image)
self.background.configure(image=self.background\u image)
img=图像帧(根)
txt=文本(根)
img.pack(填充=两者,扩展=是)
txt.pack()
root.mainloop()
我尝试用不同的选项打包
img
txt
,但没有任何改变


有人知道我做错了什么吗?

调用
。在同一个小部件上的
回调中在小部件上配置
,这与递归非常相似,总是存在永无止境的风险

触发
事件时,宽度
事件高度
包括2像素的自动填充,因此将图像设置为该大小会将
标签的大小增加4像素,从而再次触发
事件

在中不会发生这种情况,因为一旦标签的大小达到具有强制几何体的窗口的大小,它就不会再次重新配置,这也是图像用完窗口上所有空间后在程序中发生的情况

真正快速的解决方法是改变:

    new_width = event.width
    new_height = event.height
致:

为了补偿间距,但我绝对不能保证它能始终如一地工作


下面是一个不同的实现,它使用
画布
而不是
框架
标签

class ImageFrame(Canvas):
    def __init__(self, master, *pargs ,**kw):
        Canvas.__init__(self, master, *pargs,**kw)

        self.black_pixel = BytesIO(base64.b64decode("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="))
        self.img_copy = Image.open(self.black_pixel)
        self.image = None #this is overriden every time the image is redrawn so there is no need to make it yet

        self.bind("<Configure>",self._resize_image)

    def _resize_image(self,event):
        origin = (0,0)
        size = (event.width, event.height)
        if self.bbox("bg") != origin + size:
            self.delete("bg")
            self.image = self.img_copy.resize(size)
            self.background_image = ImageTk.PhotoImage(self.image)
            self.create_image(*origin,anchor="nw",image=self.background_image,tags="bg")
            self.tag_lower("bg","all")
类图像帧(画布):
定义初始功率(自功率、主功率、*pargs、**kw):
画布。__初始(自、主、*pargs、**kw)
self.black_pixel=BytesIO(base64.b64解码(“r0lgodlhaqabaaaauebaaacwaaaqaabaacakqbads=”))
self.img\u copy=Image.open(self.black\u像素)
self.image=None#每次重绘图像时都会覆盖此选项,因此无需进行重绘
self.bind(“,self.\u调整大小\u图像)
def_resize_图像(自身、事件):
原点=(0,0)
大小=(event.width、event.height)
如果self.bbox(“bg”)!=原点+大小:
自我删除(“bg”)
self.image=self.img\u copy.resize(大小)
self.background\u image=ImageTk.PhotoImage(self.image)
self.create_image(*origin,anchor=“nw”,image=self.background_image,tags=“bg”)
自我标记较低(“背景”、“全部”)

这种方法不是重新配置窗口小部件,而是在画布上重新绘制图像。

我打赌这与以下事实有关:当任何东西使窗口大小调整时,事件将触发,而不仅仅是当用户拖动窗口句柄时。如果回调中的代码可以更改窗口大小,那么可能会导致回调几乎连续启动。这非常有效,非常感谢您的解释和解决方法!
class ImageFrame(Canvas):
    def __init__(self, master, *pargs ,**kw):
        Canvas.__init__(self, master, *pargs,**kw)

        self.black_pixel = BytesIO(base64.b64decode("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="))
        self.img_copy = Image.open(self.black_pixel)
        self.image = None #this is overriden every time the image is redrawn so there is no need to make it yet

        self.bind("<Configure>",self._resize_image)

    def _resize_image(self,event):
        origin = (0,0)
        size = (event.width, event.height)
        if self.bbox("bg") != origin + size:
            self.delete("bg")
            self.image = self.img_copy.resize(size)
            self.background_image = ImageTk.PhotoImage(self.image)
            self.create_image(*origin,anchor="nw",image=self.background_image,tags="bg")
            self.tag_lower("bg","all")