PI Newbie
PI Newbie

Reputation: 3

Way to avoid having multiple windows when using Messagebox (or alternative to it)?

I'm trying to write my first GUI based python program using Tkinter. I have created a base window which holds the menu bar with a couple of options.

One of the options is for a standard 'About' box. When I call the about section with

helpMainMenu.add_command(label="About", command=self.aboutProgram)

It opens the message box, but in a fresh window so there are now two windows showing on the taskbar. Is there any way to stop it opening a new window and use the main one instead, or is there a better way to do it?

The full code is below

#! /usr/bin/python3
from tkinter import *
from tkinter import messagebox
import datetime

timeNow = datetime.datetime.now()
writeYear = 2020 # Enter the year you started writing the program
lineFeed = "\n"
programTitle = "Basic Menu"
programVersion = "Version 1.0.0"
programmerName = " Name ([email protected])"
if timeNow.year > writeYear:
    programAuthor = "©" + str(writeYear) + "-" + str(timeNow.year) + programmerName
else:
    programAuthor = "©" + str(writeYear) + programmerName
aboutMessage = programTitle + lineFeed + programVersion + lineFeed + programAuthor
class Window(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)   
        self.master = master
        self.init_window()

    def init_window(self):
        self.master.title("{} ({})".format(programTitle, programVersion))
        self.pack(fill=BOTH, expand=1)
        menu = Menu(self.master)
        self.master.config(menu=menu)

        fileMainMenu = Menu(menu, tearoff=0) #Create the File menu container
        fileMainMenu.add_command(label="Exit", command=self.programExit) # File menu option
        menu.add_cascade(label="File", menu=fileMainMenu)

        helpMainMenu = Menu(menu, tearoff=0) #Create the Help menu container
        helpMainMenu.add_command(label="About", command=self.aboutProgram)
        menu.add_cascade(label="Help", menu=helpMainMenu)
    def programExit(self):
        exitMsgBox = messagebox.askquestion ("Exit Application","Are you sure you want to exit the application",icon = "warning")
        if exitMsgBox == "yes":
            root.destroy()
            exit()
    def aboutProgram(self):
        messagebox.showinfo("About","About the application", icon = "info")

root = Tk() # root window created. Here, that would be the only window, but
windowHeight = int(root.winfo_screenheight()/100*75) # Set the main window height to 75% of the screen height
windowWidth = int(root.winfo_screenwidth()/100*75) # Set the main window width to 75% of the screen width

screenWidth = int(root.winfo_screenwidth())
screenHeight = int(root.winfo_screenheight())
positionRight = int(root.winfo_screenwidth()/2 - windowWidth/2) # Get the screen width and divide by 2, then minus the result of 'windowWidth' divided by 2
positionDown = int(root.winfo_screenheight()/2 - windowHeight/2) # Get the screen height and divide by 2, then minus the result of 'windowHeight' divided by 2
root.geometry("{}x{}+{}+{}".format(windowWidth, windowHeight, positionRight, positionDown)) # Positions the window in the center of the page.

app = Window(root)
root.mainloop()

Python Version 3.7.3

tkinter.TkVersion 8.6

Upvotes: 0

Views: 283

Answers (1)

Bryan Oakley
Bryan Oakley

Reputation: 386342

The simplest way would be to create a new frame for the "about" page, and then overlay it on top of the main window with place -- one of the few times when place is superior to grid and pack.

You should also do a "grab" on the frame so that all events are funneled to the frame and its children. With a grab, while the popup is visible you can't interact with the widgets on the main window.

Here's a quick example:

def aboutProgram(self):
    # create the frame with a message and a button
    # which destroys the window
    aboutFrame = Frame(self.master, bd=2, relief="groove")
    label = Label(aboutFrame, text="About the application...")
    button = Button(aboutFrame, text="Ok", command=aboutFrame.destroy)
    label.pack(side="top", padx=20, pady=20)
    button.pack(side="bottom", pady=20)

    # overlay the "about" page on top of the root window
    aboutFrame.place(relx=.5, rely=.5, anchor="c")

    # force all events to go to the popup
    aboutFrame.grab_set()

If you want to completely hide the contents of the main window, you can change the place arguments to fill the window:

aboutFrame.place(x=0, y=0, anchor="nw", relwidth=1.0, relheight=1.0)

Upvotes: 1

Related Questions