Python: retrieve objects's value from a class object - python

Here is my problem, I'm creating a Tkinter GUI
and in a class object I call for a text tipped in a textfield and make an array of it
But I can't find how to retrieve and use this object later on in the script.
Here my script
import pandas as pd
from pandas import *
import numpy as np
import Tkinter
from Tkinter import *
from pylab import *
from ttk import *
import ScrolledText
df = pd.DataFrame(np.random.randint(100, 500, size = (10, 20)), index = list('abcdefghij'))
mylist = df.index.values.tolist()
rootWin = Tkinter.Tk()
class GraphGUI():
def __init__(self, rootWin):
self.textfield = ScrolledText.ScrolledText(rootWin, width=30, height=10)
#Add some text:
self.textfield.insert(INSERT, "Replace")
self.textfield.grid(column=0, row=4)
self.button = Button(rootWin, text="Process!", command=self.clicked)
self.button.grid(column=1, row=4)
def clicked(self):
eText = self.textfield.get('1.0', END)
converted = eText.encode('ascii','ignore')
myarray = converted.splitlines()
print(myarray)
def clicked2():
print(clicked.myarray)
start = Tkinter.Button(rootWin, text="start!", command=clicked2).grid(column=7, row=8)
app = GraphGUI( rootWin )
rootWin.mainloop()
The problem is when I click on the process Button no problem myarray get printed.
But when I use the start button I can't retrieve it.
Is there a way to retrieve myarray out of the Class object?
Also Is it possible to print myarray with the Start button without having to use the Process button first?
##### EDIT
Here the final working script thanks to the help
class GraphGUI():
def __init__(self, rootWin):
self.textfield = ScrolledText.ScrolledText(rootWin, width=30, height=10)
#Add some text:
self.textfield.insert(INSERT, "Replace by your Accession list")
self.textfield.grid(column=6, row=4)
self.button = Button(rootWin, text="Process!", command=self.clicked)
self.button.grid(column=7, row=4)
#property
def myarray(self):
e_Text = self.textfield.get('1.0', END)
converted = e_Text.encode('ascii','ignore')
return converted.splitlines()
def clicked(self):
print(self.myarray)
print(variablea.get()) #not defined here#
print(variableb.get())
def clicked2():
print(app.myarray)
start = Tkinter.Button(rootWin, text="start!", command=clicked2).grid(column=7, row=10)

Looks like you're trying to access a local variable of an object method. That's not possible. If you need it, try defining it as its own callback instead.
class GraphGUI():
def __init__(self, rootWin):
self.textfield = ScrolledText.ScrolledText(rootWin,
width=30,
height=10)
# Add some text:
self.textfield.insert(INSERT, "Replace")
self.textfield.grid(column=0, row=4)
self.button = Button(rootWin, text="Process!", command=self.clicked)
self.button.grid(column=1, row=4)
def clicked(self):
eText = self.textfield.get('1.0', END)
converted = eText.encode('ascii', 'ignore')
myarray = converted.splitlines()
return myarray
rootWin = Tkinter.Tk()
app = GraphGUI(rootWin)
start = Tkinter.Button(rootWin, text="start!", command=app.clicked)
start.grid(column=7, row=8) # your code assigned `start = None` btw
rootWin.mainloop()
Alternatively, myarray could just be defined as a property of the class.
class GraphGUI():
...
#property
def myarray(self):
e_txt = self.textfield.get('1.0', END)
converted = e_txt.encode('ascii', 'ignore')
return converted.splitlines()
def clicked(self):
print(self.myarray)
# do whatever else it has to do
rootWin = Tkinter.Tk()
start = Tkinter.Button(rootWin, text="Start!",
command=lambda: app.myarray)
...

You are trying to access a local variable in the method of an object, which you simply cannot do.
What you can do is that that other method return the object, or you can convert that local variable into an instance variable.
The simplest solution is to have the function return the data that you want:
class GraphGUI():
...
def clicked(self):
...
return myarray
def clicked2():
myarray = app.clicked()
print("myarray:", myarray)

Related

I cant update labels in tkinter

I can't seem to update my money counter(var money) when its labeled, I have a button that's supposed to add 0.1 to moneyNum but the money counter doesn't change. I'm new to stack overflow and would appreciate any help.(btw sry if its REALLY messy)
from tkinter import *
import random
from time import sleep
root = Tk()
root.geometry('320x320')
#spacing
spacingTitle = Label(root, text=" \n\n\n\n\n\n\n\n\n")
#title
title = Label(root, text=" \bGamblers Dream\b", font="Helvetica", fg="red")
titleWelcom = Label(root, text=" Welcom to...")
titleWelcom.grid()
title.grid()
#money counter
moneyNum = float(10.0)
money = Label(root, text="money:" + str(moneyNum), font="Helvetica")
money.grid(row=3, column=0)
#moneyClicker
def moneyButtonAdder():
global moneyNum
moneyNum = moneyNum + 0.1
moneyClicker = Button(root, text="click", fg="green", command=moneyButtonAdder)
moneyClicker.grid(row=14)
root.mainloop()
The problem is that once you create a label, you pass the string to it. Label displays the string, and:
changing a string object does not change the label text
changing the integer does not change the string - it lost the whole connection when the new string object was created
So everything is not as procedural as you would have hoped it is.
The solution - use StringVar objects and detect value changes - see this.
So, the solution is:
from tkinter import *
class Observed(object):
"""adapted copy from https://stackoverflow.com/a/6192298/10713244"""
def __init__(self):
self._observed = 10.0
self._observers = []
#property
def observed(self):
return self._observed
#observed.setter
def observed(self, value):
self._observed = value
for callback in self._observers:
print('announcing change')
callback(self._observed)
def bind_to(self, callback):
print('bound')
self._observers.append(callback)
class Observer(object):
def __init__(self, data):
self.text = ''
self.data = data
self.data.bind_to(self.update)
self.tkinter_init()
def update(self, observed):
self.text = 'float: '+str(data._observed)
self.tkinter_update()
def tkinter_init(self):
self.tk = Tk()
self.tvar = StringVar()
self.label = Label(textvariable=self.tvar)
self.label.pack()
def tkinter_update(self):
self.tvar.set(self.text)
if __name__ == '__main__':
data = Observed()
label = Observer(data)
print(label.text)
data.observed = 10.0
print(label.text)
def dec(): data.observed -= 0.1
Button(label.tk, text='decrease', command=dec).pack()
label.tk.mainloop()
Hope that's helpful!

I want to create a toolbar that when clicking a button, change the frame

I created a program that when clicking on one of the buttons, it changes the frame, which contains other functions.
I tried to use ['frame'] .config, a simple function of the same, but nothing works.
from tkinter import *
from Item import Item
from Monstro import Monster
class Ferramentas:
def __init__(self,master,Item,Monster):
self.Item = Item
self.Monster = Monster
self.ferramentas = Frame(master)
self.ferramentas.grid(row=0,column=0)
self.b1 = Button(self.ferramentas,text='CALCULADORA')
self.b2 = Button(self.ferramentas,text='MONSTROS',command=self.Monstros)
self.b3 = Button(self.ferramentas,text='ITENS',command=self.Itens)
self.b1.grid(row=0,column=0)
self.b2.grid(row=0,column=1)
self.b3.grid(row=0,column=2)
self.frame_mestre = Frame(master)
self.frame_mestre.grid(row=1,column=0)
def Itens(self):
self.frame_mestre = self.Item.frame_2
self.Item.frame_2.grid(row=1,column=0,sticky="nsew")
def Monstros(self):
self.frame_mestre = self.Monster.frame_1
self.Monster.frame_1.grid(row=1,column=0,sticky="nsew")
janela = Tk()
c = Monster(janela)
b = Item(janela)
a = Ferramentas(janela,b,c)
janela.mainloop()
class Item:
def __init__(self,master):
self.frame_2 = Frame(master)
self.item_nome = Label(self.frame_2, text='NOME')
self.item_nome.grid(row=0,column=1)
class Monster:
def __init__(self, master):
self.frame_1 = Frame(master)
self.nome = Label(self.frame_1, text='NOME', relief='raised')
self.nome.grid(row=0,column=1, columnspan=2)
I hope that by clicking on the respective button, the frames change, without one overlapping the other

Python 3.x - using text string as variable name

I'm trying to avoid to multiply functions in code by using
def Return_Label(self,number)
with a parameter.
Any Idea how to use string in order to define variable name usable to .set value to StringVar()?
Example code below:
import tkinter as tk
from tkinter import *
class WINDOW():
def __init__(self):
self.Settings_Window()
def Settings_Window(self):
self.settings_window = tk.Tk()
self.settings_window.minsize(200,200)
self.entry = Entry(self.settings_window)
self.entry.pack()
self.entry2 = Entry(self.settings_window)
self.entry2.pack()
self.label1input = StringVar()
self.label = Label(self.settings_window,textvariable=self.label1input, bg='yellow')
self.label.pack(expand='yes',fill='x')
self.label2input = StringVar()
self.label2 = Label(self.settings_window, textvariable=self.label2input, bg='yellow')
self.label2.pack(expand='yes', fill='x')
self.button = Button(self.settings_window,text='SETUP1',command=self.Next)
self.button.pack()
self.button2 = Button(self.settings_window,text='SETUP2',command=self.Next2)
self.button2.pack()
self.settings_window.mainloop()
def Next(self):
self.number=1
self.Return_Label(self.number)
def Next2(self):
self.number=2
self.Return_Label(self.number)
def Return_Label(self,number):
self.entry_field_value = self.entry.get()
print(self.entry_field_value)
#self.label1input.set(self.entry_field_value)
setattr(self,'label'+str(number)+'input.set',self.entry_field_value)
window=WINDOW()
I prefer a list approach to managing multiple entry fields and updating values.
By using list you can use the index value to manage the labels as well :D.
See the below example of how you can use list to deal with all the values and updates.
import tkinter as tk
from tkinter import *
class Window(tk.Tk):
def __init__(self):
super().__init__()
self.minsize(200, 200)
self.entry_list = []
self.label_list = []
entry_count = 2
for i in range(entry_count):
self.entry_list.append(Entry(self))
self.entry_list[i].pack()
for i in range(entry_count):
self.label_list.append(Label(self,bg='yellow'))
self.label_list[i].pack(expand='yes', fill='x')
Button(self, text='SETUP', command=self.Return_Label).pack()
def Return_Label(self):
for ndex, lbl in enumerate(self.label_list):
lbl.config(text=self.entry_list[ndex].get())
if __name__ == '__main__':
Window().mainloop()
Create lists of objects rather than individual attributes for each object. For example,
import tkinter as tk
from tkinter import *
class Window:
def __init__(self):
self.settings_window()
def Settings_Window(self):
self.settings_window = tk.Tk()
self.settings_window.minsize(200,200)
self.entries = [
Entry(self.settings_window),
Entry(self.settings_window)
]
for e in self.entries:
e.pack()
self.labelinputs = [
StringVar(),
StringVar()
]
self.labels = [
Label(self.settings_window, textvariable=label, bg='yellow')
for label in self.labelinputs
]
for l in self.labels:
l.pack(expand='yes', fill='x')
self.buttons = [
Button(self.settings_window,text='SETUP1',command=lambda: self.return_label(0))
Button(self.settings_window,text='SETUP2',command=lambda: self.return_label(1))
]
for b in self.buttons:
b.pack()
self.settings_window.mainloop()
def return_label(self,number):
entry_field_value = self.entry.get()
self.labelsinput[number].set(entry_field_value)
window=WINDOW()
Dynamicly computing variable names should be avoided at all costs. They are difficult to do correctly, and it makes your code hard to understand, hard to maintain, and hard to debug.
Instead, store the widgets in a dictionary or list. For example:
def __init___(self):
...
self.vars = {}
...
self.vars[1] = StringVar()
self.vars[2] = StringVar()
...
def Return_Label(self,number):
self.entry_field_value = self.entry.get()
var = self.vars[number]
var.set(self.entry_field_value)
Though, you really don't need to use StringVar at all -- they usually just add extra overhead without providing any extra value. You can save the labels instead of the variables, and call configure on the labels
self.labels[1] = Label(...)
...
self.labels[number].configure(text=self.entry_field_value)

Tkinter Radiobutton Text

I have the following code:
class Test:
def __init__(self, master): # master is a Tk or Toplevel instance
self.master, self.typeFrame = master, tk.Frame(master)
self.typeVar = tk.StringVar(self.typeFrame)
for column, wordType in enumerate(['Noun', 'Verb', 'Adjective', 'Adverb'], 1):
typeRadioButton = tk.Radiobutton(self.typeFrame, text = wordType, textvariable = self.typeVar, value = wordType, command = self.createLambda(wordType))
typeRadioButton.grid(row = 1, column = column)
self.typeFrame.grid()
def createLambda(self, obj):
return lambda: self.changeInfo(obj)
def changeInfo(self, obj):
pass # this will do something later
However, when I run the code like this, the Radiobuttons have no text associated with them.
root = tk.Tk()
test_instance = Test(root)
test_instance.master.mainloop()
How can I fix this? Thanks in advance!
Change textvariable=... to variable=....
BTW, your example does not contain self.typeFrame.pack() or self.typeFrame.grid(..).

Get variables from Entry PYTHON 3

so I'm coding this GUI-program (using tkinter) and I'm using three Entryboxes in the same function. I wanna use their values in the main function, so how do I get the values into some kind of global variable or in a way that I can use them in a different function?
def options():
options_root = Tk()
textFrame = Frame(options_root)
textFrame.grid()
widthlabel = Label(textFrame, text="w:", justify=LEFT)
widthlabel.grid(column="0", row="0")
widthinput = Entry(textFrame)
widthinput.grid(column="1", row="0")
heightlabel = Label(textFrame, text="h:", justify=LEFT)
heightlabel.grid(column="0", row="1")
heightinput = Entry(textFrame)
heightinput.grid(column="1", row="1")
mlabel = Label(textFrame, text="m:", justify=LEFT)
mlabel.grid(column="0", row="2")
minput = Entry(textFrame)
minput.grid(column="1", row="2")
width = widthinput.get()
height = heightinput.get()
m = minput.get()
start_game_button = Button(options_root, text="Start", justify=LEFT, command=lambda:tabort(options_root))
start_game_button.grid(column="0",row="3")
exit_button = Button(options_root, text = "Exit", justify=LEFT, command=exit)
exit_button.grid(column="1", row="3")
mainloop()
def main():
options()
w = widthinput.get()
h = heightinput.get()
m = minput.get()
main()
Keep a reference to the widgets, then use the get() method. This becomes much easier if you design your application as a class:
import tkinter as tk
class SampleApp(tk.Tk):
def __init__(self, ...):
...
self.width_entry = tk.Entry(...)
self.height_entry = tk.Entry(...)
self.minput_entry = tk.Entry(...)
...
def main(...):
w = self.width_entry.get()
h = self.height_entry.get()
m = self.input_entry.get()
...
...
app = SampleApp()
app.mainloop()

Categories

Resources