Tkinter: simple dialog box appears behind main root page on raspberry pi

656 Views Asked by At

I've spent forever looking for a solution to this. There are tons of posts on stackoverflow about this problem, which have gotten me this far and now I am stumped where to go next. I need to use the dock attribute on root because it needs to appear above all other windows, and without the bar at the top. The splash attribute almost works, but then other windows can pop up on top of it too when clicking on the screen where their borders are behind the app. For some reason the code below does not work on a raspberry pi, the simpledialog box appears behind the root application, so you cannot see it at all.

However, it works on my linux laptop. The only thing I could think of is that it is a window manager issue. From following the advice of more posts, I looked at the file "/etc/X11/default-display-manager", my raspberry pi is running default raspbian which utilizes the lightdm manager and my laptop uses gdm3. With some more research it seems raspberry pis can struggle to run gdm3. I tried downloading GNOME (which I think is gdm3) by running "sudo tasksel" in the command window and it still ran into the same problem. At this point I'm willing to try pretty much anything.

import tkinter as tk
from tkinter import simpledialog, messagebox
Root = tk.Tk()
Root.attributes('-type', 'dock')
width = Root.winfo_screenwidth()
height = Root.winfo_screenheight() - 30
Root.geometry("%dx%d+0+0" % (width, height))
button = tk.Button(Root, text="exit", command=Root.destroy).pack(pady=20)
Root.deiconify()
Root.lift()
Root.focus_force()
J = tk.simpledialog.askfloat("Input", "Number of points per scan:",parent=Root,minvalue=1000, maxvalue=7000)
Root.mainloop()
1

There are 1 best solutions below

6
On

You are looking for the attribute -topmost witch just puts a window on top always (unless there are multiple windows on topmost), window manager have two kinds of z-axis, the layers overlap by level and the layer items overlap by focus history.

import tkinter as tk

class App_Dialog(tk.Tk):

    def dial_return(self):
        self.callback(
            self.entry.get()
        )

    def __init__(self, text, callback, master):
        tk.Tk.__init__(self)
        mw, mh = master.winfo_width(), master.winfo_height()
        self.geometry('300x200+{0}+{1}'.format(
            (mw // 2) - 150, (mh // 2) - 100
        ))
        self.attributes('-topmost', True)
        self.overrideredirect(True)
        self.config(bg='#A0A0A0')
        self.callback = callback
        self.update()

        tk.Label(self, text=text).pack(anchor=tk.CENTER)
        self.entry = tk.Entry(self)
        self.entry.pack(anchor=tk.CENTER)
        tk.Button(
            self, text='Save', command=self.dial_return
        ).pack(anchor=tk.CENTER)


class App(tk.Tk):

    def dialog_callback(self, text):
        self.list.insert(0, text)
        self._dialog.destroy()
        self._dialog = None

    def dialog(self, text, callback):
        if self._dialog is None:
            self._dialog = App_Dialog(
                text, callback, self
            )

    def quit(self):
        if self._dialog is not None:
            self._dialog.quit()
        self.tk.quit()

    def __init__(self):
        tk.Tk.__init__(self)
        self.overrideredirect(True)
        self.state('zoomed')

        self.list = tk.Listbox()
        self._dialog = None

        self.b_top = tk.Button(
            self, text='tk::top',
            command=lambda: self.dialog(
                'Fill this:', self.dialog_callback
            )
        )
        self.b_quit = tk.Button(
            self, text='Close',
            command=lambda: self.quit()
        )
        self.b_top.pack(anchor=tk.CENTER)
        self.b_quit.pack(anchor=tk.CENTER)
        self.list.pack(anchor=tk.CENTER)

if __name__ == '__main__':
    app = App()
    app.mainloop()