You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter GUI实现点击按钮打印耗时并重置的自动启动计时器

Tkinter GUI计时器功能实现方案

原有代码已知问题

  • 缺失yaml模块导入,调用loadData函数会直接报错
  • 实例变量命名冲突,同时定义了self.start_timer和self._start_timer两个相关变量
  • __init__方法中存在错误的time()实例化逻辑
  • reset方法判断条件写反,会触发空值计算异常
  • 缺少程序启动自动初始化计时的逻辑
  • 主函数实例化App时传入了数据集参数,但App类的构造函数没有对应接收逻辑

功能实现说明

已按照要求完成两个核心功能:

  1. 程序启动时计时器自动启动
  2. 点击「next set」按钮时,先打印上一轮任务的耗时,再重置计时器开始新一轮计时,原有加载下一组图片的逻辑不受影响

完整修改后的代码

import time
import tkinter as tk
import csv
import yaml # 补充缺失的yaml导入
from pathlib import Path
import PIL.Image
import PIL.ImageDraw
import PIL.ImageTk

MAX_HEIGHT = 500
IMAGES_PATH = Path("Images")
CSV_LABELS_KEY = "New Labels"
CSV_FILE_NAME_KEY = "FolderNum_SeriesNum"
CSV_BOUNDING_BOX_KEY = "correct_flip_bbox"
counter = 0
timer_id = None

class App(tk.Frame):
    # 修正构造函数,兼容主函数传入的数据集参数
    def __init__(self, dataset=None, master=None):
        super().__init__(master)
        self.config_paths = ["config 1.yaml", "config 2.yaml", "config 3.yaml"]
        self.config_index = 0
        self.clickStatus = tk.StringVar()
        self.loadedImages = dict()
        self.loadedBoxes = dict()
        self.master.title('Slideshow')
        # 定义存储计时开始时间的实例变量
        self._start_time = None
        
        frame = tk.Frame(self)
        # 调整按钮调用顺序:先处理计时逻辑,再加载下一组图片
        tk.Button(frame, text="  Next set ", command=lambda:[self.reset(), self.get_next_image_set()]).pack(side=tk.RIGHT)
        tk.Button(frame, text="  Exit  ", command=self.destroy).pack(side=tk.RIGHT)
        frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.canvas = tk.Canvas(self)
        self.canvas.pack()
        
        # 如果有传入数据集就用传入的,没有就自己加载
        if dataset:
            self.image_data = dataset
            self.currentIndex = 0
            self._load_image()
        else:
            self._load_dataset()
        
        # 程序启动自动开始计时
        self._start_time = time.perf_counter()

    def reset(self):
        # 已经有开始时间的情况下计算耗时
        if self._start_time is not None:
            elapsed_time = time.perf_counter() - self._start_time
            # 格式化耗时为hh:mm:ss.ms格式
            hours = int(elapsed_time // 3600)
            minutes = int((elapsed_time % 3600) // 60)
            seconds = elapsed_time % 60
            print(f'Time elapsed (hh:mm:ss.ms) {hours:02d}:{minutes:02d}:{seconds:06.3f}')
        # 重置计时器,开始新一轮计时
        self._start_time = time.perf_counter()

    def _load_dataset(self):
        try:
            config_path = self.config_paths[self.config_index]
            self.config_index += 1
        except IndexError:
            return
        image_data = loadData(config_path)
        self.image_data = image_data
        self.currentIndex = 0
        self._load_image()

    def _load_image(self):
        imgName = self.image_data[self.currentIndex]['image_file']
        if imgName not in self.loadedImages:
            self.im = PIL.Image.open(self.image_data[self.currentIndex]['image_file'])
            ratio = MAX_HEIGHT / self.im.height
            height, width = int(self.im.height * ratio), int(self.im.width * ratio)
            self.canvas.config(width=width, height=height)
            self.im = self.im.resize((width, height))
            if self.im.mode == "1":
                self.img = PIL.ImageTk.BitmapImage(self.im, foreground="white")
            else:
                self.img = PIL.ImageTk.PhotoImage(self.im)
            imgData = self.loadedImages.setdefault(self.image_data[self.currentIndex]['image_file'], dict())
            imgData['image'] = self.img
            imgData['shapes'] = self.image_data[self.currentIndex]['shapes']
        self.img = self.loadedImages[self.image_data[self.currentIndex]['image_file']]['image']
        self.canvas.create_image(0, 0, anchor=tk.NW, image=self.img)
        self.show_drag_box()
    
    # 补充你原来已有的get_next_image_set方法,保持原有逻辑不变即可
    def get_next_image_set(self):
        # 你的原有加载下一组图片的逻辑
        pass
    
    # 补充你原来已有的show_drag_box方法
    def show_drag_box(self):
        # 你的原有绘制框的逻辑
        pass

def loadData(fname):
    with open(fname, mode='r') as f:
        return yaml.load(f.read(), Loader=yaml.SafeLoader)

if __name__ == "__main__":
    data = loadData('config 1.yaml')
    app = App(data)
    app.pack()
    app.mainloop()

注意事项

  • 代码中预留的get_next_image_set、show_drag_box方法请替换为你原有业务逻辑即可
  • 耗时打印格式已经按照要求转为时分秒毫秒的格式,可根据需要调整打印规则

内容的提问来源于stack exchange,提问作者newtocoding

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 15:06:06