我已经拼凑了以下代码(原始源代码here)

我不知道如何使用图像的宽度和高度来驱动应用程序的宽度和高度

我希望应用程序窗口的大小与源图像相同.


代码如下:

import tkinter as tk
from PIL import Image, ImageTk


class MousePositionTracker(tk.Frame):
    """ Tkinter Canvas mouse position widget. """

    def __init__(self, canvas):
        self.canvas = canvas
        self.canv_width = self.canvas.cget('width')
        self.canv_height = self.canvas.cget('height')
        self.reset()

        # Create canvas cross-hair lines.
        xhair_opts = dict(dash=(3, 2), fill='white', state=tk.HIDDEN)
        self.lines = (self.canvas.create_line(0, 0, 0, self.canv_height, **xhair_opts),
                      self.canvas.create_line(0, 0, self.canv_width,  0, **xhair_opts))

    def cur_selection(self):
        return (self.start, self.end)

    def begin(self, event):
        self.hide()
        self.start = (event.x, event.y)  # Remember position (no drawing).

    def update(self, event):
        self.end = (event.x, event.y)
        self._update(event)
        self._command(self.start, (event.x, event.y))  # User callback.

    def _update(self, event):
        # Update cross-hair lines.
        self.canvas.coords(self.lines[0], event.x, 0, event.x, self.canv_height)
        self.canvas.coords(self.lines[1], 0, event.y, self.canv_width, event.y)
        self.show()

    def reset(self):
        self.start = self.end = None

    def hide(self):
        self.canvas.itemconfigure(self.lines[0], state=tk.HIDDEN)
        self.canvas.itemconfigure(self.lines[1], state=tk.HIDDEN)

    def show(self):
        self.canvas.itemconfigure(self.lines[0], state=tk.NORMAL)
        self.canvas.itemconfigure(self.lines[1], state=tk.NORMAL)

    def autodraw(self, command=lambda *args: None):
        """Setup automatic drawing; supports command option"""
        self.reset()
        self._command = command
        self.canvas.bind("<Button-1>", self.begin)
        self.canvas.bind("<B1-Motion>", self.update)
        self.canvas.bind("<ButtonRelease-1>", self.quit)

    def quit(self, event):
        self.hide()  # Hide cross-hairs.
        self.reset()


class SelectionObject:
    """ Widget to display a rectangular area on given canvas defined by two points
        representing its diagonal.
    """
    def __init__(self, canvas, select_opts):
        # Create attributes needed to display selection.
        self.canvas = canvas
        self.select_opts1 = select_opts
        self.width = self.canvas.cget('width')
        self.height = self.canvas.cget('height')

        # Options for areas outside rectanglar selection.
        select_opts1 = self.select_opts1.copy()  # Avoid modifying passed argument.
        select_opts1.update(state=tk.HIDDEN)  # Hide initially.
        # Separate options for area inside rectanglar selection.
        select_opts2 = dict(dash=(2, 2), fill='', outline='white', state=tk.HIDDEN)

        # Initial extrema of inner and outer rectangles.
        imin_x, imin_y,  imax_x, imax_y = 0, 0,  1, 1
        omin_x, omin_y,  omax_x, omax_y = 0, 0,  self.width, self.height

        self.rects = (
            # Area *outside* selection (inner) rectangle.
            self.canvas.create_rectangle(omin_x, omin_y,  omax_x, imin_y, **select_opts1),
            self.canvas.create_rectangle(omin_x, imin_y,  imin_x, imax_y, **select_opts1),
            self.canvas.create_rectangle(imax_x, imin_y,  omax_x, imax_y, **select_opts1),
            self.canvas.create_rectangle(omin_x, imax_y,  omax_x, omax_y, **select_opts1),
            # Inner rectangle.
            self.canvas.create_rectangle(imin_x, imin_y,  imax_x, imax_y, **select_opts2)
        )

    def update(self, start, end):
        # Current extrema of inner and outer rectangles.
        imin_x, imin_y,  imax_x, imax_y = self._get_coords(start, end)
        omin_x, omin_y,  omax_x, omax_y = 0, 0,  self.width, self.height

        # Update coords of all rectangles based on these extrema.
        self.canvas.coords(self.rects[0], omin_x, omin_y,  omax_x, imin_y),
        self.canvas.coords(self.rects[1], omin_x, imin_y,  imin_x, imax_y),
        self.canvas.coords(self.rects[2], imax_x, imin_y,  omax_x, imax_y),
        self.canvas.coords(self.rects[3], omin_x, imax_y,  omax_x, omax_y),
        self.canvas.coords(self.rects[4], imin_x, imin_y,  imax_x, imax_y),

        for rect in self.rects:  # Make sure all are now visible.
            self.canvas.itemconfigure(rect, state=tk.NORMAL)

        # Update bounding box result
        global bounding_box

        bounding_box = self._get_coords(start, end)

        # # Print result on every change
        # print("Bounding Box Result:")
        # print(f"Top Left: ({bounding_box[0]}, {bounding_box[1]})")
        # print(f"Bottom Right: ({bounding_box[2]}, {bounding_box[3]})\n")

    def _get_coords(self, start, end):
        """ Determine coords of a polygon defined by the start and
            end points one of the diagonals of a rectangular area.
        """
        return (min((start[0], end[0])), min((start[1], end[1])),
                max((start[0], end[0])), max((start[1], end[1])))

    def hide(self):
        for rect in self.rects:
            self.canvas.itemconfigure(rect, state=tk.HIDDEN)


class Application(tk.Frame):

    # Default selection object options.
    SELECT_OPTS = dict(dash=(2, 2), stipple='gray25', fill='black',
                          outline='')

    def __init__(self, parent, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)

        path = "/Users/nathan/Desktop/Books.jpeg"
        img = ImageTk.PhotoImage(Image.open(path))
        self.canvas = tk.Canvas(root, width=img.width(), height=img.height(),
                                borderwidth=0, highlightthickness=0)

        self.canvas.pack(expand=True)

        self.canvas.create_image(0, 0, image=img, anchor=tk.NW)
        self.canvas.img = img  # Keep reference.

        # Create selection object to show current selection boundaries.
        self.selection_obj = SelectionObject(self.canvas, self.SELECT_OPTS)

        # Callback function to update it given two points of its diagonal.
        def on_drag(start, end, **kwarg):  # Must accept these arguments.
            self.selection_obj.update(start, end)

        # Create mouse position tracker that uses the function.
        self.posn_tracker = MousePositionTracker(self.canvas)
        self.posn_tracker.autodraw(command=on_drag)  # Enable callbacks.

        # # Create a button to close the application.
        # self.close_button = tk.Button(root, text="Close", command=self.close_application)
        # self.close_button.pack()

        # Bind the Escape and Enter keys to the close_application method.
        root.bind("<Escape>", self.close_application)
        root.bind("<Return>", self.close_application)

    def close_application(self, event=None):
        try:
            print(bounding_box)
        except: 
            print("None")
        root.destroy()


if __name__ == '__main__':




    # Set the size and position of the application window.


    BACKGROUND = '#282A36'
    TITLE = 'Image Cropper'
    WIDTH, HEIGHT = 1280, 720

    root = tk.Tk()
    root.title(TITLE)
    root.configure(background=BACKGROUND)

    # Get the screen width and height
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()

    # Calculate the position to center the window
    x = (screen_width - WIDTH) // 2
    y = (screen_height - HEIGHT) // 2

    # Set the window geometry
    root.geometry('%dx%d+%d+%d' % (WIDTH, HEIGHT, x, y))



    # # Make the window fullscreen
    # root.state('zoomed')

    # # Make the window borderless
    # root.overrideredirect(True)

    app = Application(root, background=BACKGROUND)
    app.pack(side=tk.TOP, fill=tk.BOTH, expand=tk.TRUE)
    app.mainloop()

我想要做的是:

我试图定义一个全局变量.

我发现应用程序窗口的宽度和高度是在代码末尾定义的(第185行) 源图像在‘类应用程序(tk.Frame)’中定义(第135行)

我不确定我是误解了全局变量,还是别的什么.但是我不知道如何用图像中的值填充WIDTH, HEIGHT(第185行).

我试着添加

global image_size
image_size = img.width(),img.height()

到‘类应用程序(tk.Frame)’

然后用它,就像这样

WIDTH, HEIGHT = image_size

但这不管用,有谁介意帮我一下吗?

推荐答案

您已经将画布的大小设置为图像的大小,并且根据应用程序的配置方式,窗口将缩小或增大以适应图像.只要go 掉root.geometry('%dx%d+%d+%d' % (WIDTH, HEIGHT, x, y))个,窗口就会自动变成你想要的大小.

如果希望窗保持在给定的x,y位置,则使用x/y坐标指定几何图形,而不是使用宽度/高度值.

root.geometry('+%d+%d' % (x, y))

Python相关问答推荐

使用Python进行网页抓取,没有页面

如何在vercel中指定Python运行时版本?

如何使用Selenium访问svg对象内部的元素

用gekko解决的ADE方程系统突然不再工作,错误消息异常:@错误:模型文件未找到.& &

使用plotnine和Python构建地块

@Property方法上的inspect.getmembers出现意外行为,引发异常

在Python中处理大量CSV文件中的数据

如何使用matplotlib在Python中使用规范化数据和原始t测试值创建组合热图?

Python json.转储包含一些UTF-8字符的二元组,要么失败,要么转换它们.我希望编码字符按原样保留

为什么这个带有List输入的简单numba函数这么慢

在Python中管理打开对话框

如何在solve()之后获得症状上的等式的值

OR—Tools中CP—SAT求解器的IntVar设置值

使用NeuralProphet绘制置信区间时出错

让函数调用方程

如何在两列上groupBy,并使用pyspark计算每个分组列的平均总价值

剪切间隔以添加特定日期

在Admin中显示从ManyToMany通过模型的筛选结果

pandas:在操作pandora之后将pandora列转换为int

如何求相邻对序列中元素 Select 的最小代价