鱼C论坛

 找回密码
 立即注册
楼主: kerln888

[已解决]html5 左边菜单栏保持展开或者关闭的状态

  [复制链接]
 楼主| 发表于 4 小时前 | 显示全部楼层
@FishC python tkiner两个窗口切换时,用progressbar转场动画
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 4 小时前 | 显示全部楼层
kerln888 发表于 2026-01-22 12:51
@FishC python tkiner两个窗口切换时,用progressbar ...


在 Tkinter 中实现两个窗口切换时的进度条转场动画,可以按照以下思路进行:

1. 创建一个独立的进度条窗口作为过渡界面
2. 在关闭当前窗口时显示进度条窗口
3. 进度条完成后打开目标窗口

以下是示例代码:


  1. import tkinter as tk
  2. from tkinter import ttk
  3. import time

  4. class MainApp:
  5.     def __init__(self):
  6.         self.root = tk.Tk()
  7.         self.root.title("主窗口")
  8.         
  9.         # 窗口1的内容
  10.         self.frame1 = tk.Frame(self.root, width=400, height=300)
  11.         self.frame1.pack()
  12.         
  13.         tk.Label(self.frame1, text="这是窗口1", font=("Arial", 20)).pack(pady=50)
  14.         tk.Button(self.frame1, text="切换到窗口2",
  15.                  command=self.switch_to_window2).pack()
  16.    
  17.     def switch_to_window2(self):
  18.         # 创建过渡窗口
  19.         self.show_transition_window()
  20.         
  21.         # 短暂延迟后关闭当前窗口
  22.         self.root.after(100, self.open_window2)
  23.    
  24.     def show_transition_window(self):
  25.         # 创建过渡窗口
  26.         self.transition = tk.Toplevel()
  27.         self.transition.title("加载中...")
  28.         self.transition.geometry("300x150")
  29.         
  30.         # 使过渡窗口模态化
  31.         self.transition.grab_set()
  32.         
  33.         # 添加进度条
  34.         self.progress = ttk.Progressbar(
  35.             self.transition,
  36.             mode='indeterminate',
  37.             length=200
  38.         )
  39.         self.progress.pack(pady=40)
  40.         
  41.         # 添加标签
  42.         tk.Label(self.transition, text="正在切换窗口...").pack()
  43.         
  44.         # 开始进度条动画
  45.         self.progress.start(10)
  46.    
  47.     def open_window2(self):
  48.         # 关闭窗口1
  49.         self.root.withdraw()
  50.         
  51.         # 创建窗口2
  52.         self.window2 = tk.Toplevel()
  53.         self.window2.title("窗口2")
  54.         self.window2.geometry("400x300")
  55.         
  56.         # 窗口2的内容
  57.         tk.Label(self.window2, text="这是窗口2", font=("Arial", 20)).pack(pady=50)
  58.         tk.Button(self.window2, text="返回窗口1",
  59.                  command=self.back_to_window1).pack()
  60.         
  61.         # 关闭过渡窗口
  62.         self.transition.destroy()
  63.         
  64.         # 绑定窗口关闭事件
  65.         self.window2.protocol("WM_DELETE_WINDOW", self.on_closing)
  66.    
  67.     def back_to_window1(self):
  68.         # 显示过渡窗口
  69.         self.show_transition_window()
  70.         
  71.         # 短暂延迟后切换回窗口1
  72.         self.window2.after(100, self.return_to_window1)
  73.    
  74.     def return_to_window1(self):
  75.         # 关闭窗口2
  76.         self.window2.destroy()
  77.         
  78.         # 重新显示窗口1
  79.         self.root.deiconify()
  80.         
  81.         # 关闭过渡窗口
  82.         self.transition.destroy()
  83.    
  84.     def on_closing(self):
  85.         # 关闭所有窗口并退出程序
  86.         self.root.destroy()
  87.    
  88.     def run(self):
  89.         self.root.mainloop()

  90. if __name__ == "__main__":
  91.     app = MainApp()
  92.     app.run()
复制代码


如果想要使用确定模式的进度条(显示具体进度),可以修改为以下版本:


  1. import tkinter as tk
  2. from tkinter import ttk
  3. import threading

  4. class ProgressTransition:
  5.     def __init__(self, callback):
  6.         self.callback = callback
  7.         
  8.         # 创建过渡窗口
  9.         self.window = tk.Toplevel()
  10.         self.window.title("加载中...")
  11.         self.window.geometry("300x150")
  12.         
  13.         # 使窗口居中
  14.         self.window.update_idletasks()
  15.         width = self.window.winfo_width()
  16.         height = self.window.winfo_height()
  17.         x = (self.window.winfo_screenwidth() // 2) - (width // 2)
  18.         y = (self.window.winfo_screenheight() // 2) - (height // 2)
  19.         self.window.geometry(f'{width}x{height}+{x}+{y}')
  20.         
  21.         # 添加进度条
  22.         self.progress = ttk.Progressbar(
  23.             self.window,
  24.             mode='determinate',
  25.             length=250
  26.         )
  27.         self.progress.pack(pady=30)
  28.         
  29.         # 添加标签
  30.         self.label = tk.Label(self.window, text="正在切换... 0%")
  31.         self.label.pack()
  32.         
  33.         # 开始进度更新线程
  34.         self.thread = threading.Thread(target=self.update_progress)
  35.         self.thread.daemon = True
  36.         self.thread.start()
  37.    
  38.     def update_progress(self):
  39.         for i in range(101):
  40.             time.sleep(0.02)  # 控制速度
  41.             
  42.             # 使用after方法在主线程中更新UI
  43.             self.window.after(0, self.update_ui, i)
  44.         
  45.         # 完成后执行回调
  46.         self.window.after(0, self.complete)
  47.    
  48.     def update_ui(self, value):
  49.         self.progress['value'] = value
  50.         self.label.config(text=f"正在切换... {value}%")
  51.    
  52.     def complete(self):
  53.         self.window.destroy()
  54.         self.callback()

  55. # 使用示例
  56. class TwoWindowApp:
  57.     def __init__(self):
  58.         self.root = tk.Tk()
  59.         self.root.title("双窗口应用")
  60.         
  61.         self.create_window1()
  62.    
  63.     def create_window1(self):
  64.         self.window1 = tk.Frame(self.root, width=400, height=300)
  65.         self.window1.pack()
  66.         
  67.         tk.Label(self.window1, text="窗口1", font=("Arial", 24)).pack(pady=50)
  68.         tk.Button(self.window1, text="切换到窗口2",
  69.                  command=self.go_to_window2, width=15, height=2).pack()
  70.    
  71.     def go_to_window2(self):
  72.         # 显示过渡窗口
  73.         self.transition = ProgressTransition(self.show_window2)
  74.    
  75.     def show_window2(self):
  76.         # 清除窗口1
  77.         self.window1.pack_forget()
  78.         
  79.         # 创建窗口2
  80.         self.window2 = tk.Frame(self.root, width=400, height=300)
  81.         self.window2.pack()
  82.         
  83.         tk.Label(self.window2, text="窗口2", font=("Arial", 24)).pack(pady=50)
  84.         tk.Button(self.window2, text="返回窗口1",
  85.                  command=self.return_to_window1, width=15, height=2).pack()
  86.    
  87.     def return_to_window1(self):
  88.         # 显示过渡窗口
  89.         self.transition = ProgressTransition(self.show_window1)
  90.    
  91.     def show_window1(self):
  92.         # 清除窗口2
  93.         self.window2.pack_forget()
  94.         
  95.         # 重新显示窗口1
  96.         self.window1.pack()
  97.    
  98.     def run(self):
  99.         self.root.mainloop()

  100. if __name__ == "__main__":
  101.     app = TwoWindowApp()
  102.     app.run()
复制代码


主要思路说明:
1. 使用 Toplevel() 创建独立的过渡窗口
2. 使用 ttk.Progressbar 创建进度条组件
3. 有两种进度条模式可选:
   - indeterminate:不确定模式,循环动画
   - determinate:确定模式,显示具体进度
4. 使用多线程或 after() 方法更新进度
5. 进度完成后自动关闭过渡窗口并打开目标窗口

提示:可以根据需要自定义过渡窗口的样式、动画速度和完成后的回调操作。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 4 小时前 | 显示全部楼层
@FishC python tkiner进行大运算量计算时,用progressbar把做进度条,画面会卡死,没有进度条效果
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 4 小时前 | 显示全部楼层
kerln888 发表于 2026-01-22 13:01
@FishC python tkiner进行大运算量计算时,用progress ...

使用 Tkinter 进行大运算量计算时,进度条卡死是因为计算任务阻塞了 GUI 主线程。解决方法是使用多线程将计算任务放到后台运行,并通过线程安全的方式更新进度条。


问题原因:
Tkinter 的 GUI 在主线程中运行,当进行大运算量计算时,会占用主线程,导致界面无法更新,进度条看起来就会卡死。

解决方案:
使用 threading 模块创建后台线程执行计算任务,同时通过 queue.Queue 传递进度信息,并利用 Tkinter 的 after 方法在主线程中更新进度条。

示例代码:

  1. import tkinter as tk
  2. from tkinter import ttk
  3. import threading
  4. import queue
  5. import time

  6. class App:
  7.     def __init__(self, root):
  8.         self.root = root
  9.         self.root.title("进度条示例")

  10.         # 创建进度条
  11.         self.progress = ttk.Progressbar(root, length=300, mode='determinate')
  12.         self.progress.pack(pady=20)

  13.         # 创建开始按钮
  14.         self.start_button = tk.Button(root, text="开始计算", command=self.start_calculation)
  15.         self.start_button.pack(pady=10)

  16.         # 创建队列用于线程间通信
  17.         self.queue = queue.Queue()

  18.     def start_calculation(self):
  19.         # 禁用按钮,防止重复点击
  20.         self.start_button.config(state='disabled')
  21.         # 启动后台线程
  22.         thread = threading.Thread(target=self.calculation_task)
  23.         thread.daemon = True  # 设置为守护线程
  24.         thread.start()
  25.         # 启动队列检查,用于更新进度条
  26.         self.check_queue()

  27.     def calculation_task(self):
  28.         # 模拟大运算量计算
  29.         total = 100
  30.         for i in range(total + 1):
  31.             time.sleep(0.05)  # 模拟计算耗时
  32.             # 将进度信息放入队列
  33.             self.queue.put(i)
  34.         # 计算完成,放入特殊信号
  35.         self.queue.put('done')

  36.     def check_queue(self):
  37.         try:
  38.             # 非阻塞获取队列中的消息
  39.             while True:
  40.                 msg = self.queue.get_nowait()
  41.                 if msg == 'done':
  42.                     # 计算完成,恢复按钮
  43.                     self.start_button.config(state='normal')
  44.                     break
  45.                 else:
  46.                     # 更新进度条
  47.                     self.progress['value'] = msg
  48.         except queue.Empty:
  49.             pass
  50.         # 每100毫秒检查一次队列
  51.         self.root.after(100, self.check_queue)

  52. if __name__ == "__main__":
  53.     root = tk.Tk()
  54.     app = App(root)
  55.     root.mainloop()
复制代码


注意事项:
1.  Tkinter 不是线程安全的,所有 GUI 更新操作(如进度条更新)必须在主线程中进行。
2.  示例中使用了 queue.Queue 来传递进度值,确保线程安全。
3.  after 方法用于定期检查队列,避免阻塞主线程。
4.  计算线程完成后,通过队列发送 'done' 信号来恢复按钮状态。

通过这种方式,计算任务在后台运行,GUI 保持响应,进度条可以正常更新。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 4 小时前 | 显示全部楼层
@FishC python tkiner执行大量数据库语句时,用progressbar把做进度条,画面会卡死,没有进度条效果
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 4 小时前 | 显示全部楼层
kerln888 发表于 2026-01-22 13:09
@FishC python tkiner执行大量数据库语句时,用progre ...


在Tkinter中执行大量数据库操作时界面卡死,是因为数据库操作阻塞了主线程(GUI线程)。需要使用多线程或异步处理来解决。以下是解决方案:


  1. import tkinter as tk
  2. from tkinter import ttk
  3. import threading
  4. import time
  5. import sqlite3

  6. class DatabaseProgressApp:
  7.     def __init__(self, root):
  8.         self.root = root
  9.         self.root.title("数据库操作进度条")
  10.         
  11.         # 创建进度条
  12.         self.progress = ttk.Progressbar(root, length=300, mode='determinate')
  13.         self.progress.pack(pady=20)
  14.         
  15.         # 创建开始按钮
  16.         self.start_button = tk.Button(root, text="开始数据库操作", command=self.start_database_task)
  17.         self.start_button.pack(pady=10)
  18.         
  19.         # 创建标签用于显示状态
  20.         self.status_label = tk.Label(root, text="准备就绪")
  21.         self.status_label.pack(pady=10)
  22.         
  23.     def start_database_task(self):
  24.         # 禁用按钮,防止重复点击
  25.         self.start_button.config(state='disabled')
  26.         self.status_label.config(text="正在执行数据库操作...")
  27.         
  28.         # 在新线程中执行数据库操作
  29.         thread = threading.Thread(target=self.run_database_operations, daemon=True)
  30.         thread.start()
  31.         
  32.         # 启动进度条更新检查
  33.         self.check_progress()
  34.    
  35.     def run_database_operations(self):
  36.         """在后台线程中执行数据库操作"""
  37.         try:
  38.             # 连接数据库(这里使用SQLite示例)
  39.             conn = sqlite3.connect(':memory:')  # 使用内存数据库作为示例
  40.             cursor = conn.cursor()
  41.             
  42.             # 创建示例表
  43.             cursor.execute("CREATE TABLE test (id INTEGER, data TEXT)")
  44.             
  45.             # 模拟大量数据库操作
  46.             total_operations = 1000
  47.             for i in range(total_operations):
  48.                 # 执行数据库插入
  49.                 cursor.execute("INSERT INTO test VALUES (?, ?)", (i, f"数据{i}"))
  50.                
  51.                 # 更新进度(通过线程安全的方式)
  52.                 progress_value = (i + 1) * 100 / total_operations
  53.                 self.root.after(0, self.update_progress, progress_value)
  54.                
  55.                 # 模拟耗时操作
  56.                 time.sleep(0.01)
  57.             
  58.             conn.commit()
  59.             conn.close()
  60.             
  61.             # 完成后的操作
  62.             self.root.after(0, self.task_completed)
  63.             
  64.         except Exception as e:
  65.             # 错误处理
  66.             self.root.after(0, self.task_failed, str(e))
  67.    
  68.     def update_progress(self, value):
  69.         """更新进度条(在主线程中执行)"""
  70.         self.progress['value'] = value
  71.         self.status_label.config(text=f"进度: {value:.1f}%")
  72.    
  73.     def check_progress(self):
  74.         """定期检查进度条是否需要更新"""
  75.         self.root.after(100, self.check_progress)
  76.    
  77.     def task_completed(self):
  78.         """任务完成后的回调"""
  79.         self.status_label.config(text="数据库操作完成!")
  80.         self.start_button.config(state='normal')
  81.    
  82.     def task_failed(self, error_msg):
  83.         """任务失败后的回调"""
  84.         self.status_label.config(text=f"错误: {error_msg}")
  85.         self.start_button.config(state='normal')

  86. if __name__ == "__main__":
  87.     root = tk.Tk()
  88.     app = DatabaseProgressApp(root)
  89.     root.geometry("400x200")
  90.     root.mainloop()
复制代码


关键点说明:

1. 使用 threading.Thread 创建后台线程执行数据库操作,避免阻塞GUI主线程。

2. 使用 self.root.after(0, ...) 在主线程中更新GUI,这是线程安全的。

3. 通过回调函数处理任务完成和失败的情况。

4. 操作期间禁用按钮,防止重复点击。

5. 使用 daemon=True 确保程序退出时线程正确终止。

注意事项:
- 数据库操作在后台线程执行,GUI保持响应
- 所有GUI更新都在主线程中进行
- 实际使用时需要根据具体数据库调整操作代码
- 对于更复杂的情况,可以考虑使用队列(queue)进行线程间通信

这样就能实现不卡顿的进度条显示了!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2026-1-22 17:45

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表