Python Tkinter Entry Values Method Errors - python

The code is intended to write a few things to a line in a text file.
from tkinter import *
Tag=0
x="txt.txt"
w=open(x,"w")
root=Tk()
win1=Frame(root)
Label(root,text="Tag").pack()
tagE=Entry(root)
tagE.pack()
def get_it():
Tag=(tagE.get())
v=Button(root,text="Submit",command=get_it)
v.pack()
win1.pack()
w.write("%s var=%s"%(Tag,"text"))
w.close()
root.mainloop()
The Tag=(tagE.get()) is indented for more spaces than it is. When i run this code i will either get a "AttributError: 'NoneType' object has no attribute 'get' or the tag value will equal its original value of 0. Help is very much appreciated.

Apart from getting the value of the entry, you have to write the value in the file in the same function:
from tkinter import *
filename = "txt.txt"
root=Tk()
Label(root,text="Tag").pack()
tagE=Entry(root)
tagE.pack()
def get_it():
w=open(filename, "w")
tag = tagE.get()
w.write("%s var=%s"%(tag,"text"))
w.close()
v=Button(root,text="Submit",command=get_it)
v.pack()
root.mainloop()
Since you don't use the Frame as parent of any of your widgets, you can use the root element directly. As a side note, I recommend you to use lowercase notation for your variables as suggested in the PEP8, and try to use clearer names.

You misunderstand how Tkinter works. Your print statement will execute before you have a chance to click the button. You need to put your print statement inside get_it.

Related

Adding and updating new widget in tkinter in runtime

I am trying to build a GUI creator using Python and Tkinter, but ran into a problem.
My problem is How to add\update widgets in runtime?
for example:
I have created the main window.
In that main window, I have created a frame name w_frame which contains a bunch of widget.
Based on my input in the Text or Entry widget beside the w_frame, I want to update a particular widget.
Lets say w_frame contains a Entry widget, radio button, button and label all available with the basic or main attributes need to display it.
Now I want to change the background color of label.
In short I want to write the code label_name.property_name=value or for example a_label.bg=red in the text widget and as soon as I press apply button, the widget should change.
I have searched on web, but not able to find the required solution. Also tried using How can i update a certain widget in tkinter, but that does not work depending on my input.
from tkinter import *
root=Tk()
w_frame=Frame()
w_frame.pack()
def update_Frame():
a=u_text_wid.get("1.0",END)
b.config(a)
root.update()
def add_wid_in_frame():
global a,b
a=Button(w_frame,text='heelo')
a.pack()
b=Label(w_frame,text='heelo')
b.pack()
u_text_wid=Text()
u_text_wid.pack()
button1=Button(text="add",command=add_wid_in_frame)
button1.pack()
button1=Button(text="update",command=update_Frame)
button1.pack()
root.mainloop()
this results me in an error
unknown option "-bg="red"
Note:
I want to update the widget based on the property value provided by the user, so it wont be hard-code into the script.
You are getting the error because every thing you retrieve from Text widget is a string and you cannot directly pass an string to .config method, you need a keyword and then you can assign value which can be string.
According to your question and the comments on the question, what i have figured out is:
You want to run lable.config(bg='red') from the Text widget.
You want to change the property of specific widget.
Here's what you can do:
To run Tkinter code form Text widget, you can use:
getattr method
eval method
Just to change property of widget:
def update_Frame():
global bcd
a = u_text_wid.get("1.0", "end-1c")
b=a.split(",")
c=[tuple(i.split("=")) if "=" in i else i for i in b]
d=dict(i for i in c)
for key,value in d.items():
bcd[key]=value
We can use string to change property only in this format widget_name[key]=value.
Some Useful Links:
Eval()
Getattr()
For your case, you can use ast.literal_eval() to convert a JSON string to dictionary and use the dictionary in .config():
from ast import literal_eval
...
def update_Frame():
a = u_text_wid.get("1.0", "end-1c") # don't include ending newline
cnf = literal_eval(a) # convert JSON string to dictionary
b.config(cnf)
Example input of the JSON string:
{"fg":"yellow", "bg":"red"}
Note that you can also use json module to convert the JSON string as well.

Tkinter text widget - Why does INSERT not work as text index?

I have a problem that annoys me. I am currently building a small app with a Tkinter GUI.
On the front page, I want some introductory text in either a text or a scrolledtext widget. The code examples I've come across uses keywords such as INSERT, CURRENT and END for indexation inside the widget.
I have literally copy pasted the below code into my editor, but it doesn't recognise INSERT (throws error: "NameError: name 'INSERT' is not defined"):
import tkinter as tk
from tkinter import scrolledtext
window = tk.Tk()
window.title("test of scrolledtext and INSERT method")
window.geometry('350x200')
txt = scrolledtext.ScrolledText(window,width=40,height=10)
txt.insert(INSERT,'You text goes here')
txt.grid(column=0,row=0)
window.mainloop()
I can get the code to work if I change [INSERT] with [1.0], but it is very frustrating that I cannot get INSERT to work, as I've seen it in every example code I've come across
Use tk.INSERT instead of only INSERT. Full code is shown.
import tkinter as tk
from tkinter import scrolledtext
window = tk.Tk()
window.title("test of scrolledtext and INSERT method")
window.geometry('350x200')
txt = scrolledtext.ScrolledText(window,width=40,height=10)
txt.insert(tk.INSERT,'You text goes here')
txt.grid(column=0,row=0)
window.mainloop()
You don't need to use the tkinter constants. I personally think it's better to use the raw strings "insert", "end", etc. They are more flexible.
However, the reason the constants don't work for you is that you're not directly importing them. The way you're importing tkinter, you need to use tk.INSERT, etc.
INSERT could not be used directly.
You can use it in the past just because you used this in the past:
from tkinter import * # this is not a good practice
INSERT,CURRENT and END are in tkinter.constants.Now in your code,you even didn't import them.
If you want to use them,you can use
from tkinter.constants import * # not recommended
...
txt.insert(INSERT,'You text goes here')
Or
from tkinter import constants
...
txt.insert(constants.INSERT,'You text goes here') # recommend
If didn't want to import them,you can also use:
txt.insert("insert",'You text goes here')
Edit:I found in the source code of tkinter,it had import them,reboot's answer is also OK.

Tkinter cbox doesn't change var value

So, essentially what is going on is I made a password manager that had a password generation part to it, I moved it to a windowed Tkinter program for ease of use. I got everything down except for the check box, so at first when the function was called it would give me the error that alphabet had empty length so I set alphabet equal to the list with special characters. After that I tried them with while loops, same result. (this whole code is a function inside the program that only gets ran when a button is pressed) I know I could probably fix this issue with the init but I was hoping if anyone knew an easier way without rewriting too much. Here is the edit to make the code simplified. I used it with a while loop, and got the same result as the if statement. I get the error that a is not defined in this situation.
from tkinter import *
import random
def cbox_var():
while cbox_1 == True:
a = 10
while cbox_1 == False:
a = 20
print(a)
main = Tk()
cbox_1 = Checkbutton(main, text="yes or no")
cbox_1.pack()
testbutton = Button(main,text="Test", command=cbox_var)
testbutton.pack()
main.mainloop()
To get the value of a checkbutton you must assign one of the special tkinter variables to it. You can then get the value by calling the get method on the variable.
Example:
import tkinter as tk
def cbox_var():
checked = cbox_variable.get()
print("Checked?", checked)
main = tk.Tk()
cbox_variable = tk.BooleanVar()
cbox_1 = tk.Checkbutton(main, variable=cbox_variable, text="yes or no")
cbox_1.pack()
testbutton = tk.Button(main,text="Test", command=cbox_var)
testbutton.pack()
main.mainloop()

Python StringVar().get() in Tkinter returns a blank value

The StringVar.get() method returns a blank value when the function c() is called. However, it works perfectly fine when I call only the new_db () function.
I really cannot understand the problem. Could somebody explain it to me?
#modules
import os
from Tkinter import *
chance=3
def cr():
print data.get()
#new_db
def new_db():
global data
m.destroy()
new=Tk()
data=StringVar()
Entry(new,font='BRITANIC 16',textvariable=data).grid(column=1,row=2)
Button(new,text='Create New Database',command=cr).place(x=175,y=75)
new.geometry('500x100+400+250')
new.mainloop()
def c():
global m
m=Tk()
Button(m,text='erferf',command=new_db).pack()
m.mainloop()
c()
Look at this answer When do I need to call mainloop in a Tkinter application?. It tells that the mainloop() must be called once and only once.
Also, the Tk object m should still exist when new_db() is executed on the click of the Button.
For what you try to accomplish, you should create the Tk() only once, and call mainloop() only once. Then you shoud place code to hide/show the appropriate widgets. Look at In Tkinter is there any way to make a widget not visible? to know how to show/hide widgets.

Tkinter: Grab content of a ScrolledText text pad

all. I'm working on a simple Notepad-like program that saves files and closes the program when the escape key is pressed. I mention this because it is in this method that the program runs into problems. textpad is a ScrolledText object.
This line:
`contents = self.textPad.get(self, 1.0, END)`
results in the following error:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1535, in __call__
return self.func(*args)
File "todopad.py", line 24, in save_and_quit
contents = self.textPad.get(self, 1.0, END)
AttributeError: Event instance has no attribute 'textPad'
I know this is the problem, because the program executes and terminates without issue when this line is commented out. Although I don't understand the error at all.
This has been a very long-winded way of asking: How can I retrieve the contents of a ScrolledText text pad and save it to a variable or directly write it to a file? And also an explanation about the error message?
Thank you in advance.
EDIT: As requested, here is the code for the entire thing.
import sys
import Tkinter
from Tkinter import *
from ScrolledText import *
root = Tkinter.Tk(className = "TodoPad");
textPad = ScrolledText(root, width = 80, height = 20)
def start_and_open():
textFile = open('/home/colin/documents/prog/py/todopad/todo', 'r')
contents = textFile.read()
textPad.insert('1.0', contents)
textFile.close()
def save_and_quit(self):
textFile = open('/home/colin/documents/prog/py/todopad/todo', 'w')
#contents = self.textPad.get(self, 1.0, END) # The line in question
#textFile.write(contents)
textFile.close()
root.destroy()
textPad.pack()
root.bind('<Escape>', save_and_quit)
root.after(1, start_and_open)
root.mainloop()
Since I have posted the whole thing I may as well explain the rationale behind everything. It's supposed to be a fast little thing that opens a to-do list and displays what's already on the list in the text box. I make whatever edits I like, then it saves before closing when I hit escape, problem being is that it doesn't like closing because of the line that I mentioned previously in my post.
First of all, kudos on identifying the problem.
Placing the Widget
To answer what is going wrong: you need to actually place the widget into the window frame. You have a choice between .grid() and .pack(). The first allows you to pick exactly where you want it to go, the second puts in a (technically) default location.
Right now, the instance of your widget is not preset, so your program has no idea where to pull the value from. You have to set a location. i would recommend using .grid(), but for the example .pack() will work as well.
textPad = ScrolledText(root, width = 80, height = 20)
textPad.pack()
Try this, and see if it works. This should fix it, but I could be wrong.
Do NOT just do
textPad = ScrolledText(root, width = 80, height = 20).pack()
The pack() function returns a NULL and will nullify your widget.
Your Issue With Self
Finally, why are you using self at all? You are not using any classes--you need to globalize the variable. The error that is thrown is a result of your program not knowing what class you are pulling the self instance from. Remove the self variables from the program, and put this into the function:
global textPad
This will make it global and all functions will be able to use it.
This should solve all the problems you have right now. However, give it a try and report what happens.
Here are some resources on global variables, getting input from widgets, and saving to files;
http://www.python-course.eu/python3_global_vs_local_variables.php
http://effbot.org/tkinterbook/text.htm
http://www.afterhoursprogramming.com/tutorial/Python/Writing-to-Files/
Happy coding, and best of luck!!

Categories

Resources