2

I wanted to cerate a message window on top of root window which looks similar from this link. A message window with a message and an inactive button untill some portion of the code are done and then to display a message with an active button. This is how the code structure looks like(I have cut through specific details to just clear the point how my code flow looks like)

The second window is not working, instead the window appears at the end of the function. Can somebody help.

from Tkinter import *
import tkMessageBox

def a():
    return

def b():
    . . .
    . . .
    msg_window = Toplevel()
    msg_window.grapset()
    msg_window.title( ___ )
    msg_geometry( ___ )
    msgLabel = Label(window)
    msgLabel["text"]="Processing...."
    msgLabel.pack()
    btn = Button(msg_window, text="Ok", command=msg_window.destroy())
    btn.pack()
    btn.config(state=DISABLED)
    a()
    c()
    d()
    d()
    msgLabel["text"]="Done"
    msgLabel.pack()
    btn = Button(msg_window, text="Ok", command=msg_window.destroy())
    btn.pack()
    btn.config(state=NORMAL)
    e()
    if tkMessageBox.askyesno( ___ ):
        do something
    else:
        do something
    pass

def c():
    return

def d():
    return

def e():
    return

root = Tk()
frame = Frame( ___ )
frame.pack()
but_find = Button( ___ )
but_find.pack()
but_start = Button( ___ )
but_start.pack()
but_exit = Button( ___ )
but_exit.pack()
root.mainloop()

Explanation: I am building an application where the root window contains 3 buttons. When start button is clicked, function b is called, which in turn calls various other functions inside function b itself. This is the point where, i want to create a second window that shows up above the root window and making the root window inactive until function b gets completed or until the second window is destroyed.

What i want is.. The second window(contains 2 things- a message and a button) should start inside the function b after some steps. It should display the message Processing.... and an inactive button called Ok before function a starts and should appear until function d gets completed. Then, i want to display Done with an active 'Ok' button that destroys the second window. Then make the root window active.

1
  • 1
    keep playing around, don't start anything too ambitious if you are just getting started. Here is a great tkinter resource effbot.org/tkinterbook. If you are just getting started with python i would suggest to use python3 as it is the future. Commented Apr 14, 2015 at 18:04

2 Answers 2

3
from tkinter import *

class MessageBox(object):

    def __init__(self,title='Mess', msg='', b1='OK', b2='',b3='',b4=''):

    # Required Data of Init Function
        self.title = title      # Is title of titlebar
        self.msg = msg          # Is message to display
        self.b1 = b1            # Button 1 (outputs '1')
        self.b2 = b2            # Button 2 (outputs '2')
        self.b3 = b3            # Button 3 (outputs '3')
        self.b4 = b4            # Button 4 (outputs '4')
        self.choice = ''        # it will be the return of messagebox according to button press

    # Just the colors for my messagebox

        self.tabcolor = 'red'    # Button color for Active State
        self.bgcolor = 'blue'    # Button color for Non-Active State
        self.bgcolor2 = 'yellow' # Background color of Dialogue
        self.textcolor = 'Green' # Text color for Dialogue

    # Creating Dialogue for messagebox
        self.root = Toplevel()
    
    # Removing titlebar from the Dialogue
        self.root.overrideredirect(True)

    # Setting Geometry
        self.root.geometry("300x120+100+100")
    
    # Setting Background color of Dialogue
        self.root.config(bg=self.bgcolor2)

    # Creating Label For message
        self.msg = Label(self.root,text=msg,
                        font=("Helvetica",9),
                        bg=self.bgcolor2,
                        fg=self.textcolor,
                        #anchor='nw'
                        )
        self.msg.place(x=10,y=28,height=60,width=280)

    # Creating TitleBar
        self.titlebar = Label(self.root,text=self.title,
                             bg=self.bgcolor2,
                             fg=self.textcolor,
                             bd=0,
                             font=("Helvetica",10,'bold')
                             )
        self.titlebar.place(x=100,y=5)
    
        # Creating Close Button
        self.CloseBtn = Button(self.root,
                                text='x',
                                font=("Helvetica",12),
                                command = lambda : self.closed(),
                                bd=0,
                                activebackground='red',
                                activeforeground='white',
                                background=self.bgcolor2,
                                foreground=self.textcolor)
        self.CloseBtn.place(x=260,y=0,width=40)
 
        # Changing Close Button Color on Mouseover
        self.CloseBtn.bind("<Enter>", lambda e,: self.CloseBtn.config(bg='red',fg='white'))
        self.CloseBtn.bind("<Leave>", lambda e,: self.CloseBtn.config(bg=self.bgcolor2,fg=self.textcolor))

    # Creating B1 
        self.B1 = Button(self.root,text=self.b1,command=self.click1,
                        bd=0,
                        font=("Helvetica",10),
                        bg=self.bgcolor,
                        fg='white',
                        activebackground=self.tabcolor,
                        activeforeground=self.textcolor)
        self.B1.place(x=225,y=90,height=25,width=60)
    
    # Getting place_info of B1
        self.B1.info = self.B1.place_info()
    
    # Creating B2
        if not b2=="":
            self.B2 = Button(self.root,text=self.b2,command=self.click2,
                            bd=0,
                            font=("Helvetica",10),
                            bg=self.bgcolor,
                            fg='white',
                            activebackground=self.tabcolor,
                            activeforeground=self.textcolor)
            self.B2.place(x=int(self.B1.info['x'])-(70*1),
                          y=int(self.B1.info['y']),
                          height=int(self.B1.info['height']),
                          width=int(self.B1.info['width'])
                          )
    # Creating B3
        if not b3=='':
            self.B3 = Button(self.root,text=self.b3,command=self.click3,
                            bd=0,
                            font=("Helvetica",10),
                            bg=self.bgcolor,
                            fg='white',
                            activebackground=self.tabcolor,
                            activeforeground=self.textcolor)
            self.B3.place(x=int(self.B1.info['x'])-(70*2),
                          y=int(self.B1.info['y']),
                          height=int(self.B1.info['height']),
                          width=int(self.B1.info['width'])
                          )
    # Creating B4
        if not b4=='':
            self.B4 = Button(self.root,text=self.b4,command=self.click4,
                            bd=0,
                            font=("Helvetica",10),
                            bg=self.bgcolor,
                            fg='white',
                            activebackground=self.tabcolor,
                            activeforeground=self.textcolor)
            self.B4.place(x=int(self.B1.info['x'])-(70*3),
                          y=int(self.B1.info['y']),
                          height=int(self.B1.info['height']),
                          width=int(self.B1.info['width'])
                          )

    # Making MessageBox Visible
        self.root.wait_window()

    # Function on Closeing MessageBox
    def closed(self):
        self.root.destroy() # Destroying Dialogue
        self.choice='closed'#Assigning Value
        
    # Function on pressing B1
    def click1(self):
        self.root.destroy() # Destroying Dialogue
        self.choice='1'     # Assigning Value

    # Function on pressing B2
    def click2(self):
        self.root.destroy() # Destroying Dialogue
        self.choice='2'     # Assigning Value

    # Function on pressing B3
    def click3(self):
        self.root.destroy() #Destroying Dialogue
        self.choice='3'     # Assigning Value

    # Function on pressing B4
    def click4(self):
        self.root.destroy() #Destroying Dialogue
        self.choice='4'     #Assigning Value

root = Tk()

def func():
    a = MessageBox(msg='Hello I m your multiline message',
                    title='Hello World',
                    b1='Button 1',
                    b2='Button 2',
                    )
    print(a.choice)

Button(root,text='Click Me',command=func).pack()

root.mainloop()
Sign up to request clarification or add additional context in comments.

1 Comment

What have you done with the indentation in this code! Too puzzle
2

Try developing your own dialog. Example:

import Tkinter as tk


class CustomDialog(tk.Toplevel):
    def __init__(self, title, message, command1=self.ok, command2=self.ok, command3=self.ok, buttontext1="button1", buttontext2="button2", buttontext3="button3"):
        self.base = tk.Toplevel()
        self.base.title(title)
        self.label = tk.Label(self.base, text=message)
        self.label.pack()
        self.label.grid(row=0, column=0, columnspan=3, sticky=N)
        self.button1 = tk.Button(self.base, text=buttontext1, command=command1)
        self.button1.pack()
        self.button1.grid(row=1, column=0, sticky=N)
        self.button2 = tk.Button(self.base, text=buttontext2, command=command2)
        self.button2.pack()
        self.button2.grid(row=1, column=1, sticky=N)
        self.button3 = tk.Button(self.base, text=buttontext3, command=command3)
        self.button3.pack()
        self.button3.grid(row=1, column=2, sticky=N)
    def ok(self, event=None):
        self.destroy()
    def baseconfig(self, option, value):
        self.base[option] = value
    def labelconfig(self, option, value):
        self.label[option] = value
    def buttonconfig(self, number, option, value):
        exec "self.button%s[option] = value" % str(number)

def customDialog(title, message, command1=self.ok, command2=self.ok, command3=self.ok, buttontext1="button1", buttontext2="button2", buttontext3="button3", button1ret=None, button2ret=None, button3ret=None):
    def _button1press():
        command1()
        return button1ret
    def _button2press():
        command2()
        return button2ret
    def _button3press():
        command3()
        return button3ret
    dialog = CustomDialog(title, message, _button1press, _button2press, _button3press, buttontext1, buttontext2, buttontext3)

And to disable the first button, call self.buttonconfig(1, state, DISABLED) (1 refers to the number of the button). To enable it, use self.buttonconfig(1, state, NORMAL).

3 Comments

Thanks a lot. say i have to return a value to the mainloop on a button click, How should i call it,..?
It says self is not defined.
The example I gave above used a class deriving tk.Toplevel. In Python, you use self to access class members. To enable/disable some button mybutton, just use mybutton['state'] = NORMAL or mybutton['state'] = DISABLED, respectively (notice that NORMAL and DISABLED are actually tk.NORMAL and tk.DISABLED).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.