0

I hope I can explain the problem properly enough... so basically, I am in the progress of creating a Gui.

In this extracted piece of code I want to iterate over my port_str list and make a frame with the name of each element and some radio buttons in the frame;

and for three of these buttons R1_wire, R2_wire, etc. I call another function sel_wire_1 with 'command' to either make the buttons (e.g.R1_discipline) active or disabled.

The problem is now that if I want to print the value of the selected radio button in one of the first frames it always shows me the name of the last element in the list and the value(either 1 or two) of the last element of the port_str list and this depended on activation in sel_wire__1 also only works for the last frame (the last element of the list port_str). Also this dependend selection of sel_wire_1 does inly work for the last created frame.

So I have several identical frames in front of me with different 'labels'(out of the list) but the command function only works correctly for the last frame(last element).

I tried so many things but I still don't know how to fix that as I'm new to tkinter and not that good with OOP. I did exactly the same thing in functional programming and it worked perfectly. So what is the problem in this oop case then? Thanks to everyone who can help in advance

class MSM:

  def __init__(self,top):
    #create main frame, holds everything
    self.main_frame= Frame(self.top,width = 50, height = 100, bd = 1)
    self.main_frame.pack(fill=BOTH, expand=1)

    #creat a canvas
    self.my_canvas = Canvas(self.main_frame)
    self.my_canvas.pack_propagate(0)
    self.my_canvas.pack(side = LEFT, fill = BOTH, expand = 1)
    self.second_frame = Frame(self.my_canvas)



    port_str = [port1,port2,port3,port4,port5]
    for port in port_str:
    self.pins(port) #here i call the pins() function in a for loop to create s frame with some radiobuttons for each element of the port_str list


  def pins(self,port):
#here im defining a frame and the label of each frame which are elements of the port_str list 
    self.frame_portdetails = Frame(self.frame_portdetails_top)
    self.frame_portdetails.pack(fill= 'both', expand = 1)

    self.var_wiretype = IntVar()
    self.R1_wiretype = Radiobutton(self.frame_portdetails, text= ("wire",port),variable=self.var_wiretype, value=1,command= self.sel_wiretype_1)
    self.R1_wiretype.grid( row=1,column=1,sticky='W')
    self.R2_wiretype = Radiobutton(self.frame_portdetails, text=("wreal",port),variable=self.var_wiretype, value=2,command=self.sel_wiretype_1)
    self.R2_wiretype.grid( row=1,column=2,sticky= 'W' )
        
#discipline here just more buttons are being defined
    self.var_discipline = IntVar()        
    self.R1_discipline = Radiobutton(self.frame_portdetails, text="logic", variable=self.var_discipline, value=1 )
    self.R1_discipline.grid(row=2,column=1,sticky='W')

    self.R2_discipline = Radiobutton(self.frame_portdetails, text="vreal", variable=self.var_discipline, value=2)
    self.R2_discipline.grid(row=2,column=2,sticky='W')

    self.R3_discipline = Radiobutton(self.frame_portdetails, text="ireal", variable=self.var_discipline, value=3)
    self.R3_discipline.grid(row=2,column=3,sticky='W')

    self.R4_discipline = Radiobutton(self.frame_portdetails, text="other", variable=self.var_discipline, value=4 )
    self.entry1 = ttk.Entry (self.frame_portdetails, width = 10 ) 
    self.entry1.grid(row=3,column=2)
    self.R4_discipline.grid(row=3,column=1,sticky='W')
       
  def sel_wiretype_1(self): #this should either make a button active or 
  #disabled but is seems this is only being applied to the last element 
  #of the list/ the last frame(and the buttons inside) that is being 
  #created
    if(self.var_wiretype.get()==1):
      self.R1_discipline['state']='active'
      self.R2_discipline['state']='disabled'
      self.R3_discipline['state']='disabled'
      self.var_discipline.set(1)
    else:
      self.R1_discipline['state']='disabled'
      self.R2_discipline['state']='active'
      self.R3_discipline['state']='active'
      self.var_discipline.set(2)

if __name__ == "__main__":

root = tk.Tk()
app = MSM(root)
root.mainloop(            
na lolig
  • 1
  • 2
  • 1
    Don't define function inside other functions as that can be hard to debug. Also please prove a minimal working example of your problem, – TheLizzard Sep 06 '21 at 20:09
  • Okay thank you!! i did edit it already. I have it now as a method of the class too. But what is meant with working example exactly? First time asking on stackoverflow – na lolig Sep 06 '21 at 21:12
  • The smallest working code possible that shows the problem but doesn't have unnecessary stuff inside it. Like right now I don't think we need to see the definition of `self.label_portcall` but we do need a bit more of the code from `pins` and `sel_wiretype_1`. If you ask a very specific question, you are more likely to get a clearer answer. – TheLizzard Sep 06 '21 at 21:15
  • I understand! well the self.label_portcall should just show that the frames being created with labelnames of each element of the list i want to iterate through. in pins() i just go on defining buttons nothing more. I will try to be more precise: pins is cretaing frames and placing buttons in it and 3 of these buttons are linked to sel_wiretype_1() so when i click on R1_wiretype e.g. i want some buttons to be active and some to be disabled. But this behavior only occcurs in the last frame (means the last iteration of the loop i guess?) its maybe being overwritten? but the labels are different – na lolig Sep 06 '21 at 21:40
  • @TheLizzard in this question for example https://stackoverflow.com/questions/66248958/python-tkinter-how-to-create-radiobuttons-in-loop you gave the tip to use the partial function but i don't know how to apply it in my case – na lolig Sep 07 '21 at 11:47
  • That only applies to when you are creating buttons in a for loop and want to pass in the parameter that the for loop is updating in the `command` function. I don't think it will work in this case. Also can you please make a working example that I can copy/paste to see the full problem? – TheLizzard Sep 07 '21 at 11:56
  • You are calling `.pins()` multiple times, but each time storing the created widgets/vars in the *same* attributes, overwriting the values from the previous call. You need to create a distinct container of some sort (an instance of `class Pin`, perhaps) on each call to `.pins()`, store the widgets & vars in that, and append them to a list so that ALL of the values continue to exist. – jasonharper Sep 07 '21 at 13:30
  • @TheLizzard okay so i can use that if i want to update the row for example? I tried to make a working example . this should create a window and a main frame and loop over port_str to create the frames in the pin() function If R1_wire is clicked i only want R1_discipline to be active and if R2_wire is clicked i want the rest to be active. In my original code this class is in TopLevel Window and not in root but i don't know how to make the whole code accessible if that is necessary. – na lolig Sep 07 '21 at 16:41
  • @jasonharper Yes exactly its overwriting all values and function of the frames ánd buttons with the values of the last iteration but i don't know how to save the outputs of pins(). I cant't do a list for every button and frame? So you mean i should turn pins into a class? and make a list for evry widget i am crating? – na lolig Sep 08 '21 at 06:51
  • @jasonharper Also do you know why doing the exactly same thing (looping the function oins) doesn't lead to overwriting issues when done with functional programming? Why just when usimg oop? – na lolig Sep 08 '21 at 07:37

0 Answers0