wait_dialog.py 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #
  2. # Copyright (c) Contributors to the Open 3D Engine Project.
  3. # For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. #
  5. # SPDX-License-Identifier: Apache-2.0 OR MIT
  6. #
  7. import tkinter as tk
  8. class WaitDialog:
  9. """
  10. A cancelable modal dialog that can be helpful to
  11. notify the user that some work is being done
  12. in the background.
  13. """
  14. MAX_DOTS = 4
  15. def __init__(self, tk_parent, work_message: str, cancel_cb):
  16. self._tk_parent = tk_parent
  17. self._dialog = tk.Toplevel(tk_parent)
  18. # Display the dialog at the center of its parent.
  19. w = 340
  20. h = 100
  21. self._dialog.wait_visibility()
  22. x = tk_parent.winfo_x() + tk_parent.winfo_width()//2 - w//2
  23. y = tk_parent.winfo_y() + tk_parent.winfo_height()//2 - h//2
  24. self._dialog.geometry(f"{w}x{h}+{x}+{y}")
  25. self._dialog.title("Operation In Progress...")
  26. self._dialog.grab_set() # Make the dialog modal.
  27. self._cancel_cb = cancel_cb
  28. lbl = tk.Label(self._dialog, text=work_message)
  29. lbl.pack()
  30. # This is a simple string that will be updated periodically
  31. # and its value will be bound to a tk Label widget.
  32. self._progress_string_var = tk.StringVar()
  33. self._progress_string_var.set("")
  34. self._progress_sign = 1 # Start positive
  35. lbl = tk.Label(self._dialog, textvariable=self._progress_string_var)
  36. lbl.pack()
  37. # The Cancel button
  38. button = tk.Button(self._dialog, text="Cancel", command=self._on_cancel_button)
  39. button.pack()
  40. def _on_cancel_button(self):
  41. self.close()
  42. self._cancel_cb()
  43. def close(self):
  44. """
  45. Call this function when the job is done. Will close
  46. and destroy this dialog
  47. """
  48. self._dialog.destroy()
  49. self._tk_parent.focus_set()
  50. def on_tick(self, delta_seconds: float):
  51. progress = self._progress_string_var.get()
  52. if self._progress_sign > 0:
  53. progress = f"{progress}*"
  54. if len(progress) >= self.MAX_DOTS:
  55. self._progress_sign = -1
  56. else:
  57. num_dots = len(progress)
  58. if num_dots < 1:
  59. self._progress_sign = 1
  60. else:
  61. progress = "*" * (num_dots - 1)
  62. self._progress_string_var.set(progress)
  63. # class WaitDialog END
  64. ######################################################