Issue with the get method of Tkinter (Python 2.x) [duplicate] - python-2.7

This question already has answers here:
Tkinter: AttributeError: NoneType object has no attribute <attribute name>
(4 answers)
Closed 4 years ago.
I am using Tkinter and I am having trouble with the get method. I saw that it was a common issue (here for example 'NoneType' object has no attribute 'get') but I don't really understand how to fix it.
I thought that station_I.get() was suppose to return a string variable but apparently I was wrong.
What is this issue due to ?
PS: I am using Tkinter with Python 2.7
Here is the error I get:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\python\Anaconda2\lib\lib-tk\Tkinter.py", line 1542, in __call__
return self.func(*args)
File "C:/Users/python/Documents/project.py", line 168, in path
print station_I.get()
AttributeError: 'NoneType' object has no attribute 'get'
Here is my code:
from Tkinter import *
import ttk
def path():
print station_I.get()
window = Tk()
stations = ["1","2","3"]
text = StringVar()
text.set("Path: ")
station_I = ttk.Combobox(window, values = stations).place(x=50, y=50)
station_F = ttk.Combobox(window, values = stations).place(x=50, y=100)
bouton = Button(window, command = path, text = "Calculate").place(x=125,y=150)
label = Label(window, textvariable = text).place(x=50,y=225)
window.geometry("330x400")
window.mainloop()

make sure you position your geometry manager on the next line after your variable for your widget
Replace this
station_I = ttk.Combobox(window, values = stations).place(x=50, y=50)
with
station_I = ttk.Combobox(window, values = stations)
station_I.place(x=50, y=50)
and all the variable for the widget variable with the example above.
Full code
from tkinter import *
from tkinter import ttk
def path():
print (station_I.get())
window = Tk()
stations = ["1","2","3"]
text = StringVar()
text.set("Path: ")
station_I = ttk.Combobox(window, values = stations)
station_I.place(x=50, y=50)
station_F = ttk.Combobox(window, values = stations)
station_F.place(x=50, y=100)
bouton = Button(window, command = path, text = "Calculate")
bouton.place(x=125,y=150)
label = Label(window, textvariable = text)
label.place(x=50,y=225)
window.geometry("330x400")
window.mainloop()

Related

Error assigning values to combobox (python 2.7)

i am getting an error whenever i try to add values to a combobox (python 2.7). Below is my code.
from Tkinter import *
from tkinter.ttk import *
class StartApp:
def __init__(self,Runtime):
self.Runtime = Runtime
Runtime.title("My App")
self.frame1 = Frame(Runtime, width=500)
self.frame1.grid(sticky='nsew')
self.SearchName_Combobox = Combobox(self.frame1).grid(row=3, column=3, columnspan=10)
self.SearchName_Combobox['values'] = [1,2,3]
root = Tk()
the_app = StartApp(root)
root.mainloop()
i get the following error.
TypeError: 'NoneType' object does not support item assignment
This solves the issue
from Tkinter import *
from tkinter.ttk import *
class StartApp:
def __init__(self,Runtime):
self.Runtime = Runtime
Runtime.title("My App")
self.frame1 = Frame(Runtime, width=500)
self.frame1.grid(sticky='nsew')
**self.SearchName_Combobox = Combobox(self.frame1)**
self.SearchName_Combobox['values'] = [1,2,3]
**self.SearchName_Combobox.grid(row=3, column=3, columnspan=10)**
root = Tk()
the_app = StartApp(root)
root.mainloop()
I tried to explain what i changed but apparently the bold formatting didn't work. This was the change
Original:
self.SearchName_Combobox = Combobox(self.frame1).grid(row=3, column=3, columnspan=10)
Corrected:
self.SearchName_Combobox = Combobox(self.frame1)
self.SearchName_Combobox.grid(row=3, column=3, columnspan=10)**

How can I make a button print in the display I created? (Tkinter)

I have been working on an app in python for a teacher at my school. What I want it to do is have a simple GUI and a way I can type in a word and it will print the words value in the same slot i typed the word.(kind of like a calculator) A=1 B=2 C=3 etc. It is fairly simple, as i am a beginner, but I can't quite get my button to show the value of the words I type in. If anyone could help it would be great!
Thanks!
Here is my code so far:
from Tkinter import *
import sys
def dollaramount():
print sum(map(" abcdefghijklmnopqrstuvwxyz".index, raw_input().lower()))
root = Tk()
frame = Frame(root)
frame.pack()
num1=StringVar()
topframe = Frame(root)
topframe.pack(side=TOP)
txtDisplay=Entry(frame, textvariable = num1, bd= 20, insertwidth= 1, font= 30, bg="white", fg="black")
txtDisplay.pack(side=TOP)
button1 = Button(topframe, padx=16, pady=16, bd=8, text="=", bg="white", fg="black", command=dollaramount)
button1.pack(side=LEFT)
root.mainloop()
I guess what you want is the following:
from Tkinter import *
import sys
def dollaramount():
# get the word written in the entry
word = num1.get()
# compute its value
val = sum(map(" abcdefghijklmnopqrstuvwxyz".index, word.lower()))
# display its value in the entry
num1.set("%s=%i" % (word, val))
root = Tk()
frame = Frame(root)
frame.pack()
num1=StringVar(root)
topframe = Frame(root)
topframe.pack(side=TOP)
txtDisplay=Entry(frame, textvariable = num1, bd= 20, insertwidth= 1, font= 30, bg="white", fg="black")
txtDisplay.pack(side=TOP)
button1 = Button(topframe, padx=16, pady=16, bd=8, text="=", bg="white", fg="black", command=dollaramount)
button1.pack(side=LEFT)
root.mainloop()
Your dollaramount function was not working because you used command line specific functions print and raw_input instead of using the set and get methods of the StringVar. I commented the code so that you can understand what it does.

Using Python Tkinter .config() method

I am trying to use the Python Tkinter .config() method to update some message text. I can't get it to work. What might I be doing wrong (see the update_message method):
#!/usr/bin/python
import alsaaudio as aa
import audioop
import Tkinter as tk
import tkFont
import threading
import Queue
# styles
BACKROUND_COLOR = '#000000'
TYPEFACE = 'Unit-Bold'
FONT_SIZE = 50
TEXT_COLOR = '#777777'
TEXTBOX_WIDTH = 400
# text
TITLE = 'listen closely'
SCORE_MESSAGE = 'your score:\n '
END_MESSAGE = 'too loud!\ntry again'
# configuration
DEVICE = 'hw:1' # hardware sound card index
CHANNELS = 1
SAMPLE_RATE = 8000 # Hz // 44100
PERIOD = 256 # Frames // 256
FORMAT = aa.PCM_FORMAT_S8 # Sound format
NOISE_THRESHOLD = 3
class Display(object):
def __init__(self, parent, queue):
self.parent = parent
self.queue = queue
self._geom = '200x200+0+0'
parent.geometry("{0}x{1}+0+0".format(
parent.winfo_screenwidth(), parent.winfo_screenheight()))
parent.overrideredirect(1)
parent.title(TITLE)
parent.configure(background=BACKROUND_COLOR)
parent.displayFont = tkFont.Font(family=TYPEFACE, size=FONT_SIZE)
self.process_queue()
def process_queue(self):
try:
score = self.queue.get(0)
self.print_message(score)
except Queue.Empty:
pass
self.parent.after(100, self.update_queue)
def update_queue(self):
try:
score = self.queue.get(0)
self.update_message(score)
except Queue.Empty:
pass
self.parent.after(100, self.update_queue)
def print_message(self, messageString):
print 'message', messageString
displayString = SCORE_MESSAGE + str(messageString)
self.message = tk.Message(
self.parent, text=displayString, bg=BACKROUND_COLOR,
font=self.parent.displayFont, fg=TEXT_COLOR, width=TEXTBOX_WIDTH, justify="c")
self.message.place(relx=.5, rely=.5, anchor="c")
def update_message(self, messageString):
print 'message', messageString
displayString = SCORE_MESSAGE + str(messageString)
self.message.config(text=displayString)
def setup_audio(queue, stop_event):
data_in = aa.PCM(aa.PCM_CAPTURE, aa.PCM_NONBLOCK, 'hw:1')
data_in.setchannels(2)
data_in.setrate(44100)
data_in.setformat(aa.PCM_FORMAT_S16_LE)
data_in.setperiodsize(256)
while not stop_event.is_set():
# Read data from device
l, data = data_in.read()
if l:
# catch frame error
try:
max_vol = audioop.rms(data, 2)
scaled_vol = max_vol // 4680
print scaled_vol
if scaled_vol <= 3:
# Too quiet, ignore
continue
queue.put(scaled_vol)
except audioop.error, e:
if e.message != "not a whole number of frames":
raise e
def main():
root = tk.Tk()
queue = Queue.Queue()
window = Display(root, queue)
stop_event = threading.Event()
audio_thread = threading.Thread(target=setup_audio,
args=[queue, stop_event])
audio_thread.start()
try:
root.mainloop()
finally:
stop_event.set()
audio_thread.join()
pass
if __name__ == '__main__':
main()
I don't want to be laying down a new message every time I update. If the .config() doesn't work, is there another method to update the text configuration of the message?
I would use string variables, first create your string variable then set it to want you want it to display at the start next make your object and in text put the sting variable then when you want to change the text in the object change the string variable.
self.messaget = StringVar()
self.messaget.set("")
self.message = tk.Message(
self.parent, textvariable=self.messaget, bg=BACKROUND_COLOR,
font=self.parent.displayFont, fg=TEXT_COLOR,
width=TEXTBOX_WIDTH, justify="c").grid()
#note renember to palce the object after you have created it either using
#.grid(row = , column =) or .pack()
#note that it is textvariable instead of text if you put text instead it will run but
#but will show PY_Var instead of the value of the variable
edit
to change the text without recreating the object you do the name of the string variable you have used and .set
self.messaget.set("hi")

Tcl Error: Out of Stack Space With Flask and Matplotlib in Python 2.7

Thanks for your time:
I created a flask server that takes in variables from a form post and outputs a pie or bar graph. While debugging, I noticed this error:
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
File "C:\Python27\lib\atexit.py", line 24, in _run_exitfuncs
func(*targs, **kargs)
File "C:\Python27\lib\site-packages\matplotlib\_pylab_helpers.py", line 92, in destroy_all
manager.destroy()
File "C:\Python27\lib\site-packages\matplotlib\backends\backend_tkagg.py", line 618, in destroy
self.canvas._tkcanvas.after_cancel(self.canvas._idle_callback)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 616, in after_cancel
self.tk.call('after', 'cancel', id)
TclError: out of stack space (infinite loop?)
Error in sys.exitfunc:
Traceback (most recent call last):
File "C:\Python27\lib\atexit.py", line 24, in _run_exitfuncs
func(*targs, **kargs)
File "C:\Python27\lib\site-packages\matplotlib\_pylab_helpers.py", line 92, in destroy_all
manager.destroy()
File "C:\Python27\lib\site-packages\matplotlib\backends\backend_tkagg.py", line 618, in destroy
self.canvas._tkcanvas.after_cancel(self.canvas._idle_callback)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 616, in after_cancel
self.tk.call('after', 'cancel', id)
_tkinter.TclError: out of stack space (infinite loop?)
This seems to cause the server to reload (successfully for what it's worth) which is a problem. No clue what's going on here, other than tkinter being upset. And, no luck with my google fu.
flask server (w debug settings. Mapped vars are due to a project req.):
# Flask App that functions as a graph end point replacement "DAC-780"
# Standard Library
import os
import uuid
# Third Party
from flask import Flask, request
# Local
from pie import make_pie
from bar import make_bar
app_root = os.path.dirname(os.path.abspath(__file__))
images = os.path.join(app_root, 'static/images')
app = Flask(__name__, static_folder="static")
app._static_folder = os.path.join(app_root, 'static')
#app.route('/charts/<path>', methods=['POST'])
def graph(path):
g_data_list = []
file_name = str(uuid.uuid4())
# if bar graph
if path == "chart4.asp":
# grab vars
g_title = str(request.form['Title'])
x_title = str(request.form['CatTitle'])
y_title = str(request.form['ValTitle'])
ser1 = str(request.form['Ser1'])
ser2 = str(request.form['Ser2'])
cat1 = str(request.form['Cat1'])
cat2 = str(request.form['Cat2'])
cat3 = str(request.form['Cat3'])
cat4 = str(request.form['Cat4'])
cat5 = str(request.form['Cat5'])
cat6 = str(request.form['Cat6'])
cat7 = str(request.form['Cat7'])
cat8 = str(request.form['Cat8'])
cat9 = str(request.form['Cat9'])
cat10 = str(request.form['Cat10'])
cat11 = str(request.form['Cat11'])
cat12 = str(request.form['Cat12'])
cat13 = str(request.form['Cat13'])
s1d1 = int(request.form['S1D1'])
s1d2 = int(request.form['S1D2'])
s1d3 = int(request.form['S1D3'])
s1d4 = int(request.form['S1D4'])
s1d5 = int(request.form['S1D5'])
s1d6 = int(request.form['S1D6'])
s1d7 = int(request.form['S1D7'])
s1d8 = int(request.form['S1D8'])
s1d9 = int(request.form['S1D9'])
s1d10 = int(request.form['S1D10'])
s1d11 = int(request.form['S1D11'])
s1d12 = int(request.form['S1D12'])
s1d13 = int(request.form['S1D13'])
s2d1 = int(request.form['S2D1'])
s2d2 = int(request.form['S2D2'])
s2d3 = int(request.form['S2D3'])
s2d4 = int(request.form['S2D4'])
s2d5 = int(request.form['S2D5'])
s2d6 = int(request.form['S2D6'])
s2d7 = int(request.form['S2D7'])
s2d8 = int(request.form['S2D8'])
s2d9 = int(request.form['S2D9'])
s2d10 = int(request.form['S2D10'])
s2d11 = int(request.form['S2D11'])
s2d12 = int(request.form['S2D12'])
s2d13 = int(request.form['S2D13'])
# vars i mapped but weren't needed for my graph lib
g_type = str(request.form['Type'])
g_cats = str(request.form['Cats'])
g_series = str(request.form['Series'])
cat_title = str(request.form['CatTitle'])
# add data to g_data_list so we can process it
g_data_list.append((ser1, [s1d1, s1d2, s1d3, s1d4, s1d5, s1d6, s1d7, s1d8,
s1d9, s1d10, s1d11, s1d12, s1d13]))
g_data_list.append((ser2, [s2d1, s2d2, s2d3, s2d4, s2d5, s2d6, s2d7, s2d8,
s2d9, s2d10, s2d11, s2d12, s2d13]))
x_labels = [cat1, cat2, cat3, cat4, cat5, cat6, cat7, cat8, cat9, cat10,
cat11, cat12, cat13]
# make a graph to return in html
graph = make_bar(g_title, y_title, x_labels, g_data_list, file_name, cat_title, x_title)
else:
# all others are probably pie graphs
g_title = str(request.form['Title'])
cat1 = str(request.form['Cat1'])
cat2 = str(request.form['Cat2'])
cat3 = str(request.form['Cat3'])
cat4 = str(request.form['Cat4'])
s1d1 = int(request.form['S1D1'])
s1d2 = int(request.form['S1D2'])
s1d3 = int(request.form['S1D3'])
s1d4 = int(request.form['S1D4'])
# vars that aren't needed for replications of the final product, but
# were part of the old code
g_type = str(request.form['Type'])
g_cats = str(request.form['Cats'])
g_series = str(request.form['Series'])
cat_title = str(request.form['CatTitle'])
val_title = str(request.form['ValTitle'])
s1 = str(request.form['Ser1'])
s2 = str(request.form['Ser2'])
# add data
g_data_list.append([cat1, s1d1])
g_data_list.append([cat2, s1d2])
g_data_list.append([cat3, s1d3])
g_data_list.append([cat4, s1d4])
# make graph to send back via html
graph = make_pie(g_title, g_data_list, file_name)
# make a web page with graph and return it
html = """
<html>
<head>
<title>%s</title>
</head>
<body>
<img src="/static/images/%s.png" alt="An Error Occured"/>
</body>
</html>
""" % (g_title, str(file_name))
return html
if __name__ == '__main__':
app.run(port=3456, host="0.0.0.0", debug=True)
bar.py:
# creates a bar chart based on input using matplotlib
import os
import numpy as np
import matplotlib.pyplot as plt
from pylab import rcParams
rcParams['figure.figsize'] = 6.55, 3.8
app_root = os.path.dirname(os.path.abspath(__file__))
images = os.path.join(app_root, 'static/images')
def make_bar(g_title, y_title, x_labels, data_series, file_name, cat_title,
x_title):
n_groups = 13
bar_width = 0.35
opacity = 0.4
fig, ax = plt.subplots()
index = np.arange(n_groups)
error_config = {'ecolor': '0.3'}
plt.bar(index, tuple(data_series[0][1]), bar_width,
alpha=opacity,
color='b',
error_kw=error_config,
label='{}'.format(data_series[0][0]))
plt.bar(index + bar_width, tuple(data_series[1][1]), bar_width,
alpha=opacity,
color='r',
error_kw=error_config,
label='{}'.format(data_series[1][0]))
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
plt.xlabel(x_title, fontsize=10)
plt.ylabel(y_title, fontsize=10)
plt.title(g_title, fontsize=11)
plt.xticks(index + bar_width, tuple(x_labels), fontsize=8)
plt.yticks(fontsize=8)
plt.axis('tight')
lgd = plt.legend(fontsize=8, bbox_to_anchor=(1.15, 0.5))
plt.tight_layout()
plt.draw()
plt.savefig('{}/{}.png'.format(images, file_name),
dpi=100, format='png', bbox_extra_artists=(lgd,),
bbox_inches='tight')
return
pie.py:
# creates a pie chart w/ matplotlib
import os
import matplotlib.pyplot as plt
from pylab import rcParams
app_root = os.path.dirname(os.path.abspath(__file__))
images = os.path.join(app_root, 'static/images')
def make_pie(title, g_data_list, file_name):
rcParams['figure.figsize'] = 5.75, 3
labels = [entry[0] for entry in g_data_list]
sizes = [entry[1] for entry in g_data_list]
ax = plt.subplot(111)
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.7, box.height])
patches, texts = ax.pie(sizes, startangle=90)
ax.legend(patches, labels, loc='center left',
bbox_to_anchor=(.9, 0.5), fontsize=8)
plt.axis('equal')
plt.suptitle(g_title, fontsize=12)
plt.draw()
plt.savefig('{}/{}.png'.format(images, file_name), dpi=100, format='png')
return
I noticed that the function that graphed everything, when run separately, would stay running after I closed the plot window. Adding plt.clf() fixed that problem, and appears to be the solution to mine relating to Flask as well.
Had same problem with seaborn
import matplotlib
matplotlib.use('Agg')
helps me.
details: https://matplotlib.org/faq/usage_faq.html#what-is-a-backend

Passing text from a function to a gui

I've got a GUI function in a file 'test_gui.py', which is adapted from one of Bryan Oakley's answers to a question regarding getting text from a Tkinter entry box.
import sys
import os
import Tkinter as tk
class testing(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.label1 = tk.Label(self, text = "Enter benchmark version")
self.label2 = tk.Label(self, text = "Enter test_suite (a for all)")
self.label3 = tk.Label(self, text = "Enter sub_suite t or w")
self.entry1 = tk.Entry(self)
self.entry2 = tk.Entry(self)
self.entry3 = tk.Entry(self)
self.button = tk.Button(self, text="Get", command=self.on_button)
self.button.grid(row = 4, column = 0)
self.label1.grid(row = 1, column = 0)
self.label2.grid(row = 2, column = 0)
self.label3.grid(row = 3, column = 0)
self.entry1.grid(row = 1, column = 1)
self.entry2.grid(row = 2, column = 1)
self.entry3.grid(row = 3, column = 1)
def on_button(self):
benchmark = self.entry1.get()
test_suite = self.entry2.get()
sub_suite = self.entry3.get()
home_path=os.path.dirname(os.path.abspath(__file__))
path = os.path.join(home_path, sub_suite, 'results')
sys.path.insert(0, path)
import compare_data as compare
compare.compare_results(benchmark, test_suite)
self.label4 = tk.Label(self, text=fil)
self.button2.grid(row = 5, column = 10)
app = testing()
app.mainloop()
and I need to pass it 'fil' from a different function which is run after pressing button through the function compare_results. In this function I've got:
import test_gui
test_gui.testing(fil)
To do this I think I need to define on_button as
def on_button(self, fil)
But then this returns the error that on_button requires two arguments. If I give fil a default value it will pass that to the label on pressing the button.
Is there a way of passing text from a function run through a gui back to the gui?
You can use lambda to pass more arguments to the button command.
So instead of
command = self.on_button
You could use
command = lambda: self.on_button(fil)
To pass 'fil' to the on_button function.
Is this what you had in mind?