This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Missing default root in tkinter simpledialog.py
Type: behavior Stage: resolved
Components: Tkinter Versions: Python 3.10
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: dominic108, epaine, gpolo, serhiy.storchaka
Priority: normal Keywords: patch

Created on 2019-12-31 08:15 by dominic108, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 17775 closed python-dev, 2019-12-31 23:12
Messages (6)
msg359106 - (view) Author: Dominic Mayers (dominic108) * Date: 2019-12-31 08:15
My first "bug" report here. Not sure I am doing it right. It is just that if I execute the code

    import tkinter
    from tkinter import simpledialog
    tkinter.Tk().withdraw() 
    integer_value = simpledialog.askinteger('Dialog Title', 'What is your age?', minvalue=0, maxvalue=100)

It works. In particular, when the line `parent = tkinter._default_root` is executed in simpledialog.py, `_default_root` is defined.  However, if I execute the code

    import tkinter
    from tkinter import simpledialog
    integer_value = simpledialog.askinteger('Dialog Title', 'What is your age?', minvalue=0, maxvalue=100)

which does not have the line `tkinter.Tk().withdraw()` it does not work. When the line `parent = tkinter._default_root` is executed, `_default_root` is not defined. 

I don't know if it is a bug. I don't understand the remainder of the code enough to say. However, the purpose of this line is to define a parent when none is provided. It seem to me that it should be possible to find a parent window...
msg359117 - (view) Author: Dominic Mayers (dominic108) * Date: 2019-12-31 14:44
If it's normal, then the error message should perhaps be more informative and user friendly than just a traceback: 

    Traceback (most recent call last):
      File "./dialog.py", line 6, in <module>
        integer_value = simpledialog.askinteger('Dialog Title', 'What is your age?', minvalue=0, maxvalue=100)
      File "/usr/lib/python3.7/tkinter/simpledialog.py", line 341, in askinteger
        d = _QueryInteger(title, prompt, **kw)
      File "/usr/lib/python3.7/tkinter/simpledialog.py", line 271, in __init__
        Dialog.__init__(self, parent, title)
      File "/usr/lib/python3.7/tkinter/simpledialog.py", line 137, in __init__
        if parent.winfo_viewable():
    AttributeError: 'NoneType' object has no attribute 'winfo_viewable'

If it is not too intrusive, it would be even more user friendly if the code found some parent window.
msg359134 - (view) Author: Dominic Mayers (dominic108) * Date: 2019-12-31 22:08
Again, I just spent a few minutes looking at this, but in the ttk module, in a similar situation, they do:

    if master is None:
        if tkinter._support_default_root:
            master = tkinter._default_root or tkinter.Tk()
        else:
            raise RuntimeError(
                    "No master specified and tkinter is "
                    "configured to not support default root")

Why not do the same for _QueryDialog in simpledialog.py? Actually, I would also withdraw the root that was just created, because the user doesn't expect this extra window. So, I would replace

    if not parent:
         parent = tkinter._default_root
 
with

    if parent is None:
        if tkinter._default_root: 
            parent = tkinter._default_root
        elif tkinter._support_default_root
            parent = tkinter.Tk()
            parent.withdraw()
        else:
            raise RuntimeError(
                    "No parent specified and tkinter is "
                    "configured to not support default root")

This tries to get a parent, if possible, and provides a more useful message when no parent can be found, just as in the ttk module in a similar situation.
msg359146 - (view) Author: Dominic Mayers (dominic108) * Date: 2020-01-01 06:50
Just to add that I realize now that tkinter is designed for applications with a root window, the "application window". That's why little attention is given to a possible missing root. In fact, it's interesting that we have this code in simpledialog.py: 

     
        # Here, if parent is None, we have a run time error.
        if parent.winfo_viewable():
            self.transient(parent)
 
        if title:
            self.title(title)

        self.parent = parent

        self.result = None

        body = Frame(self)
        self.initial_focus = self.body(body)
        body.pack(padx=5, pady=5)

        self.buttonbox()

        if not self.initial_focus:
            self.initial_focus = self

        self.protocol("WM_DELETE_WINDOW", self.cancel)

        if self.parent is not None:
            self.geometry("+%d+%d" % (parent.winfo_rootx()+50,
                                      parent.winfo_rooty()+50))


But, self.parent will never be None. So the geometry always depends on the parent, which is compatible with the view that we are within an application with a root window - there is always a parent.

But it contradicts a bit, in my view, the "simple" in "simpledialog". What about an application with no root window, like git for example, but which, unlike git,  needs to create a simple dialog in some occasions?
msg383391 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2020-12-19 17:46
It is addressed in issue42630. Now a RuntimeError with relevant error message is raised when call askinteger() without explicit parent if there is no default root widget.

Autocreating a top-level root window is not good idea. It pops up an empty window with default size and title and left it open after closing the dialog window. If withdraw it right after creation, it would look less weird, but it may break the following code which calls Tk() and expects it to be set as a default root window.
msg383765 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2020-12-25 21:38
Issue42721 made possible to use these dialogs without default root window. A temporary hidden root window is created for the time of life of a dialog and it is not set as default root window.

Positioning dialog wit5hout parent was improved in issue42685.
History
Date User Action Args
2022-04-11 14:59:24adminsetgithub: 83352
2020-12-25 21:38:03serhiy.storchakasetstatus: open -> closed
resolution: fixed
messages: + msg383765

stage: patch review -> resolved
2020-12-19 17:46:05serhiy.storchakasetmessages: + msg383391
2020-06-14 14:55:24epainesetnosy: + epaine

versions: + Python 3.10, - Python 3.9
2020-01-01 08:42:43xtreaksetnosy: + gpolo, serhiy.storchaka
2020-01-01 06:50:22dominic108setmessages: + msg359146
2020-01-01 00:51:39dominic108setversions: + Python 3.9, - Python 3.7
2019-12-31 23:12:44python-devsetkeywords: + patch
stage: patch review
pull_requests: + pull_request17208
2019-12-31 22:08:04dominic108setmessages: + msg359134
2019-12-31 14:44:00dominic108setmessages: + msg359117
2019-12-31 08:15:47dominic108create