I'm new to Tkinter, and also new to this forum. I am trying to learn to use Tkinter, and I have a problem!
I want to save some text to a text file by writing the text and then press a button to run a function that saves the info. But it seems like my "command" does not start the function.
def ny_artikel():
artikel_data = open ("artikel_databas.txt", "w")
artikel_data.write(ny_artikel.get())
artikel_data.close ()
spara_artikel = Button(new_product_window, text ="Save new article", command = ny_artikel)
spara_artikel.grid(row=7, column=1)
ny_artikel is an entry box used in my program, but I think it's too many rows to paste it all in here.
When I press the button, nothing at all happens. Not even an error message.
I assume, that the code in your answer is only part of your python file. I tried it out with Entry e in my example and it works right:
import tkinter
def ny_artikel():
with open('artikel_databas.txt', 'w') as artikel_data:
artikel_data.write(e.get())
main = tkinter.Tk()
e = tkinter.Entry(main)
e.grid(row=0, column=0)
spara_artikel = tkinter.Button(main, text ="Save new article", command = ny_artikel)
spara_artikel.grid(row=1, column=0)
main.mainloop()
As alternative I used 'with' 'as' in ny_artikel() function, which automatically closes the file. Using file.close() works fine as well.
What is the python keyword "with" used for?
Related
I am trying to create a python text editor. What I want to create in my app, is a textbox where the user writes python code, another box where the user will see the terminal output and a button to run the code. After a few days of research, I found out that terminal output can be shown by using the subprocess module. I used it, worked pretty well! I type print("hello world"), it works.
However, only one thing that did not work is when we run something like input("Enter your name: "). The program just crashes when I run it. This is where I got stuck for a long time. I know doing something like that is not easy because the output box is just a text widget. But, I have seen that many apps can do that so the input function might be possible.
The code below is a sample from my project:
from tkinter import *
import subprocess, os
def run():
code = open(f"{os.getcwd()}/test2.py", 'w')
code.write(input_box.get(1.0, END))
code.close()
process = subprocess.Popen("python3 test2.py", stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)
output, error = process.communicate()
output_box.delete(1.0, END)
output_box.insert(END, output)
output_box.insert(END, error)
root = Tk()
input_box = Text(root)
input_box.grid(row=0, column=0)
output_box = Text(root)
output_box.grid(row=0, column=1)
btn = Button(root, text="Run", command=run)
btn.grid(row=1, column=0)
output_box.insert(1.0, "Output:\n")
output_box.bind('<BackSpace>', lambda _: 'break')
root.mainloop()
The program crashes here:
My current approach is to make my own input function hidden in the users code (this line of code does it): code.write(open(f"{os.getcwd()}/input_string.py", 'r').read(), input_box.get(1.0, END))
Here is input_string.py where it uses tkinter.simpledialog.askstring:
from tkinter import simpledialog
def input(prompt):
ipt = simpledialog.askstring('input', prompt)
return ipt
This works but I am open to better solutions here. I hope you understand my question and the effort I put into this.
and first of all, excuse me if I write many mistakes in my text, English is not my first language, thanks in advance. Secondly, I'm new with Python and Tkinter, I have watched a few youtube videos and I'm following some tutorials to do this.
I'm trying to create a software that it is supposed to receive a value that I enter through an Entry after I press a button to generate it, save that value in a variable and generate a new document.txt with the value I introduced.
I have tried changing the line with:
- idcheck=StringVar() to idcheck = str(), but in console it says: AttributeError: 'str'object has no attribute 'get'.
This is the code, I have tried to reduce at maximum the amount of code so you can try to execute and check what's happening.
from tkinter import *
window = Tk()
def funcion():
print("ID: ", idcheck.get()) #To make sure that the value I'm entering is correct
window.title("app")
Label(window, text="ID").grid(padx=10 ,pady=10, row=0, column=0)
idcheck = StringVar() #this is giving me troubles when I do next step (.write says it must be str() not StringVar()
Entry(window, textvariable=idcheck, width=30).grid(padx=5, row=0, column=1, sticky=E+W)
Button(window, text="Generate", width=30, command=funcion).grid(padx=10,pady=10,row=2,column=0,columnspan=2,sticky=E+W)
idchecklist = open("document.txt","w")
idchecklist.write(idcheck.get())
idchecklist.close()
window.mainloop()
I expect to get the value I'm introducing in the Entry in a new document but the actual output is creating a document.txt but it is empty (I don't know how to get this value).
What else could I try? Thanks.
The logic to write to a file is outside the function. When you execute the python program it creates the file document.txt even before user clicks on Generate button and idecheck is empty at that point which is why the file is empty. You could move this logic when user clicks on Generate button as below
def funcion():
print("ID: ", idcheck.get()) # To make sure that the value I'm entering is correct
idchecklist = open("document.txt", "w")
idchecklist.write(idcheck.get())
idchecklist.close()
I've written a script using tkinker in python. When I run the script, it receives an input and print that to the console. It is working great.
What I wish to do is add any functionality to my existing script in such a way so that after filling in the inputbox when I press the get button, it will print the value in the console and quits automatically. Once again, my existing script is capable of printing values. I need to make that button quit as soon as the printing is done. Any help on this will be highly appreciated.
Here is what I've tried so far:
from tkinter import *
master = Tk()
e = Entry(master)
e.pack()
e.focus_set()
callback = lambda : get_val(e.get())
get_val = lambda item: print(item) #this extra function is for further usage
Button(master, text="get", width=10, command=callback).pack()
master.mainloop()
This is how the inputbox looks like:
Modify the callback function as:
def callback():
get_val(e.get()) #Gets your stuff done
master.destroy() #Breaks the TK() main loop
exit() #Exits the python console
Here,master.destroy() breaks the master.mainloop() loop and thus terminates the GUI and finally exit() makes it exit the python console.
Maintaining your lambda syntax:
callback = lambda : (print(e.get()), master.destroy())
The key is to call master.destroy().
I wrote a python 3.4.2 programme to get a user input from python IDLE, perform some processing on the input and display a few statements in the python IDLE using print().
Now I am in the process of converting this to use a GUI using tkinter. This is the simple tkinter code I wrote for the GUI.
from tkinter import *
root=Tk()
root.title("Post-fix solver")
root.geometry("500x500")
mainframe=Frame(root)
mainframe.grid(column=0, row=0)
inputval=StringVar()
inputentry=Entry(mainframe,textvariable=inputval).grid(column=1,row=1)
executebutton=Button(mainframe,text="Run",command=check_expression).grid(column=1,row=5)
outputtext=Text(mainframe).grid(column=1,row=5)
root.mainloop()
So far I was able to get the user input through the Entry widget named inputentry in the GUI and send it to a variable in the original code using inputval.get(). Then it performs the processing on the input and shows the outputs of print() statement in the python IDLE.
My question is how can I modify the programme to send all those print() statements to the Text widget named outputtext and display them in the GUI?
I would be glad if you could show me how to do this without using classes as I am a beginner in python
3 easy steps:
1) Get the content of your variable and put it to a variable that I'm gonna name varContent;
2) Clear your text widget, that is, if the name of your text widget is text, then run text.delete(0, END);
3) Insert the string you've got in your variable varContent into your text text widget, that is, do text.insert(END, varContent).
I would do my code like this:
from tkinter import *
def check_expression():
#Your code that checks the expression
varContent = inputentry.get() # get what's written in the inputentry entry widget
outputtext.delete('0', 'end-1c') # clear the outputtext text widget
outputtext.insert(varContent)
root = Tk()
root.title("Post-fix solver")
root.geometry("500x500")
mainframe = Frame(root)
mainframe.grid(column=0, row=0)
inputentry = Entry(mainframe)
inputentry.grid(column=1, row=1)
executebutton = Button(mainframe, text="Run", command=check_expression)
executebutton.grid(column=1, row=5)
outputtext = Text(mainframe)
outputtext.grid(column=1, row=5)
root.mainloop()
For Python 3.x
After creating the entry box with inputentry=Entry(mainframe).grid() you can get the typed entries with inputentry.get().
Do the following to put the typed entry in a variable and to print it in the text widget named outputtext:
entryvar=inputentry.get() # the variable entryvar contains the text widget content
outputtext.delete(1.0,tk.END) # clear the outputtext text widget. 1.0 and tk.END are neccessary. tk implies the tkinter module. If you just want to add text dont incude that line
outputtext.insert(tk.END,entryvar) # insert the entry widget contents in the text widget. tk.END is necessary.
If you're using Python 3.4+ to run the program too, you can use the contextlib.redirect_stdout to capture the print output for a duration of a few statements into a file, or even a string:
import io
from contextlib import redirect_stdout
...
file = io.StringIO()
with redirect_stdout(file):
# here be all the commands whose print output
# we want to capture.
output = file.getvalue()
# output is a `str` whose contents is everything that was
# printed within the above with block.
Otherwise a better though a bit more arduous way is to make a StringIO file and print to it, so you'd have
buffer = io.StringIO()
print("something", file=buffer)
print("something more", file=buffer)
output = buffer.getvalue()
text.insert(END, output)
I went here: http://effbot.org/zone/vroom.htm
And tried this out:
filename = raw_input("Filename?")
editor = Text()
editor.pack(fill=Y, expand=1)
editor.config(font="Courier 12")
editor.focus_set()
mainloop()
#save
f = open(filename, "w")
text = str(editor.get(0.0,END))
try:
f.write(text.rstrip())
f.write("\n")
However, I was given an error:
TclError: invalid command name ".40632072L"
How can i fix this problem?
I'm not comfortable with object-oriented programming, so I would prefer an imperative solution (without any class keywords).
The problem is that, after the mainloop finishes, all of your widgets, including editor, get destroyed, so you can't call editor.get.
What you want to do is add some code that stashes the value of editor in a plain old string while the main loop is running, and then use that variable. For example:
text=''
def stash(*args):
global text
text = str(editor.get(0.0,END))
editor.bind_all('<<Modified>>', stash)
Or, of course, do the simpler thing: write the file from within the GUI instead of after the GUI has exited. If you go look farther down the same page, you'll see how they do that.