简体   繁体   中英

Python tkinter focus_set for SubMenu after clicking back button

I am new to tkinter, I have 3 title windows. if I go from window1 to window2, focus_set is working, and if I go from window2 to window3, focus_set is working, if I come back from window3 to window2, its not focusing the entry text, which I want to focus.

And its working from window2 to window1. My simple code is as below: I know its bit more code, but it will help to find exact mistake.

I have tried finding the bug, not able to work.

from Tkinter import *

UI_MainForm = ''

Black = 'Black'
Green = 'Green'
Red = 'Red'
Gray = 'Gray'
entrytext = ''
entrytext1 = ''
entrytext2 = ''

top = ''
Subtop = ''

entry = ''
entry1 = ''
entry2 = ''


def printf(Message, Color):
 global UI_SB
 global UI_TxtBar   
 UI_TxtBar.insert(END, Message, Color)
 UI_TxtBar.see("end")
 print Message
 return;

def UserInput():
  global UI_MainForm
  UI_MainForm = Tk()

  #Initialization of Main Window    

  UI_MainForm.resizable(1,0)
  UI_MainForm.geometry("300x575+500+50")
  UI_MainForm.title("Window1")
  UI_MainForm.transient()
  UI_MainForm.deiconify() 


    # LabelFrame to add all the Menu menu Display items
  labelframe = LabelFrame(UI_MainForm,text="Please select the below options:",width=300, height=100,bd = 2)
  labelframe.pack(fill="both")
  labelframe.config(relief=RIDGE)

    # LabelFrame to add the User input text box and buttons
  labelframe1 = LabelFrame(UI_MainForm,text="User Input:",width=300, height=100,bd = 2)
  labelframe1.pack(pady=8,fill="both")
  labelframe1.config(relief=FLAT)

#adding Text Box
# textbox = Text(labelframe1, height=1, width=35,wrap=WORD)
# textbox.pack(padx=4, pady=4)

#Entry the text and display
    global entrytext
    global entry
    entrytext = StringVar()
    entry = Entry(labelframe1,textvariable=entrytext,width=35)
    entry.pack(padx = 1, pady = 5)
    entry.focus_set() # which will highlight the box without mouse click
     #   entry.delete(0, 'end')
    entry.selection_range(0, END)
    Input = entrytext.get()
    # self.text.insert(END, Input + '\n')
    # self.scroll.config(Input = self.text.yview)



    #Main Menu Label Display items
    MainMenuDisplay =  [{"ID": 1,"Description": "Display Data1"},
                    {"ID": 2,"Description": "Display Data2"}]

       for menu in MainMenuDisplay:
           temp_text = '{0}. {1}'.format(menu['ID'], menu['Description'])
           Label(labelframe, text=temp_text).pack(anchor = W)


  ButtonOK = Button(labelframe1, text = "OK", command =OnButtonOK, width =15)
  ButtonOK.pack(side = LEFT, padx = 15, pady = 15)


  ButtonEXIT = Button(labelframe1, text = "EXIT", width =15)
  ButtonEXIT.pack(side = RIGHT, padx = 15)

  UI_MainForm.mainloop()

  return;


def OnButtonOK():
# UI_MainForm.withdraw()

  Input = int(entrytext.get())

  if (Input == 1):
    SubMenu();

  elif (Input == 2):
    SED_Menu_Display();


  else:
      print "The Input is not valid 
  return;   
def SubMenu():
 # UI_MainForm.withdraw()
 entry.delete(0,END) #Delete the Main Menu entry text after click
 UI_MainForm.iconify()
 global top
 top = Toplevel(UI_MainForm)
 top.geometry("300x250+500+50")
 top.title("Window2")

    NumericMenuDisplay = [{"ID": 1,"Description": "Display Numeric PIDs SubMenu 1"}]


    labelframe = LabelFrame(top,text="Please select the below options:",width=300, height=150,bd = 2)
    labelframe.pack(fill="both")
    labelframe.config(relief=RIDGE)



   for menu in NumericMenuDisplay:
    temp_text = '{0}. {1}'.format(menu['ID'], menu['Description'])
    Label(labelframe, text=temp_text).pack(anchor = W)

 top.resizable(1,0)
 top.grab_set()

 frame = Frame(top,width=300, height=100,bd = 2)
 frame.pack(fill = 'both',padx=3, pady=3)
 frame.config(relief=RIDGE)


     Label(frame, text = "q: Quit this Menu (Back to Main Menu)").pack( padx = 10, pady = 5)
    global entrytext1
    entrytext1 = StringVar()
    entry1 = Entry(frame,textvariable=entrytext1, width = 35)
    entry1.pack(padx = 5, pady = 5)
    entry1.focus_set() # which will highlight the box without mouse click

    topButtonShow = Button(frame, text = 'Show', command = OpenSubMenu,width = 15)
    topButtonBack = Button(frame, text = 'Back', command = OnChildClose,width = 15)
    topButtonShow.pack(side = LEFT,padx = 25,pady = 5)
    topButtonBack.pack(side = RIGHT,padx = 5,pady = 15)


    return;
def OpenSubMenu():
  Input = entrytext1.get()

   if (Input == '1'):
    NumericPIDsSubMenu1();
  elif (Input == 'q'):
    BackMenu();
  else:
    print "The Input is not valid"
  return;

def NumericPIDsSubMenu1():
 entry.delete(0,END) #Delete the Main Menu entry text after click
 top.iconify()
 global Subtop
 Subtop = Toplevel(top)
 Subtop.geometry("475x600+500+15")
 Subtop.title("Window3")
 Subtop.grab_set()
 leftFrame = Frame(Subtop,width=300, height=100,bd = 2)
 leftFrame.grid(row=0, column=0, padx=0.1, pady=0.1)
 leftFrame.config(relief=RIDGE)


 frame = Frame(Subtop,width=400, height=150,bd = 1)
 frame.grid(row=1, column=0,padx=5,pady=2,columnspan=2) #columnspan is to combine the grid(row & column)


 frame1 = Frame(Subtop,width=450, height=170,bd = 1)
 frame1.grid(row=2, column=0,padx=5,pady=2,columnspan=2) #columnspan is to combine the grid(row & column)
 frame1.config(relief=RIDGE)

 Label(frame, text = "q:Quit this Menu (Back to Main Menu)").pack( padx = 10, pady = 5)
 global entrytext2
 entrytext2 = StringVar()
 entry2 = Entry(frame,textvariable=entrytext2, width = 35)
 entry2.pack(padx = 5, pady = 5)
 entry2.focus_set() 



 topButtonShow = Button(frame, text = 'Show', command = OpenSubMenu1,width = 10)
 topButtonBack = Button(frame, text = 'Back', command = SubMenuChildClose,width = 10)
 topButtonShow.pack(side = LEFT,padx = 10,pady = 5)
 topButtonBack.pack(side = RIGHT,padx = 10,pady = 5)


    data_items =  [{"ID": 1,"Description": "Display1"},
                    {"ID": 2,"Description": "Display2"}]

   for i,readdta in enumerate(data_items,start=1):

      temp_text = '{0}. {1:04X} - {2}'.format(i,readdta['ID'], readdta['Description'])

      Label(leftFrame, text=temp_text).pack(anchor = W,padx=5)

   return;

  def OpenSubMenu1():
   global Input
   Input = int(entrytext2.get()
   return;

 def SED_Menu_Display():
   return;
 def OnChildClose():
   BackMenu();
   return;

  def BackMenu():
   UI_MainForm.deiconify() #Go back to the Main Window
   top.destroy() # Destroy the Child Window
   UI_MainForm.grab_set()
   entry.focus_set()

 def BackSubMenu():
  top.deiconify() #Go back to the Main Window
  Subtop.destroy() # Destroy the Child Window
  top.grab_set()
  entry1.focus_set()
  #entry2.selection_range(0, END)
  return;

 def SubMenuChildClose():
  BackSubMenu();
  return;


def Main():

    UserInput()


Main()

error is:I know the error type, but i want specific code, where i need to change

Attribute Error: 'str' object has no attribute focus_set

Unbalanced quotes and indentation issues aside (assuming you fix those), what is producing the error is an global and local variable issue.

You first created a global variable entry1 = '' , which is a string . Later in your code, you created a local variable entry1 in the scope of SubMenu() function:

def SubMenu():
    #...

    entry1 = Entry(frame,textvariable=entrytext1, width = 35)
    entry1.pack(padx = 5, pady = 5)
    entry1.focus_set() # which will highlight the box without mouse click

    #...
    return

This local entry1 variable is a tkinter widget.

When created (and called):

def BackSubMenu():
    #....
    entry1.focus_set()
    return

entry1 is not in the local scope of BackSubMenu() so it looked for in the global scope, where entry1 is a string, hence the error.

To changeg entry1 fron a string to an instance of a tkinter widget, use the global keyword in the definition of SubMenu() as you've done in other places in the code;

def SubMenu():
    global entry1   #modify the global entry1 from string to tkinter entry instance
    #...

    entry1 = Entry(frame,textvariable=entrytext1, width = 35)
    entry1.pack(padx = 5, pady = 5)
    entry1.focus_set() # which will highlight the box without mouse click

    #...
    return

You might want to consider using classes to build your code.

Working code

from Tkinter import *

UI_MainForm = ''

Black = 'Black'
Green = 'Green'
Red = 'Red'
Gray = 'Gray'
entrytext = ''
entrytext1 = ''
entrytext2 = ''

top = ''
Subtop = ''

entry = ''
entry1 = ''
entry2 = ''


def printf(Message, Color):
    global UI_SB
    global UI_TxtBar   
    UI_TxtBar.insert(END, Message, Color)
    UI_TxtBar.see("end")
    print Message
    return;

def UserInput():
    global UI_MainForm
    UI_MainForm = Tk()

    #Initialization of Main Window    

    UI_MainForm.resizable(1,0)
    UI_MainForm.geometry("300x575+500+50")
    UI_MainForm.title("Window1")
    UI_MainForm.transient()
    UI_MainForm.deiconify() 


        # LabelFrame to add all the Menu menu Display items
    labelframe = LabelFrame(UI_MainForm,text="Please select the below options:",width=300, height=100,bd = 2)
    labelframe.pack(fill="both")
    labelframe.config(relief=RIDGE)

        # LabelFrame to add the User input text box and buttons
    labelframe1 = LabelFrame(UI_MainForm,text="User Input:",width=300, height=100,bd = 2)
    labelframe1.pack(pady=8,fill="both")
    labelframe1.config(relief=FLAT)

#adding Text Box
# textbox = Text(labelframe1, height=1, width=35,wrap=WORD)
# textbox.pack(padx=4, pady=4)

#Entry the text and display
    global entrytext
    global entry
    entrytext = StringVar()
    entry = Entry(labelframe1,textvariable=entrytext,width=35)
    entry.pack(padx = 1, pady = 5)
    entry.focus_set() # which will highlight the box without mouse click
     #   entry.delete(0, 'end')
    entry.selection_range(0, END)
    Input = entrytext.get()
    # self.text.insert(END, Input + '\n')
    # self.scroll.config(Input = self.text.yview)



    #Main Menu Label Display items
    MainMenuDisplay =  [{"ID": 1,"Description": "Display Data1"},
                                    {"ID": 2,"Description": "Display Data2"}]

    for menu in MainMenuDisplay:
         temp_text = '{0}. {1}'.format(menu['ID'], menu['Description'])
         Label(labelframe, text=temp_text).pack(anchor = W)


    ButtonOK = Button(labelframe1, text = "OK", command =OnButtonOK, width =15)
    ButtonOK.pack(side = LEFT, padx = 15, pady = 15)


    ButtonEXIT = Button(labelframe1, text = "EXIT", width =15)
    ButtonEXIT.pack(side = RIGHT, padx = 15)

    UI_MainForm.mainloop()

    return;


def OnButtonOK():
# UI_MainForm.withdraw()

    Input = int(entrytext.get())

    if (Input == 1):
        SubMenu();

    elif (Input == 2):
        SED_Menu_Display();

    else:
            print "The Input is not valid" 
    return  

def SubMenu():
    global entry1   #modify the global entry1 from string to tkinter entry instance
    # UI_MainForm.withdraw()
    entry.delete(0,END) #Delete the Main Menu entry text after click
    UI_MainForm.iconify()
    global top
    top = Toplevel(UI_MainForm)
    top.geometry("300x250+500+50")
    top.title("Window2")

    NumericMenuDisplay = [{"ID": 1,"Description": "Display Numeric PIDs SubMenu 1"}]


    labelframe = LabelFrame(top,text="Please select the below options:",width=300, height=150,bd = 2)
    labelframe.pack(fill="both")
    labelframe.config(relief=RIDGE)


    for menu in NumericMenuDisplay:
        temp_text = '{0}. {1}'.format(menu['ID'], menu['Description'])
        Label(labelframe, text=temp_text).pack(anchor = W)

    top.resizable(1,0)
    top.grab_set()

    frame = Frame(top,width=300, height=100,bd = 2)
    frame.pack(fill = 'both',padx=3, pady=3)
    frame.config(relief=RIDGE)


    Label(frame, text = "q: Quit this Menu (Back to Main Menu)").pack( padx = 10, pady = 5)
    global entrytext1
    entrytext1 = StringVar()
    entry1 = Entry(frame,textvariable=entrytext1, width = 35)
    entry1.pack(padx = 5, pady = 5)
    entry1.focus_set() # which will highlight the box without mouse click

    topButtonShow = Button(frame, text = 'Show', command = OpenSubMenu,width = 15)
    topButtonBack = Button(frame, text = 'Back', command = OnChildClose,width = 15)
    topButtonShow.pack(side = LEFT,padx = 25,pady = 5)
    topButtonBack.pack(side = RIGHT,padx = 5,pady = 15)


    return

def OpenSubMenu():
    Input = entrytext1.get()

    if (Input == '1'):
        NumericPIDsSubMenu1();
    elif (Input == 'q'):
        BackMenu();
    else:
        print "The Input is not valid"
    return

def NumericPIDsSubMenu1():
    entry.delete(0,END) #Delete the Main Menu entry text after click
    top.iconify()
    global Subtop
    Subtop = Toplevel(top)
    Subtop.geometry("475x600+500+15")
    Subtop.title("Window3")
    Subtop.grab_set()
    leftFrame = Frame(Subtop,width=300, height=100,bd = 2)
    leftFrame.grid(row=0, column=0, padx=0.1, pady=0.1)
    leftFrame.config(relief=RIDGE)


    frame = Frame(Subtop,width=400, height=150,bd = 1)
    frame.grid(row=1, column=0,padx=5,pady=2,columnspan=2) #columnspan is to combine the grid(row & column)


    frame1 = Frame(Subtop,width=450, height=170,bd = 1)
    frame1.grid(row=2, column=0,padx=5,pady=2,columnspan=2) #columnspan is to combine the grid(row & column)
    frame1.config(relief=RIDGE)

    Label(frame, text = "q:Quit this Menu (Back to Main Menu)").pack( padx = 10, pady = 5)
    global entrytext2
    entrytext2 = StringVar()
    entry2 = Entry(frame,textvariable=entrytext2, width = 35)
    entry2.pack(padx = 5, pady = 5)
    entry2.focus_set() 



    topButtonShow = Button(frame, text = 'Show', command = OpenSubMenu1,width = 10)
    topButtonBack = Button(frame, text = 'Back', command = SubMenuChildClose,width = 10)
    topButtonShow.pack(side = LEFT,padx = 10,pady = 5)
    topButtonBack.pack(side = RIGHT,padx = 10,pady = 5)


    data_items =  [{"ID": 1,"Description": "Display1"}, {"ID": 2,"Description": "Display2"}]

    for i,readdta in enumerate(data_items,start=1):

        temp_text = '{0}. {1:04X} - {2}'.format(i,readdta['ID'], readdta['Description'])

        Label(leftFrame, text=temp_text).pack(anchor = W,padx=5)

    return

def OpenSubMenu1():
    global Input
    Input = int(entrytext2.get())
    return

def SED_Menu_Display():
    return

def OnChildClose():
    BackMenu()
    return

def BackMenu():
    UI_MainForm.deiconify() #Go back to the Main Window
    top.destroy() # Destroy the Child Window
    UI_MainForm.grab_set()
    entry.focus_set()


def BackSubMenu():
    top.deiconify() #Go back to the Main Window
    Subtop.destroy() # Destroy the Child Window
    top.grab_set()
    entry1.focus_set()
    #entry2.selection_range(0, END)
    return

def SubMenuChildClose():
    BackSubMenu();
    return


def Main():
    UserInput()


Main()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM