Python tkinter窗体显示几个像素关闭

omjgkv6w  于 2023-03-31  发布在  Python
关注(0)|答案(1)|浏览(116)

我尝试使用tkinter在屏幕的特定点显示窗口(0.0 =上/左,1.0 =下/右)。不幸的是,显示器通常偏离其应有位置约8个像素。(不是其左上点),我已经写了一个函数来计算xy的位置与窗体的尺寸。的大小,因此不会在任务栏下生成窗体。)
由于tkinter允许使用geometry("form_width x form_height + x_offset + y_offset")进行定位,因此每当我尝试让它在偏移量(0,0)它生成稍微向右偏远的位置-需要(-8,0)来加载屏幕左上角的窗口,没有间隙。在左下方加载(0,1)生成的值稍高(窗体和任务栏之间有间隙)和太靠右。右上角和右下角也存在类似的问题。总之,它总是生成大约8个像素太靠右,如果它试图在监视器工作区的底部生成,它会生成太高的8。(在顶部生成不会把它放得太高。)
当所有元素都添加到表单后调用定位函数时,它会调用表单上的.update()来重新计算所需的空间,然后使用.winfo_reqwidth().winfo_reqheight()执行所有必要的计算,然后将结果传递给窗口的geometry()
为什么会出现像素偏移问题?是因为update()没有考虑到表单元素的某些填充,还是我的计算机显示器有问题?(我不认为是屏幕问题-所有其他应用程序都正常工作,但我可能错了。)
计算窗体位置的函数如下。参数:window-计算位置的形式/顶层,pos_xy-屏幕中位置的列表/元组或枚举(包含元组)(左上角0,0;右下角1,1)。

def new_calc_position(self, window, pos_xy):
        # if size of desktop minus taskbar has not been calculated, calculate it
        if self.work_area is None:
            monitor_info = GetMonitorInfo(MonitorFromPoint((0, 0)))
            workspace = monitor_info.get("Work")
            self.work_area = [workspace[2], workspace[3]]  # [width, height]
            print(f"Work area: {workspace[2]}, {workspace[3]}")

            monitor_area = monitor_info.get("Monitor")
            self.taskbar_height = monitor_area[3] - workspace[3]
            print(f"Monitor area: {monitor_area[2]}, {monitor_area[3]}")
            print(f"Taskbar height: {self.taskbar_height}")

        # test that pos_xy is enum Position or list containing two floats 0.0 <= x <= 1.0
        if type(pos_xy) is Position:
            pos_xy = pos_xy.value  # convert enum to list for use
        elif isinstance(pos_xy, (list, tuple)) and len(pos_xy) == 2 and all(isinstance(el, float) and
                                                                            0.0 <= el <= 1.0 for el in pos_xy):
            pass  # is list/tuple, length of 2, and all numbers are floats 0.0 <= x <= 1.0
        else:
            raise TypeError("pos_xy must be of type Position or a list containing two numbers between 0.0 and 1.0")

        window.withdraw()  # stop window from showing
        window.update()  # force it to update its required size; would flash to screen if not withdrawn
        window.deiconify()  # allow window to show

        # calculate targeted position
        target_width = self.work_area[0] * pos_xy[0]
        target_height = self.work_area[1] * pos_xy[1]

        print("Monitor width:   " + str(self.work_area[0]))
        print("Monitor height:  " + str(self.work_area[1]))

        print("Width percent:   " + str(pos_xy[0]))
        print("Height percent:  " + str(pos_xy[1]))

        print("Width target:    " + str(target_width))
        print("Height target:   " + str(target_height))

        # calculate required width and height
        width = window.winfo_reqwidth()
        height = window.winfo_reqheight()
        print("Form width:      " + str(width))
        print("Form height:     " + str(height))

        # TODO create a lock parameter to allow a certain generation point
        x_offset = int(target_width - (width / 2))
        y_offset = int(target_height - (height / 2))
        print("Initial xoffset: " + str(x_offset))
        print("Initial yoffset: " + str(y_offset))

        # bounce window to display entirely in screen; assume will not overlap both sides in one dimension
        if x_offset < 0: # too far to left
            x_offset = 0
        elif x_offset + width > self.work_area[0]: # too far to right
            x_offset = self.work_area[0] - width

        if y_offset < 0:
            y_offset = 0
        elif y_offset + height > self.work_area[1]:
            y_offset = self.work_area[1] - self.taskbar_height - height

        print("Ending xoffset:  " + str(x_offset))
        print("Ending yoffset:  " + str(y_offset))

        print(f"{width}x{height}+{x_offset}+{y_offset}")
        return f"{width}x{height}+{x_offset}+{y_offset}"
atmip9wb

atmip9wb1#

我不能告诉你为什么x偏移问题会发生,但我至少可以确认你是对的。
我以前从未注意到这一点,但在我的Windows10机器上,x偏移量为0,y偏移量为0将根窗口正确地放置在屏幕顶部。但它位于大约7像素我的右边,在屏幕左手留下一个小间隙。将x偏移设置为-7将根窗口正确地定位在屏幕的左侧,没有间隙。
注意,你可以用鼠标抓取根窗口并将其移动到屏幕的左侧。因此,无论你是使用负偏移量,还是手动移动窗口,当被迫这样做时,它都没有问题正确地位于屏幕的左侧。
其他Windows应用程序在最大化时确实正确地位于屏幕的左手,因此这将其缩小到tkinter的怪癖,或者Windows和tkinter之间的交互。
如果这种行为在Linux和Mac上是一样的,那么这是tkinter的怪癖。如果不是,那么这是Windows + tkinter的问题。
最重要的是,你的代码不是问题所在。

相关问题