3

I am trying to open a simple dialog window, in which the user enters a choice based on a menu presented on the root window. When I run the code however the dialog opens directly above the menu in the root window obscuring it from sight. Is there a way to open the dialog so it opens next to the root window as shown in the attached image.

enter image description here

I have checked this link and it does not seem there is any positioning arguments for simple dialogs. I have also tried with toplevel but it got messy with multiple windows open.

My code is as follows:

from Tkinter import *
import tkSimpleDialog

root = Tk()
root.lift()


Label(root, text = "Menu Choices:").grid(row=1, column =0)
Label(root, text='1. Baloney and cheese').grid(row=2, column=0, pady=4)
Label(root, text='2. Roast chicken and gravy').grid(row=3, column=0, pady=4)
Label(root, text='3. Pear salad').grid(row=4, column=0, pady=4)
Label(root, text='4. Cateloupe and brocoli soup').grid(row=5, column=0, pady=4)

people = ["Liam","Henry","Paula"]

menuChoice = []

for i in people:
    c = tkSimpleDialog.askinteger('Franks Restaurant', 'Please choose your meal?', parent = root)
    menuChoice.append(c)

root.mainloop()
alkey
  • 986
  • 4
  • 16
  • 33
  • this is a very odd way of getting input from a user, and not how GUIs are designed to work. Why do you not make the menu choices buttons or radiobuttons, and avoid the dialog altogether? – Bryan Oakley Oct 18 '16 at 14:21
  • You should just add an entry or a listbox to the main window. – Dashadower Oct 18 '16 at 14:24
  • @BryanOakley + Dashadower Thanks for your comments but this is just an example of a problem where I wanted to generate pop ups and assign. As you say, maybe it is best to display all the information on the root screen but as I was iterating through a list of choices and then updating a dictionary entry with the choice I decided to do it this way. Perhaps it is just not possible to anchor a simple dialog box to the side of a root window..... – alkey Oct 18 '16 at 21:36
  • @Bryan, whether using **tkSimpleDialog** is a good practice or not, is another question. The question here is very simple and it can be reduced to this: "How can I position **tkSimpleDialog** where I want?" It is a valid and very good question. I have the same problem. – Apostolos Mar 11 '18 at 22:13
  • @alkey, your question is a million-dollar question! :) This is what I concluded after a long research, in which I found the same exact question, unanswered, in 3 more places. What is really annoying is that the dialog box is placed at random, usually near the top left corner of the screen. They could at least place at the center! – Apostolos Mar 11 '18 at 23:33

3 Answers3

1

One way is to use a Toplevel widget. And it's not messy at all. Anyway, to place your input frame where you want, you have first to set dimensions and a position of your main (root) frame:

from Tkinter import *
import ttk

root = Tk()
root.lift()
w = 300; h = 200; x = 10; y = 10
root.geometry('%dx%d+%d+%d' % (w, h, x, y))

Label(root, text = "Menu Choices:").grid(row=1, column =0)
Label(root, text='1. Baloney and cheese').grid(row=2, column=0, pady=4)
Label(root, text='2. Roast chicken and gravy').grid(row=3, column=0, pady=4)
Label(root, text='3. Pear salad').grid(row=4, column=0, pady=4)
Label(root, text='4. Cateloupe and brocoli soup').grid(row=5, column=0, pady=4)

def store_entry():
  print "Entry stored as "+ent.get()

def exit_entry():
  print "Entry cancelled"
  top.destroy()

top = Toplevel()
top.title('Franks Restaurant')
top.geometry("%dx%d+%d+%d" % (w, h, w+x+20, y))
Label(top, text='Please choose your meal').place(x=10,y=10)
ent = Entry(top); ent.place(x=10, y=50); ent.focus()
Button(top, text="OK", command=store_entry).place(x=10, y=150) 
Button(top, text="Cancel", command=exit_entry).place(x=60, y=150)  

root.mainloop()

This is an example of having user input window positioned where you want. You need to implement it for validation and storing of the user input and for as many users as you need.

Apostolos
  • 3,115
  • 25
  • 28
1

the Tk library actually has a function that does this although it is nominally 'private'. You can use it as follows.

import tkinter as tk

root = tk.Tk()
root.wm_geometry("800x600")
dialog = tk.Toplevel(root)
root_name = root.winfo_pathname(root.winfo_id())
dialog_name = dialog.winfo_pathname(dialog.winfo_id())
root.tk.eval('tk::PlaceWindow {0} widget {1}'.format(dialog_name, root_name))
root.mainloop()

This will place your dialog centred over the specified window (in this case th root window).

Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321
patthoyts
  • 32,320
  • 3
  • 62
  • 93
1
  • Here is an example of positioning a dialog relative to the main window.
  • Each time you open the dialog it will track the root window position.
  • it uses the geometry to set the left and top position of the dialog

'

import tkinter as tk

try:  # allows the text to be more crisp on a high dpi display
  from ctypes import windll
  windll.shcore.SetProcessDpiAwareness(1)
except:
  pass

# ----------------------------------------------------------------------------
class CustomDialog:
    def __init__(self, parent):
        self.top = tk.Toplevel(parent)

        xPos = root.winfo_x()
        yPos = root.winfo_y()
        posStr = "+" + str(xPos + 160) + "+" + str(yPos)
        self.top.geometry(posStr)

        tk.Label(self.top, text="Dlg is positioned relative to root window.").pack()
        tk.Button(self.top, text="Ok", command=self.Ok).pack()

    def Ok(self):
        self.top.destroy()

# ----------------------------------------------------------------------------
def onOpenDlg():
    inputDialog = CustomDialog(root)
    root.wait_window(inputDialog.top)

# ----------------------------------------------------------------------------
root = tk.Tk()
tk.Label(root, text="Position Dlg Example").pack()
tk.Button(root, text="Open Dlg", command=onOpenDlg).pack()

root.mainloop()

'

Louie
  • 91
  • 4