robertlugg / easygui

easygui for Python
http://easygui.readthedocs.org/en/master/
BSD 3-Clause "New" or "Revised" License
451 stars 114 forks source link

diropenbox and fileopenbox do not display on top #215

Open ajmcgraw opened 1 year ago

ajmcgraw commented 1 year ago

I saw that the code

    localRoot = tk.Tk()
    localRoot.withdraw()
    localRoot.attributes("-topmost", True)

was added in this PR, https://github.com/robertlugg/easygui/pull/199 but this still does not make the file open boxes display at the front.

I am running python 3.10.6 with anaconda on Windows 10. I downloaded easygui initially from conda, and then downloaded directly from github with pip to insure I wasn't missing any updates. pip install git+https://github.com/robertlugg/easygui

If I take the two functions from fileopen_box.py and diropen_box.py and paste them in my code, as well as adding the imports, both of the functions work properly and the boxes display on the top of my project.

import tkinter as tk
import easygui.boxes.utils as ut
import easygui.boxes.fileboxsetup as fbs

# this function is from https://github.com/robertlugg/easygui/blob/master/easygui/boxes/diropen_box.py
def diropenbox(msg=None, title=None, default=None):
    """
    A dialog to get a directory name.
    Returns the name of a directory, or None if user chose to cancel.
    If the "default" argument specifies a directory name, and that
    directory exists, then the dialog box will start with that directory.
    :param str msg: used in the window title on some platforms
    :param str title: the window title
    :param str default: starting directory when dialog opens
    :return: Normalized path selected by user
    """
    title = ut.getFileDialogTitle(msg, title)
    localRoot = tk.Tk()
    localRoot.withdraw()
    localRoot.attributes("-topmost", True)
    if not default:
        default = None
    localRoot.update() #fix ghost window issue #119 on mac.
    f = ut.tk_FileDialog.askdirectory(
        parent=localRoot, title=title, initialdir=default, initialfile=None
    )
    localRoot.destroy()
    if not f:
        return None
    return os.path.normpath(f)

# this function is from https://github.com/robertlugg/easygui/blob/master/easygui/boxes/fileopen_box.py
def fileopenbox(msg=None, title=None, default='*', filetypes=None, multiple=False):
    """
    Displays an "open file" dialog box and returns the selected file as a string.
    The "default" argument specifies a filepath that (normally)
    contains one or more wildcards.
    fileopenbox() will display only files that match the default filepath.
    If omitted, defaults to "\\*" (all files in the current directory).
    WINDOWS EXAMPLE::
        ...default="c:/myjunk/*.py"
    will open in directory c:\\myjunk\\ and show all Python files.
    WINDOWS EXAMPLE::
        ...default="c:/myjunk/test*.py"
    will open in directory c:\\myjunk\\ and show all Python files
    whose names begin with "test".
    Note that on Windows, fileopenbox automatically changes the path
    separator to the Windows path separator (backslash).
    **About the "filetypes" argument**
    If specified, it should contain a list of items,
    where each item is either:
    - a string containing a filemask          # e.g. "\\*.txt"
    - a list of strings, where all of the strings except the last one
      are filemasks (each beginning with "\\*.",
      such as "\\*.txt" for text files, "\\*.py" for Python files, etc.).
      and the last string contains a filetype description
    EXAMPLE::
        filetypes = ["*.css", ["*.htm", "*.html", "HTML files"]  ]
    .. note:: If the filetypes list does not contain ("All files","*"), it will be added.
    If the filetypes list does not contain a filemask that includes
    the extension of the "default" argument, it will be added.
    For example, if default="\\*abc.py"
    and no filetypes argument was specified, then
    "\\*.py" will automatically be added to the filetypes argument.
    :param str msg: the msg to be displayed.
    :param str title: the window title
    :param str default: filepath with wildcards
    :param object filetypes: filemasks that a user can choose, e.g. "\\*.txt"
    :param bool multiple: If true, more than one file can be selected
    :return: the name of a file, or None if user chose to cancel
    """
    localRoot = tk.Tk()
    localRoot.withdraw()
    localRoot.attributes("-topmost", True)

    initialbase, initialfile, initialdir, filetypes = fbs.fileboxSetup(
        default, filetypes)

    # ------------------------------------------------------------
    # if initialfile contains no wildcards; we don't want an
    # initial file. It won't be used anyway.
    # Also: if initialbase is simply "*", we don't want an
    # initialfile; it is not doing any useful work.
    # ------------------------------------------------------------
    if (initialfile.find("*") < 0) and (initialfile.find("?") < 0):
        initialfile = None
    elif initialbase == "*":
        initialfile = None

    func = ut.tk_FileDialog.askopenfilenames if multiple else ut.tk_FileDialog.askopenfilename
    ret_val = func(parent=localRoot,
                   title=ut.getFileDialogTitle(msg, title),
                   initialdir=initialdir, initialfile=initialfile,
                   filetypes=filetypes
                   )
    if not ret_val or ret_val == '':
        localRoot.destroy()
        return None
    if multiple:
        f = [os.path.normpath(x) for x in localRoot.tk.splitlist(ret_val)]
    else:
        try:
            f = os.path.normpath(ret_val)
        except AttributeError as e:
            print("ret_val is {}".format(ret_val))
            raise e
    localRoot.destroy()

    if not f:
        return None
    return f