mirror of https://github.com/python/cpython
gh-72684: Tkinter: provide interface for "tk busy" subcommands (GH-107684)
Add tkinter.Misc methods: tk_busy_hold(), tk_busy_configure(), tk_busy_cget(), tk_busy_forget(), tk_busy_current(), and tk_busy_status().
This commit is contained in:
parent
ca0c6c1f1e
commit
79db9d9a0e
|
@ -144,6 +144,15 @@ pathlib
|
|||
:meth:`~pathlib.Path.is_dir`.
|
||||
(Contributed by Barney Gale in :gh:`77609` and :gh:`105793`.)
|
||||
|
||||
tkinter
|
||||
-------
|
||||
|
||||
* Add :mod:`tkinter` widget methods:
|
||||
:meth:`!tk_busy_hold`, :meth:`!tk_busy_configure`,
|
||||
:meth:`!tk_busy_cget`, :meth:`!tk_busy_forget`,
|
||||
:meth:`!tk_busy_current`, and :meth:`!tk_busy_status`.
|
||||
(Contributed by Miguel, klappnase and Serhiy Storchaka in :gh:`72684`.)
|
||||
|
||||
traceback
|
||||
---------
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import functools
|
||||
import unittest
|
||||
import tkinter
|
||||
from tkinter import TclError
|
||||
import enum
|
||||
from test import support
|
||||
from test.test_tkinter.support import AbstractTkTest, AbstractDefaultRootTest
|
||||
from test.test_tkinter.support import AbstractTkTest, AbstractDefaultRootTest, requires_tk
|
||||
|
||||
support.requires('gui')
|
||||
|
||||
|
@ -36,6 +37,59 @@ class MiscTest(AbstractTkTest, unittest.TestCase):
|
|||
for name in str(b).split('.'):
|
||||
self.assertFalse(name.isidentifier(), msg=repr(name))
|
||||
|
||||
@requires_tk(8, 6, 6)
|
||||
def test_tk_busy(self):
|
||||
root = self.root
|
||||
f = tkinter.Frame(root, name='myframe')
|
||||
f2 = tkinter.Frame(root)
|
||||
f.pack()
|
||||
f2.pack()
|
||||
b = tkinter.Button(f)
|
||||
b.pack()
|
||||
f.tk_busy_hold()
|
||||
with self.assertRaisesRegex(TclError, 'unknown option "-spam"'):
|
||||
f.tk_busy_configure(spam='eggs')
|
||||
with self.assertRaisesRegex(TclError, 'unknown option "-spam"'):
|
||||
f.tk_busy_cget('spam')
|
||||
with self.assertRaisesRegex(TclError, 'unknown option "-spam"'):
|
||||
f.tk_busy_configure('spam')
|
||||
self.assertIsInstance(f.tk_busy_configure(), dict)
|
||||
|
||||
self.assertTrue(f.tk_busy_status())
|
||||
self.assertFalse(root.tk_busy_status())
|
||||
self.assertFalse(f2.tk_busy_status())
|
||||
self.assertFalse(b.tk_busy_status())
|
||||
self.assertIn(f, f.tk_busy_current())
|
||||
self.assertIn(f, f.tk_busy_current('*.m?f*me'))
|
||||
self.assertNotIn(f, f.tk_busy_current('*spam'))
|
||||
|
||||
f.tk_busy_forget()
|
||||
self.assertFalse(f.tk_busy_status())
|
||||
self.assertFalse(f.tk_busy_current())
|
||||
with self.assertRaisesRegex(TclError, "can't find busy window"):
|
||||
f.tk_busy_configure()
|
||||
with self.assertRaisesRegex(TclError, "can't find busy window"):
|
||||
f.tk_busy_forget()
|
||||
|
||||
@requires_tk(8, 6, 6)
|
||||
def test_tk_busy_with_cursor(self):
|
||||
root = self.root
|
||||
if root._windowingsystem == 'aqua':
|
||||
self.skipTest('the cursor option is not supported on OSX/Aqua')
|
||||
f = tkinter.Frame(root, name='myframe')
|
||||
f.pack()
|
||||
f.tk_busy_hold(cursor='gumby')
|
||||
|
||||
self.assertEqual(f.tk_busy_cget('cursor'), 'gumby')
|
||||
f.tk_busy_configure(cursor='heart')
|
||||
self.assertEqual(f.tk_busy_cget('cursor'), 'heart')
|
||||
self.assertEqual(f.tk_busy_configure()['cursor'][4], 'heart')
|
||||
self.assertEqual(f.tk_busy_configure('cursor')[4], 'heart')
|
||||
|
||||
f.tk_busy_forget()
|
||||
with self.assertRaisesRegex(TclError, "can't find busy window"):
|
||||
f.tk_busy_cget('cursor')
|
||||
|
||||
def test_tk_setPalette(self):
|
||||
root = self.root
|
||||
root.tk_setPalette('black')
|
||||
|
|
|
@ -901,6 +901,85 @@ class Misc:
|
|||
"""Ring a display's bell."""
|
||||
self.tk.call(('bell',) + self._displayof(displayof))
|
||||
|
||||
def tk_busy_cget(self, option):
|
||||
"""Return the value of busy configuration option.
|
||||
|
||||
The widget must have been previously made busy by
|
||||
tk_busy_hold(). Option may have any of the values accepted by
|
||||
tk_busy_hold().
|
||||
"""
|
||||
return self.tk.call('tk', 'busy', 'cget', self._w, '-'+option)
|
||||
busy_cget = tk_busy_cget
|
||||
|
||||
def tk_busy_configure(self, cnf=None, **kw):
|
||||
"""Query or modify the busy configuration options.
|
||||
|
||||
The widget must have been previously made busy by
|
||||
tk_busy_hold(). Options may have any of the values accepted by
|
||||
tk_busy_hold().
|
||||
|
||||
Please note that the option database is referenced by the widget
|
||||
name or class. For example, if a Frame widget with name "frame"
|
||||
is to be made busy, the busy cursor can be specified for it by
|
||||
either call:
|
||||
|
||||
w.option_add('*frame.busyCursor', 'gumby')
|
||||
w.option_add('*Frame.BusyCursor', 'gumby')
|
||||
"""
|
||||
if kw:
|
||||
cnf = _cnfmerge((cnf, kw))
|
||||
elif cnf:
|
||||
cnf = _cnfmerge(cnf)
|
||||
if cnf is None:
|
||||
return self._getconfigure(
|
||||
'tk', 'busy', 'configure', self._w)
|
||||
if isinstance(cnf, str):
|
||||
return self._getconfigure1(
|
||||
'tk', 'busy', 'configure', self._w, '-'+cnf)
|
||||
self.tk.call('tk', 'busy', 'configure', self._w, *self._options(cnf))
|
||||
busy_config = busy_configure = tk_busy_config = tk_busy_configure
|
||||
|
||||
def tk_busy_current(self, pattern=None):
|
||||
"""Return a list of widgets that are currently busy.
|
||||
|
||||
If a pattern is given, only busy widgets whose path names match
|
||||
a pattern are returned.
|
||||
"""
|
||||
return [self._nametowidget(x) for x in
|
||||
self.tk.splitlist(self.tk.call(
|
||||
'tk', 'busy', 'current', pattern))]
|
||||
busy_current = tk_busy_current
|
||||
|
||||
def tk_busy_forget(self):
|
||||
"""Make this widget no longer busy.
|
||||
|
||||
User events will again be received by the widget.
|
||||
"""
|
||||
self.tk.call('tk', 'busy', 'forget', self._w)
|
||||
busy_forget = tk_busy_forget
|
||||
|
||||
def tk_busy_hold(self, **kw):
|
||||
"""Make this widget appear busy.
|
||||
|
||||
The specified widget and its descendants will be blocked from
|
||||
user interactions. Normally update() should be called
|
||||
immediately afterward to insure that the hold operation is in
|
||||
effect before the application starts its processing.
|
||||
|
||||
The only supported configuration option is:
|
||||
|
||||
cursor: the cursor to be displayed when the widget is made
|
||||
busy.
|
||||
"""
|
||||
self.tk.call('tk', 'busy', 'hold', self._w, *self._options(kw))
|
||||
busy = busy_hold = tk_busy = tk_busy_hold
|
||||
|
||||
def tk_busy_status(self):
|
||||
"""Return True if the widget is busy, False otherwise."""
|
||||
return self.tk.getboolean(self.tk.call(
|
||||
'tk', 'busy', 'status', self._w))
|
||||
busy_status = tk_busy_status
|
||||
|
||||
# Clipboard handling:
|
||||
def clipboard_get(self, **kw):
|
||||
"""Retrieve data from the clipboard on window's display.
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
Add :mod:`tkinter` widget methods: :meth:`!tk_busy_hold`,
|
||||
:meth:`!tk_busy_configure`, :meth:`!tk_busy_cget`, :meth:`!tk_busy_forget`,
|
||||
:meth:`!tk_busy_current`, and :meth:`!tk_busy_status`.
|
Loading…
Reference in New Issue