Home     |     .Net Programming    |     cSharp Home    |     Sql Server Home    |     Javascript / Client Side Development     |     Ajax Programming

Ruby on Rails Development     |     Perl Programming     |     C Programming Language     |     C++ Programming     |     IT Jobs

Python Programming Language     |     Laptop Suggestions?    |     TCL Scripting     |     Fortran Programming     |     Scheme Programming Language


 
 
Cervo Technologies
The Right Source to Outsource

MS Dynamics CRM 3.0

Python Programming Language

Tkinter, tkMessagebox and overrideredirect


Hi everybody.

I have this code snippet that shows a window without a titlebar (using
overrideredirect) and two buttons on it: one quits and the other one
brings up a simple tkMessageBox.
On Windows (any flavour) the tkMessagebox brings up over the
underlying window.
On Linux (apparently any flavour) the tkMessagebox brings up under the
underlying window.
You can drag the popup window near the main window to discover if it's
over or under it.
Obviously I would like to show a popup that is over the main window!
Before asking I tried, I read, I googled, I pulled my hair off, but no
avail...
Any hints?
Thanks a lot for your time.
Ciao.
Marco.

import tkMessageBox
from Tkinter import *

class App():
    def __init__(self):
        self.root = Tk()
        self.root.overrideredirect(1)
        self.frame = Frame(self.root, width=320, height=200,
                           borderwidth=5, relief=RAISED)
        self.frame.pack_propagate(False)
        self.frame.pack()
        self.bQuit = Button(self.frame, text="Quit",
command=self.root.quit)
        self.bQuit.pack(pady=20)
        self.bHello = Button(self.frame, text="Hello",
command=self.hello)
        self.bHello.pack(pady=20)

    def hello(self):
        tkMessageBox.showinfo("Popup", "Hello!")

app = App()
app.root.mainloop()

Apparently:

def hello(self):
     self.root.after_idle(self.root.lower)
     tkMessageBox.showinfo("Popup", "Hello!")

does something looking like what you want. I don't know of any way to get  
the identifier for the window created by tkMessageBox.showinfo, so if  
there's a way to do better than that, I don't know it.

As an aside, having a window with overrideredirect(1) creating "normal"  
windows such as the one created via tkMessageBox.showinfo is asking for  
problems. What are you trying to do here?

HTH
--
python -c "print ''.join([chr(154 - ord(c)) for c in  
'U(17zX(%,5.zmz5(17l8(%,5.Z*(93-965$l7+-'])"

On Jun 6, 8:55 am, "Eric Brunel" <see.signat@no.spam> wrote:

> Apparently:

Eric,
first of all, thanks!

> def hello(self):
>      self.root.after_idle(self.root.lower)
>      tkMessageBox.showinfo("Popup", "Hello!")

Well, this lowers the background frame but I want to keep it visible
under the popup.

> As an aside, having a window with overrideredirect(1) creating "normal"
> windows such as the one created via tkMessageBox.showinfo is asking for
> problems. What are you trying to do here?

I just need a window without the titlebar as my main window (think of
it as a kiosk application). No titlebar is mandatory :-(
I place controls on it and I open popup dialog windows.
If there is a better way to do it, I would be happy to know it.
Thanks again.
Ciao.
Marcio.

On Wed, 06 Jun 2007 14:26:12 +0200, <marcob@gmail.com> wrote:
>> As an aside, having a window with overrideredirect(1) creating "normal"
>> windows such as the one created via tkMessageBox.showinfo is asking for
>> problems. What are you trying to do here?

> I just need a window without the titlebar as my main window (think of
> it as a kiosk application). No titlebar is mandatory :-(
> I place controls on it and I open popup dialog windows.
> If there is a better way to do it, I would be happy to know it.

My only advice would then be to avoid using the standard functions to  
create dialog boxes, and to create them yourself. For example:
----------------------------------------------------------
 from Tkinter import *

class App:
     def __init__(self):
         self.root = Tk()
         self.root.overrideredirect(1)
         frm = Frame(self.root, width=320, height=200, borderwidth=5,  
relief=RAISED)
         frm.pack_propagate(0)
         frm.pack()
         Button(frm, text="Quit", command=self.root.quit).pack(pady=20)
         Button(frm, text="Hello", command=self.hello).pack(pady=20)

     def hello(self):
         dialogWdw = Toplevel()
         dialogWdw.title('Popup')
         Label(dialogWdw, text='Hello!').pack(side=TOP)
         Button(dialogWdw, text='OK',  
command=dialogWdw.destroy).pack(side=TOP)
         dialogWdw.tkraise(self.root)
         self.root.wait_window(dialogWdw)

app = App()
app.root.mainloop()
----------------------------------------------------------

But even with this, you may run into problems. For example, on my Linux  
box with my window manager, the main window goes behind all other windows  
once the button in the dialog is clicked. So I'd say that if you want to  
bypass the window manager, bypass it for everything and do  
overrideredirect(1) on all the windows you create. But this means that  
you'll have to do everything "manually", especially window stacking.
--
python -c "print ''.join([chr(154 - ord(c)) for c in  
'U(17zX(%,5.zmz5(17l8(%,5.Z*(93-965$l7+-'])"

On Jun 6, 3:38 pm, "Eric Brunel" <see.signat@no.spam> wrote:

> My only advice would then be to avoid using the standard functions to
> create dialog boxes, and to create them yourself. For example:
> ----------------------------------------------------------
>  from Tkinter import *
[snip]
> app.root.mainloop()
> ----------------------------------------------------------
> But even with this, you may run into problems. For example, on my Linux
> box with my window manager, the main window goes behind all other windows
> once the button in the dialog is clicked. So I'd say that if you want to
> bypass the window manager, bypass it for everything and do
> overrideredirect(1) on all the windows you create. But this means that
> you'll have to do everything "manually", especially window stacking.

Besides that, the popup window is yet under the main frame... :-(
Seems to me that dialogWdw.tkraise(self.root) doesn't do its job.
It's like overrideredirect in main window override also tkraise on it.

I can't believe there isn't an easier way to make a kiosk application
without titlebar.
Perhaps to create a normal window bigger than screen with title bar
outside it?
And after how can I ignore titlebar menu command or "x" and "-"
button?
Or is it possible to create a main Toplevel without "x" and "-"?

Thanks.
Ciao.
Marco.

On Thu, 07 Jun 2007 09:04:24 +0200, <marcob@gmail.com> wrote:

[snip]

> I can't believe there isn't an easier way to make a kiosk application
> without titlebar.

That's not the problem: there *is* an easy way, and you found it:  
overrideredirect(1). But now you're trying to mix windows ignored by the  
window manager - as you've told it to - and windows that *are* managed by  
the window manager. This is where the problem is.

> Perhaps to create a normal window bigger than screen with title bar
> outside it?

This won't work on some platforms and/or with some window managers... And  
there's no portable way to do that, as sometimes, the dimensions you give  
for the window includes the window decorations, and sometimes they don't.

> And after how can I ignore titlebar menu command or "x" and "-"
> button?

For the 'X' button, it's quite simple:  
myToplevel.protocol('WM_DELETE_WINDOW', lambda: None)

For the '-' button, I don't know any way.

> Or is it possible to create a main Toplevel without "x" and "-"?

Apart from overrideredirect(1), I don't think there's any.

BTW, what are you trying to do here? Will your application run on a  
"normal" desktop computer? Or will it run on special devices such as  
vending machines or similar? If in the first case, my advice would be to  
give up this design (which many people hate, BTW) and use normal windows.  
You'll have far less trouble and will probably make your users happier. If  
in the second case, you shouldn't rely on an existing window manager, and  
try to design your GUI so that doing things "manually" will be easier. For  
example, instead of displaying a dialog for a message, maybe you should  
just reserve a screen zone to display the message, optionally displaying  
it in a special color or making it blink so that the user can't miss it.  
You may also consider using the "place" layout method to display things at  
random coordinates in your application window. For example:

--------------------------------------------------------
 from Tkinter import *

class App:
     def __init__(self):
         self.root = Tk()
         self.root.overrideredirect(1)
         frm = Frame(self.root, width=320, height=200,
                            borderwidth=5, relief=RAISED)
         frm.pack_propagate(0)
         frm.pack()
         Button(frm, text="Quit", command=self.root.quit).pack(pady=20)
         Button(frm, text="Hello", command=self.hello).pack(pady=20)

     def hello(self):
         self.dialogWdw = Frame(self.root, borderwidth=2, relief=RAISED)
         Label(self.dialogWdw, text='Hello!').pack(side=TOP, padx=20,  
pady=4)
         Button(self.dialogWdw, text='OK',  
command=self.destroyDialog).pack(side=TOP, padx=20, pady=4)
         self.dialogWdw.place(x=170, y=100, anchor='center')

     def destroyDialog(self):
         self.dialogWdw.place_forget()
         self.dialogWdw.destroy()

app = App()
app.root.mainloop()
--------------------------------------------------------

HTH
--
python -c "print ''.join([chr(154 - ord(c)) for c in  
'U(17zX(%,5.zmz5(17l8(%,5.Z*(93-965$l7+-'])"

On Jun 7, 12:01 pm, "Eric Brunel" <see.signat@no.spam> wrote:

> BTW, what are you trying to do here? Will your application run on a
> "normal" desktop computer? Or will it run on special devices such as
> vending machines or similar?

You got it: it's a special device.

> in the second case, you shouldn't rely on an existing window manager, and
> try to design your GUI so that doing things "manually" will be easier. For
> example, instead of displaying a dialog for a message, maybe you should
> just reserve a screen zone to display the message, optionally displaying
> it in a special color or making it blink so that the user can't miss it.
> You may also consider using the "place" layout method to display things at
> random coordinates in your application window. For example:

You are right and I think it's not a big deal for simple popup
messages.
But when I need tkFileDialog.askdirectory I think things get harder.
I would prefer not have to reimplement the whole stuff from scratch...

Ciao.
Marco.
P.S. BTW I already owe you a pizza for your help. Do you think you can
be at http://www.pycon.it this weekend? :-)

Add to del.icio.us | Digg this | Stumble it | Powered by Megasolutions Inc