【问题标题】:How to update tkinter label text in real time如何实时更新 tkinter 标签文本
【发布时间】:2021-04-05 18:07:22
【问题描述】:

我有一个应用程序可以获取光标所在像素的 css3 颜色,我想使用 tkinter 在一个小窗口中显示文本。下面是我的代码的 tkinter 部分:

import pyautogui, PIL
import tkinter as tk

def cursorpixel():
    x,y = pyautogui.position()
    pixel = (x,y,x+1,y+1)
    return pixel

def grabColor(square, max_colors=256):
    img=PIL.ImageGrab.grab(square)
    color = img.getcolors(max_colors)
    return color

def main():
    root=tk.Tk()
    root.minsize(150, 50)
    color = tk.Label(root,
                     text= grabColor(cursorpixel()),
                     fg = "black",
                     font = "Arial").pack()
    root.mainloop()

while __name__ == "__main__":
    main()

这可以按我的意愿工作,而没有在我的光标在屏幕上移动时更新标签文本的功能。它在启动应用程序时工作一次,并且标签文本保持不变。我将如何做到这一点,以便每当我的光标移动时标签文本都会更新?我正在使用 python 3.7

谢谢

【问题讨论】:

  • 您的代码目前无法运行。请包含您的grabColor() 函数。
  • 该功能已添加。
  • 谢谢@Logan!还请包括您的进口声明
  • 刚刚添加,谢谢帮助!

标签: python python-3.x tkinter


【解决方案1】:

将变量赋值给text参数并没有帮助,因为即使变量的值发生变化,它也不会反映在标签中。这是我的方法(这只是众多可能方法中的一种)

import pyautogui, PIL
import tkinter as tk
from threading import Thread

def cursorpixel():
    x,y = pyautogui.position()
    pixel = (x,y,x+1,y+1)
    grabColor(pixel)

def grabColor(square, max_colors=256):
    global color_label,root
    img=PIL.ImageGrab.grab(square)
    color = img.getcolors(max_colors)
    color_label.config(text=color)

def refresh():
    while True:
        cursorpixel()

def main():
    global color_label,root
    root=tk.Tk()
    root.minsize(150, 50)
    color_label = tk.Label(root,
                     fg = "black",
                     font = "Arial")
    color_label.pack()
    Thread(target=refresh).start()
    root.mainloop()

if __name__ == "__main__":
    main()

注意事项

  • 我改用了多线程并创建了一个函数refresh(),它在无限循环中触发cursorpixel()
  • 我从cursorpixel() 调用了grabColor() 函数,并以pixel 作为参数。
  • 我已经使用color_label.config() 方法来更改标签中的文本,您也可以使用color_label['text'] 或者将textvariable var = StringVar() 分配给标签,然后在其上使用var.set()。李>
  • 我不确定将__name__='__main__' 放在while 循环中是否是一个不错的选择,因为您将无法在不终止任务的情况下关闭窗口,每次尝试时都会弹出新窗口这样做。

【讨论】:

  • 如果此代码得到更多扩展,多线程仍然可以工作吗?
  • @CoolCloud 以我所拥有的知识,我不明白为什么不应该这样做,如果您有案例,请告诉我,我很乐意学习
  • @CoolCloud 不一定,因为 tkinter 是单线程的。但是tk.StingVar() 和追踪它对我来说似乎是稳定的。
  • 我在一些地方看到过这个,比如@martineau 说“多线程不能与 Tkinter 对象交互。在 Tkinter 应用程序中安全多线程的一个好方法是使用队列对象从辅助线程通信(传递数据)到主线程。通常 self.after() 用于安排定期检索其他线程正在生成的数据。"跨度>
  • @CoolCloud 他们可能需要进行一些更改以优化它,以防他们有多个辅助线程要处理,但如果这是唯一的,我认为应该没有问题.
【解决方案2】:

回答

我将.after 命令添加到grabColor() 函数中,并结合了cursorpixelgrabColor() 函数。我使用.config 来更新颜色。代码如下:

import pyautogui, PIL
from tkinter import *

root=Tk()
root.minsize(150, 50)
colortext = Label(root)
colortext.pack()

def grabColor():
    x,y = pyautogui.position()
    pixel = (x,y,x+1,y+1)
    img=PIL.ImageGrab.grab(bbox=pixel)
    color = img.getcolors()
    colortext.config(text=str(color))
    root.after(100, grabColor)

grabColor()

root.mainloop()

来源/其他资源
How do I create an automatically updating GUI using Tkinter?

【讨论】:

    【解决方案3】:

    您可以使用after()定期抓取颜色:

    import tkinter as tk
    from PIL import ImageGrab
    
    def grab_color(label):
        x, y = label.winfo_pointerxy()
        color = ImageGrab.grab((x, y, x+1, y+1)).getpixel((0, 0))
        label.config(text=str(color))
        label.after(100, grab_color, label)
    
    def main():
        root = tk.Tk()
        color_label = tk.Label(root, width=20)
        color_label.pack(padx=10, pady=10)
        grab_color(color_label)
        root.mainloop()
    
    if __name__ == "__main__":
        main()
    

    注意winfo_pointerxy() 被用来代替pyautogui.position() 以减少对外部模块的依赖。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多