-1

Recently got stuck on a part of my code which doesn't seem to make much sense to me. I'm busy with a program with multiple Screens to monitor a water process. In a Setup Page, There are radio button options To select the amount of Filters (1-4) alongside other settings. To Group These radio button Filter_Num = tk.IntVar() is used and then the value is assigned by 4 Radio Buttons.

    Filt1=tk.Radiobutton(self, text = "1" ,variable=Filter_Num,value=1)
    Filt1.place(x=700,y=141)
    Filt2=tk.Radiobutton(self, text = "2" ,variable=Filter_Num,value=2)
    Filt2.place(x=750,y=141)
    Filt3=tk.Radiobutton(self, text = "3" ,variable=Filter_Num,value=3)
    Filt3.place(x=700,y=160)
    Filt4=tk.Radiobutton(self, text = "4" ,variable=Filter_Num,value=4)
    Filt4.place(x=750,y=160)

Now using this on another page where the control options are shown i have a function that shows the statussus of the outputs, this updates every 500 milliseconds, black being it is disabled, but when using a comparison operator as such

    if Filter_Num < 4:
        self.Filter4Can.itemconfigure(self.Filter_4i, fill="black") 
    elif (Filter_4_Solenoid == 1) and (Filter_Num >= 4):
        self.Filter4Can.itemconfigure(self.Filter_4i, fill="green")                     
    else:
        self.Filter4Can.itemconfigure(self.Filter_4i, fill="red")

the program runs the error "TypeError: '<' not supported between instances of 'IntVar' and 'int'"

Understandable, so I need to use .get() or .getvar() to retrieve the value inside the Variable, as such self.Filter_Number = Filter_Num.get(), but if do that I get the error "AttributeError:'int' object has no attribute 'get'"

If i understand this correctly, Its either telling me its an IntVar and cant compare, or telling me its an Integer and cant get the Value from it. Am I missing something? I'm fairly new to the language.

Whats Even More Strange is when Using the IntVar within an if as such

if Filter_4_Solenoid == 1:
   x = Filter_Num
   x = x.get()
   print(x)

The Value is converted without Problem and I can get 1 - 4, But Outside the If, the Problem Persists

Adriaan vS
  • 43
  • 5
  • Use `Filter_Num.get()` instead. – acw1668 Jun 24 '20 at 10:01
  • @acw1668 Thanks for the answer, but as stated in the second last paragraph, using .get() on the IntVar results in "AttributeError:'int' object has no attribute 'get'" – Adriaan vS Jun 24 '20 at 11:26
  • 1
    That means somewhere in your code has changed it to int type. – acw1668 Jun 24 '20 at 11:29
  • @acw1668 Its a global variable and assigned its value only in the Setup Page. No where else in the Code is it altered. (Edited Post) – Adriaan vS Jun 24 '20 at 11:54
  • 1
    You are obviously mistaken about not assigning a value elsewhere; you wouldn't be getting this error if that was true. – jasonharper Jun 24 '20 at 12:25
  • @jasonharper Its A new Section of Code Which is only used in 3 Places 1.- The Initializing global where 3 is assigned as default 2.- The Setup screen where You can assign 1 - 4 3.- A GUI class where a function updated the variables every 0.5 seconds. This is where the Error occurs. But when using an IF statement within the update function, i can access it and print "PY_VAR6" or .get() it to print "1-4" Its only outside the If where the problem persists. – Adriaan vS Jun 24 '20 at 12:54
  • @jasonharper Here are two screenshots to show how simply changing its position results in an error [link](https://imgur.com/a/2mV1lvm) – Adriaan vS Jun 24 '20 at 13:09

2 Answers2

0

You're claiming that both Filter_Num < 4 is throwing an error claiming Filter_Num is an IntVar, and Filter_Num.get() is throwing an error claiming Filter_Num is an int. It's not possible for both of those to be true.

If Filter_Num is truly an instance of IntVar like you claim it is, you need to use the .get() method to get the value before using it in an expression:

if Filter_Num.get() < 4:
    ...

That is unquestionably how you would use an instance of IntVar in an expression.

If that throws the error "AttributeError:'int' object has no attribute 'get'", the only possible explanation is that Filter_Num is an int because the error is telling you it's an int. If that is true, then if Filter_Num < 4 absolutely will work.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • Thanks for the Reply. [Here](https://imgur.com/a/xDhSkw0) are two screenshots showing both Cases. In my reply to another comment [Here](https://imgur.com/a/2mV1lvm) showing that i can get the values inside an IF statement, just not outside it. Which is why this is odd. That being said, I wont put is past myself for making a silly mistake somewhere, but the variable isn't used anywhere else. – Adriaan vS Jun 24 '20 at 13:21
  • @YuMChUM777: it is an immutable fact that the variable can't both be an `int` and an instance of `IntVar` _at the same time_. It must be one or the other. If it's one at one point and the other at another point, the only possible conclusion is that something changes it. – Bryan Oakley Jun 24 '20 at 13:55
  • And you're a 100% correct which is why i'm baffled but hopefully it can be figured out or worked around. So the radio buttons assigns the global as an IntVar, meaning anywhere in my code i can use .get() to retrieve the value. The problem comes when its used or assigned a new value, it changes to an Int, meaning no need to .get(). Is there a way to convert the value back to an IntVar? like you would use int()? – Adriaan vS Jun 25 '20 at 10:48
  • @YuMChUM777: tkinter will not change it from an `IntVar` to an `int`. Your code must be doing that somewhere. – Bryan Oakley Jun 25 '20 at 12:46
  • I think the problem comes when grouping the radio buttons with 'Filter_Num = tk.IntVar()' on the Setup Page and the initializing of the other pages where its monitored. '.get()' gives an error at initial start because Filter_Num is assigned an int at the global space 'Filter_Num = 3'. But at the Setup screen its changed to an IntVar to group the tkinter radio buttons, and that intVar is assigned its value (1-4). So it make sense that .get() gives an error if it tries to read that initial "3" at start and not the the "1-4" you'll insert inside the PY_VAR of the radio button. – Adriaan vS Jun 29 '20 at 09:58
  • Simpler Explanation: The Monitoring Page reads that initially assigned Integer before it gets changed to an IntVar when the Setup Page code is ran further down. Which explains why both the errors exist. The variable is an integer for a few milliseconds before it gets changed to IntVar, and in that time, the monitoring code tries to access it before its changed. – Adriaan vS Jun 29 '20 at 10:16
  • @YuMChUM777: _"Filter_Num is assigned an int at the global space 'Filter_Num = 3'"_ - your question doesn't show that, so it's impossible for us to have guessed that. This is why we prefer that you post a _complete_ [mcve]. Though it does prove that my answer is correct. – Bryan Oakley Jun 29 '20 at 14:05
  • That was my mistake, sorry. Thanks for the Tip, i'll follow the example route next time,and thanks for trying as well. – Adriaan vS Jun 30 '20 at 07:55
0

Managed to Get it working after seeing my silly mistake. The Errors were due to the order in which the GUI Classes were initialized. The Monitoring GUI classes starts before the Setup GUI screen where the radio buttons variables are grouped into IntVar() classes. This was fixed by changing the order in which they initialize in the MainView Class and running the Setup Class(Actually my 6th Page) 1st. The simplified code Now looks like this.

global Filter_Num = 2 #Initial Junk integer

Class Page4(page):                          ##IO Page##
    def __init__(self, *args, **kwargs):
        Page.__init__(self, *args, **kwargs)
        self.Create_IO_Widgets()
        self.IO_Updater()

    def Create_IO_Widgets(self):
        self.Filter2Can = tk.Canvas(self, width=30, height=30, bg="DarkOrange1")
        self.Filter2i = self.Filter2Can.create_oval(2,2,28,28,fill="red")
        self.Filter2Can.place(x=200,y=200)

    def Update_IO_Reading(self):
        if (Filter_Num.get()<2):
            self.Filter2Can.itemconfigure(self.Filter2i, fill="black")
        else:
            self.Filter2Can.itemconfigure(self.Filter2i, fill="red")

    def IO_Updater(self):
        self.Update_IO_Reading()
        self.after(500, self.IO_Updater)
           

Class Page6(Page):                          ##Setup Page##
    def __init__(self, *args, **kwargs):
        Page.__init__(self, *args, **kwargs)
        self.Create_Setup_Widgets()

    def Create_Setup_Widget(self)
        global Filter_Num               #Global declared in function so that Change can be made

        Filter_Num = tk.IntVar(Value=#) #Actual initial read value can be changed in here

        Filt1= tk.Radiobutton(self, text="1", variable=Filter_Num, value=1)
        Filt1.place(x=100,y=100)
        Filt2= tk.Radiobutton(self, text="2", variable=Filter_Num, value=2)
        Filt2.place(x=120,y=100)

Class MainView(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
        

        p6 = Page6(self);p4 = Page4(self) #Initializing Order Changed to prevent incorrect initial readings

I'll Leave the Question up although the actual error is slightly different than expected, and a silly mistake.

Answer = Make Sure the Order in which your code is run is correct

Adriaan vS
  • 43
  • 5