【问题标题】:tkinter window/frame blinks on button clicktkinter 窗口/框架在按钮单击时闪烁
【发布时间】:2016-09-23 00:37:58
【问题描述】:

这是一个 tkinter 程序,带有一个开始/停止按钮,用于进入和退出一个无限循环,该循环记录到一个文本记录器小部件。我一生都无法弄清楚为什么,但只有当按下开始 按钮 时,框架才会闪烁/闪烁,但功能运行良好。当我从文件菜单中选择开始时,没有闪光......关于为什么会这样的任何想法?这是我的代码中的错误吗?

import tkinter as tk
import tkinter.scrolledtext as tkst
from tkinter import ttk
import logging


def popupmsg(msg):
    popup = tk.Tk()
    popup.wm_title("!")
    label = ttk.Label(popup, text=msg)
    label.pack(side="top", fill="x", pady=10)
    b1 = ttk.Button(popup, text="Okay", command=popup.destroy)
    b1.pack()
    popup.mainloop()


class TextHandler(logging.Handler):

    def __init__(self, text):
        # run the regular Handler __init__
        logging.Handler.__init__(self)
        # Store a reference to the Text it will log to
        self.text = text

    def emit(self, record):
        msg = self.format(record)

        def append():
            self.text.configure(state='normal')
            self.text.insert(tk.END, msg + '\n')
            self.text.configure(state='disabled')
            # Autoscroll to the bottom
            self.text.yview(tk.END)

        # This is necessary because we can't modify the Text from other threads
        self.text.after(0, append)

    def create(self, num):
        # Create textLogger
        topframe = tk.Frame(root)
        topframe.pack(side=tk.TOP)
        if num == 0:
            st = tkst.ScrolledText(topframe, state='disabled')
            st.configure(font='TkFixedFont')

            st.pack()

            self.text_handler = TextHandler(st)

            # Add the handler to logger
            self.logger = logging.getLogger()
            self.logger.addHandler(self.text_handler)
            print(num)

        else:
            # Add the handler to logger
            self.logger = logging.getLogger()
            print(num)


def stop():
    root.flag = False


def loop():
    th = TextHandler("none")
    th.create(1)

    def start():
        if root.flag:
            th.logger.error("error")
            root.after(1000, start)
        else:
            th.logger.error("Loop stopped")
            root.flag = True
            return
    start()



class HomePage(tk.Frame):

    def __init__(self, parent):

        tk.Frame.__init__(self, parent)

        #logger and main loop
        th = TextHandler("none")
        th.create(0)
        root.flag = True

        bottomframe = tk.Frame(root)
        bottomframe.pack(side=tk.BOTTOM)

        topframe = tk.Frame(root)
        topframe.pack(side=tk.TOP)

        topframe = tk.Frame(root)
        topframe.pack(side=tk.TOP)

        # Create taskbar/menu
        taskbar = tk.Menu(self.master)
        self.master.config(menu=taskbar)

        file = tk.Menu(taskbar)
        file.add_command(label="Run", command=loop)
        file.add_command(label="Stop", command=stop)
        file.add_separator()
        file.add_command(label="Settings", command=lambda: popupmsg("Coming \"soon\"..."))
        file.add_separator()
        file.add_command(label="Quit", command=quit)
        taskbar.add_cascade(label="File", menu=file)

        startButton = tk.Button(bottomframe, text="Start", command=loop)
        startButton.pack()

        stopButton = tk.Button(bottomframe, text="Stop",  command=stop)
        stopButton.pack()

        exitButton = tk.Button(bottomframe, text="Exit",  command=quit)
        exitButton.pack()


if __name__ == "__main__":
    root = tk.Tk()
    app = HomePage(root)
    root.wm_title("Scraper")
    root.mainloop()

【问题讨论】:

  • 我没有仔细看代码中的原因和位置,但是在按下按钮时,您的窗口会稍微调整大小(垂直变大)。这很可能会导致问题。

标签: python tkinter


【解决方案1】:

我不完全确定为什么,但是像这样调整我的代码已经修复了这个屏幕闪烁问题。

我将stoploop 函数作为方法移到TextHandler 类中。这使我可以删除对TextHandler 的第二次调用以及loop 函数中的create 方法。我现在也不需要 create 方法中的第二个参数(将其用作一种标志),因此已将其删除。

我猜当点击开始按钮时 flash 是第二次调用。

import tkinter as tk
import tkinter.scrolledtext as tkst
from tkinter import ttk
import logging


def popupmsg(msg):
    popup = tk.Tk()
    popup.wm_title("!")
    label = ttk.Label(popup, text=msg)
    label.pack(side="top", fill="x", pady=10)
    b1 = ttk.Button(popup, text="Okay", command=popup.destroy)
    b1.pack()
    popup.mainloop()


class TextHandler(logging.Handler):

    def __init__(self, text):
        # run the regular Handler __init__
        logging.Handler.__init__(self)
        # Store a reference to the Text it will log to
        self.text = text

    def emit(self, record):
        msg = self.format(record)

        def append():
            self.text.configure(state='normal')
            self.text.insert(tk.END, msg + '\n')
            self.text.configure(state='disabled')
            # Autoscroll to the bottom
            self.text.yview(tk.END)

        # This is necessary because we can't modify the Text from other threads
        self.text.after(0, append)

    def create(self):
        # Create textLogger
        topframe = tk.Frame(root)
        topframe.pack(side=tk.TOP)

        st = tkst.ScrolledText(topframe, state='disabled')
        st.configure(font='TkFixedFont')

        st.pack()

        self.text_handler = TextHandler(st)

        # Add the handler to logger
        self.logger = logging.getLogger()
        self.logger.addHandler(self.text_handler)

    def stop(self):
        root.flag = False

    def loop(self):
        def start():
            if root.flag:
                self.logger.error("error")
                root.after(1000, start)
            else:
                self.logger.error("Loop stopped")
                root.flag = True
                return
        start()


class HomePage(tk.Frame):

    def __init__(self, parent):

        tk.Frame.__init__(self, parent)

        #logger and main loop
        th = TextHandler("none")
        th.create()
        root.flag = True

        bottomframe = tk.Frame(root)
        bottomframe.pack(side=tk.BOTTOM)

        topframe = tk.Frame(root)
        topframe.pack(side=tk.TOP)

        topframe = tk.Frame(root)
        topframe.pack(side=tk.TOP)

        # Create taskbar/menu
        taskbar = tk.Menu(self.master)
        self.master.config(menu=taskbar)

        file = tk.Menu(taskbar)
        file.add_command(label="Run", command=lambda: th.loop())
        file.add_command(label="Stop", command=lambda: th.loop())
        file.add_separator()
        file.add_command(label="Settings", command=lambda: popupmsg("Coming \"soon\"..."))
        file.add_separator()
        file.add_command(label="Quit", command=quit)
        taskbar.add_cascade(label="File", menu=file)

        startButton = tk.Button(text="Start", command=lambda: th.loop())
        startButton.pack()

        stopButton = tk.Button(text="Stop",  command=lambda: th.stop())
        stopButton.pack()

        exitButton = tk.Button(text="Exit",  command=quit)
        exitButton.pack()


if __name__ == "__main__":
    root = tk.Tk()
    app = HomePage(root)
    root.wm_title("Scraper")
    root.mainloop()

¯\_(ツ)_/¯

【讨论】:

  • 这不是一个非常有用的答案。读者需要逐行比较代码以寻找差异。你应该解释你改变了什么。
  • @Bryan Oakley:被指控有罪。老实说,因为这篇文章几乎没有引起任何兴趣,甚至没有评论,但我认为发表一些东西总比没有好。但那是懒惰。希望现在好多了。
猜你喜欢
  • 1970-01-01
  • 2014-10-26
  • 1970-01-01
  • 1970-01-01
  • 2018-05-26
  • 2021-05-17
  • 2013-09-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多