2

I have a (second) tkinter window, which, when opened, does not get the focus, but rather the first window remains focused (although the second window appears in front of the other). It contains a textbox which I want to be able to type in, but I have to double-click it in order to type.

How do I focus the textbox when opening the window?

My tries: textbox.focus_set(), window.grab_set(), window.focus_set()

None of them did what I wanted to do.

EDIT: Instead, .focus_set() raises an error when (and only when) closing the main window: can't invoke "focus" command: application has been destroyed

This is my current code (tkWin is the main window, tkcWinis the second window):

def click(self, field):
    import _tkinter
    if field != None:
        try:
            self.tkcWin = Tk()#creating window
            self.tkcWin.focus()
            self.tkcWin.title(field)
            self.tkcWin.geometry('300x100')
            self.mainframe = Frame(master=self.tkcWin,background="#60BF98")
            self.mainframe.place(x=0, y=0, width=300, height=300)
            self.textb = Text(master=self.mainframe)
            self.textb.place(x=0, y=50)
            self.textb.bind("<Return>",lambda a: self.setM(field))
            self.textb.bind("<Return>",lambda a: self.tkcWin.destroy(),True)
            self.tkcWin.grab_set()
            self.tkWin.wait_window(self.tkcWin)
            self.textb.focus_set()
            hwnd = self.tkcWin.winfo_id()
            ctypes.windll.user32.SetFocus(hwnd)
            self.tkcWin.mainloop()
        except _tkinter.TclError:
            self.tkcWin.destroy()
pascalhein
  • 5,700
  • 4
  • 31
  • 44
  • 1
    You only use `Tk()` for the main window. See [this example](http://stackoverflow.com/a/10039671/1217270) for a look at the class structure. Look for "# Font Size Window" in the third example. You want to use a [TopLevel](http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/toplevel.html) window for all secondary windows. If you want to replace what is in a main window, make a frame widget that contains everything, which you can destroy and replace with a new Frame that contains the "new window". – Honest Abe Dec 14 '12 at 18:41

1 Answers1

1

It turns out that you can simply call the secondary window's deiconify() method and then the widget's focus_set() method:

toplevel.deiconify()
text.focus_set()

Here's the original work-around for Windows (no longer recommended):

Start by adding import ctypes at the top.
Go ahead and focus your widget like you have with: text.focus_set()
Get the hwnd of the second window: top_hwnd = toplevel.winfo_id()
And finally activate the second window with: ctypes.windll.user32.SetFocus(top_hwnd)

Honest Abe
  • 8,430
  • 4
  • 49
  • 64
  • I cannot use a library because this has to work on a computer in school. However, the second way you described doesn't focus the window. – pascalhein Dec 14 '12 at 17:30
  • @csharpler It worked for me. Is your second window a [TopLevel](http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/toplevel.html) window? Are you sure you are retrieving its hwnd? `yourTopLevel.winfo_id()` It would help for you to post what you are trying if you can't figure it out. – Honest Abe Dec 14 '12 at 18:24
  • @csharpler I've updated the answer to include a native Tkinter solution. – Honest Abe Feb 22 '13 at 02:32