Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining what tkinter window is currently on top

Tags:

python

tkinter

I have written an application in python 2.7 and tkinter. I created a tool bar with several buttons that open up respective top windows that display various options. I used ttk.Checkbutton with the 'toolbutton' style as an indicator to show whether the option windows are open or closed.

The problem is that the option windows will go to the back if another window is selected. Currently, if one selects the toolbutton again, the option window will close. However, I only want to close the window if it is on top. If the option window is not on top, I want the window to moved to the front.

Some of the code I have working:

class MainWindow:
    def __init__(self,application):
        self.mainframe=tk.Frame(application)
        application.geometry("900x600+30+30")

        self.otherOptionsSelect=tk.IntVar()
        self.otherOptions_Button=ttk.Checkbutton(application,style='Toolbutton',variable=self.otherOptionsSelect,
                                                onvalue=1, offvalue=0,image=self.optionsIcon, command=self.otherOptions)
    def otherOptions(self):

        if self.otherOptionsSelect.get()==0:
            self.otherOptions.destroy()
            return

        self.otherOptions=tk.Toplevel()
        self.otherOptions.title("IsoSurface Options")
        self.otherOptions.geometry("200x165+"+str(int(application.winfo_x())+555)+"+"+str(int(application.winfo_y())+230))

        self.otherOptApply_button=ttk.Button(self.otherOptions,text="Apply",command=self.showFrame)
        self.otherOptApply_button.place(x=20,y=80,width=50,height=30)

        self.otherOptClose_button=ttk.Button(self.otherOptions,text="Close",command=self.otherOptionsClose)
        self.otherOptClose_button.place(x=80,y=80,width=50,height=30)

    def otherOptionsClose(self):
        self.otherOptionsSelect.set(0)
        self.otherOptions.destroy()

Here is a picture of the entire application I have written: enter image description here

In the above image, each window has their respective ttk.checkbutton. At the moment, toggling the checkbutton either opens or closes the window. However, what I really want it to do is close the window if the window is in front of the application, or bring the window to the front if it is behind the application.

Hopefully this clears some things up.

Thanks in advance!

like image 412
Onlyjus Avatar asked Apr 27 '12 01:04

Onlyjus


1 Answers

It is in fact possible to check stacking order of windows. Using Tkinter, you have to do some funny tcl evals to get at the information. I found the answer at TkDoc in the section on Windows and Dialogs, scroll down until you get to "Stacking Order". The code baffled me until I started playing around with it interactively. My test code was:

import Tkinter as tk
root = tk.Tk()
root.title('root')
one = tk.Toplevel(root)
one.title('one')
two = tk.Toplevel(root)
two.title('two')

I then manipulated the windows so that two was on top, one under that and root below them all. In that configuration, the following weirdness can tell you relative layering of windows:

root.tk.eval('wm stackorder '+str(two)+' isabove '+str(root))

returns 1, meaning "Yes, window two is above window root." While the following:

root.tk.eval('wm stackorder '+str(root)+' isabove '+str(two))

returns 0, meaning "No, window root is not above window two." You can also use the command:

root.tk.eval('wm stackorder '+str(root))

Which gives back the full window stacking order in the form of a weird string something like this:

'. .68400520L .68401032L'

Which starts to make sense when you run the commands:

str(root)
str(one)
str(two)

and figure out that root has the internal name '.', one is '.68400520L' and two is '.68401032L'. You read the output of root.tk.eval('wm stackorder '+str(root)) backwards so it's saying two is on top, one is under that and root is below both.

like image 160
John Gaines Jr. Avatar answered Oct 31 '22 05:10

John Gaines Jr.