Home > Enterprise >  How to I access the value of a function called inside a tkinter button?
How to I access the value of a function called inside a tkinter button?

Time:01-08

def play():
    wind2 = tk.Toplevel()
    v = tk.IntVar()
    ques = ["Identify the least stable ion amongst the following.",
            "The set representing the correct order of first ionisation potential is",
            "The correct order of radii is"]
    o1 = ["", "Li⁺", "Be⁻", "B⁻", "C⁻"]
    o2 = ["", "K > Na > Li", "Be > Mg >Ca", "B >C > N", "Ge > Si >C"]
    o3 = ["", "N < Be < B", "F⁻ < O²⁻ < N³⁻", "Na < Li < K", "Fe³⁺ < Fe⁴⁺ < Fe²⁺"]
    choice=[o1, o2, o3]
    ans=[2,2,2]
    qsn = tk.Label(wind2, text = ques[0])
    qsn.pack()

    def selection():
        selected = v.get()
        return selected
        
    r1 = tk.Radiobutton(wind2, text = o1[1], variable = v, value = 1, command=selection)
    r2 = tk.Radiobutton(wind2, text = o1[2], variable = v, value = 2, command=selection)
    r3 = tk.Radiobutton(wind2, text = o1[3], variable = v, value = 3, command=selection)
    r4 = tk.Radiobutton(wind2, text = o1[4], variable = v, value = 4, command=selection)
    r1.pack()
    r2.pack()
    r3.pack()
    r4.pack()

    def nxt():
        n = random.randint(1,2)
        qsn['text'] = ques[n]
        r1['text'] = choice[n][1]
        r2['text'] = choice[n][2]
        r3['text'] = choice[n][3]
        r4['text'] = choice[n][4]
        return n
        
    nbut = tk.Button(wind2, text = "next", command = nxt)
    nbut.pack()

Here the nxt function is being called when nbut is clicked. But how do I access the value returned by nxt (i.e. n)? Basically I'm trying to build a quiz. n gives me the question number and selected gives what the user has selected. I'm trying to compare selected with the correct answer from the list ans

CodePudding user response:

Try making the variable n a global variable

     def nxt():
         global n
         n = random.randint(1,2)
         qsn['text'] = ques[n]
         r1['text'] = choice[n][1]
         r2['text'] = choice[n][2]
         r3['text'] = choice[n][3]
         r4['text'] = choice[n][4]

Then you won't have to use return n anymore and can still access the value of the variable outside the function

CodePudding user response:

I would suggest an alternative approach. Instead of using using a global variable or creating a placeholder that is initially set to None, which can be error prone and negatively effect readability, you can instead iterate through your list of questions and see which one matches the current label text to see which is the current question being asked.

For example:

def play():
    wind2 = tk.Toplevel()
    v = tk.IntVar()
    ques = ["Identify the least stable ion amongst the following.",
            "The set representing the correct order of first ionisation potential is",
            "The correct order of radii is"]
    o1 = ["", "Li⁺", "Be⁻", "B⁻", "C⁻"]
    o2 = ["", "K > Na > Li", "Be > Mg >Ca", "B >C > N", "Ge > Si >C"]
    o3 = ["", "N < Be < B", "F⁻ < O²⁻ < N³⁻", "Na < Li < K", "Fe³⁺ < Fe⁴⁺ < Fe²⁺"]
    choice=[o1, o2, o3]
    ans=[2,2,2]
    user_answer = []  # used to store user selected answers
    qsn = tk.Label(wind2, text = ques[0])
    qsn.pack()

    def selection():
        selected = v.get()
        for i in range(len(ques)):  # iterate through question text
            if qsn["text"] == ques[i]:  # if question text matches current label text
                break    # we have the right question index so stop iterating
        if ans[i] == selected:      # if the selected answer matches the accurate answer
            print("Correct Answer")
        else:
            print("Incorrect Answer")
        user_answer.append((i, selected))  # store question index and selected answer in the user_answer list
        print(user_answer)      

    r1 = tk.Radiobutton(wind2, text = o1[1], variable = v, value = 1, command=selection)
    r2 = tk.Radiobutton(wind2, text = o1[2], variable = v, value = 2, command=selection)
    r3 = tk.Radiobutton(wind2, text = o1[3], variable = v, value = 3, command=selection)
    r4 = tk.Radiobutton(wind2, text = o1[4], variable = v, value = 4, command=selection)
    r1.pack()
    r2.pack()
    r3.pack()
    r4.pack()

    def nxt():
        n = random.randint(1,2)
        qsn['text'] = ques[n]
        r1['text'] = choice[n][1]
        r2['text'] = choice[n][2]
        r3['text'] = choice[n][3]
        r4['text'] = choice[n][4]

    nbut = tk.Button(wind2, text = "next", command = nxt)
    nbut.pack()

To answer your original question, there really is no way to get a return value from a callback function in this context, you need to store the value in some other way if you do need it for later. You can see one example of this at the end of the selection method. This line user_answer.append((i, selected)) stores the question index and the selection number in an empty list I created at load time.

  • Related