I have just started to create a simple text editor. I have already bound a couple of functions to certain keypresses and now I'm trying to add a function that operates on the Return delete being pressed. The aim is to remove the last character entered into the text widget. Here is my code:
from tkinter import *
from tkinter import filedialog
import os
root = Tk()
root.geometry('{}x{}'.format(500, 500))
def addchar(event):
w.insert(END, event.char)
def deletechar(event):
current = w.get()
new = current[:-1]
w.delete(0,END)
w.insert(END, new)
def savefile(event):
file = filedialog.asksaveasfilename(defaultextension=".txt")
if file is None:
return
text2save = str(w.get())
file.append(data)
file.close()
w = Entry(root, bd=1)
w.pack()
w.place(x=0, y=0, width=500)
root.bind("<Key>", addchar)
root.bind("<BackSpace>", deletechar)
root.bind("<Control-s>", savefile)
root.bind("<Return>", newline)
root.mainloop()
The issue I'm having is that nothing is removed upon pressing delete to remove the last character entered. Any help appreciated. P.S. Ive tried adding a savefile function to save the text to a file but it doesn't work if anyone can help there also, it would again be appreciated :)
I didn't try to run your code right know because I'm running out of time. However, first of all, you should not use pack and place geometry manager in the same Toplevel, you should only use one. Second, in your savefile function, you did not open the file, so your file variable is only a string. You should use something like file = open(file).
Related
I am trying to implement a text widget in tkinter which will allow input text for only a specified time (here 5 secs) and then capture the typed text, without using a submit button calling a function.
I want the time to start as soon as user starts typing and shall prevent user inputting any longer after 5secs. The text that was inputted thus far shall be catured.
I tried the below code which is not working. I tried looking in the documentation and did web search and many stackoverflow discussion threads. I couldn't find an answer. Appreciate inputs on a solution.
from tkinter import *
my_window = Tk()
type_txt = Text()
type_txt.grid(row=0, column=0)
type_txt.focus()
type_txt.after(5000, type_txt.configure(state=DISABLED))
typed_text = type_txt.get("1.0", END)
print(typed_text)
my_window.mainloop()
You can bind <key> event to a function, then inside the callback to disable the text box 5 seconds later using .after().
from tkinter import *
my_window = Tk()
type_txt = Text()
type_txt.grid(row=0, column=0)
type_txt.focus()
def disable_textbox():
type_txt.configure(state=DISABLED)
typed_text = type_txt.get("1.0", END)
print(typed_text)
def start_typing(event):
# disable <Key> binding
type_txt.unbind('<Key>')
# disable text box 5 seconds later
type_txt.after(5000, disable_textbox)
type_txt.bind('<Key>', start_typing)
my_window.mainloop()
l am doing practice with Tkinter and its feature. l have been working on "filedialog". I have no problem with select the file. But, l would like to select an image and open on Tkinter. However, it keep giving error when l click on open the image.
When Printed out the path of file, io.TextIOWrapper name='D:/GIS/Python_Pro/Tkinter_lib/my_image/nature_1.jpg' mode='r' encoding='cp1254. How can l get only path as `'D:/GIS/Python_Pro/Tkinter_lib/my_image/nature_1.jpg'.
def Select_File():
root.filename =filedialog.askopenfile(initialdir='D:\GIS\Python_Pro\Tkinter_lib\my_image',title="Select a file",filetypes=(("png files","*.png"),("ico files","*.ico"),("All Files","*.*")))
path_file=Label(root,text=root.filename ).pack()
my_img=ImageTk.PhotoImage(Image.open(root.filename))
img_label=Label(root,image=my_img).pack()
#Buttons
Btn_1=Button(root,text="Select a file",command=Select_File).pack()
The function filedialog.askopenfile will return a IO object.You can use this when you need to revise this file.
If you just need to get the full path,use filedialog.askopenfilename,and it will return the file path you select.
try filedialog.askopenfilename instead of filedialog.askopenfile
I am making a text editor it has all the features but not an auto-indent feature which can automatically add spaces after loops or conditions. Please tell me how can I make, and please try to give a code which can do it. I am making this in Tkinter and want this function in the text widget. I had made this text editor.
I made this in Tkinter so please help me to give a code for auto-indent. I had tried for firing events whenever a user presses ':' button to give an indent in the next line but it does not follow the pattern of multilevel indenting. like
for i in range(100):
if i==5:
break
else:
print('got till '+str(i))
but my code does not follow like this it only adds space in the first line so the code looks like.
for i in range(100):
if i==5:
break
else:
print('got till '+str(i))
so it is a bit tricky. Please comment for any related info or question but please answer me.
You just need to get the indentation from the current line and add the new level of indentation.
Here's a complete working example:
import tkinter as tk
import re
root = tk.Tk()
text = tk.Text(root)
text.pack(fill="both", expand=True)
def autoindent(event):
# the text widget that received the event
widget = event.widget
# get current line
line = widget.get("insert linestart", "insert lineend")
# compute the indentation of the current line
match = re.match(r'^(\s+)', line)
current_indent = len(match.group(0)) if match else 0
# compute the new indentation
new_indent = current_indent + 4
# insert the character that triggered the event,
# a newline, and then new indentation
widget.insert("insert", event.char + "\n" + " "*new_indent)
# return 'break' to prevent the default behavior
return "break"
text.bind(":", autoindent)
root.mainloop()
In the code mentioned I am trying to get value of "text" which is inside the function . Outside of a function with one variable "A" but here I am not getting anything.Can anyone help me on this issue please
Also when I am writing print statement inside the function it is printing the value
enter code here
from tkinter import *
window = Tk()
window.geometry('500x500')
def callback(self):
text = No_of_chances.get()
return text
No_of_chances = Entry(window)
No_of_chances.place(x=50, y=300)
No_of_chances.bind('<Return>', callback)
A=text
print(A)
window.mainloop()
The text variable is not defined when you try to do A=text this is because the function callback() is only called when the enter button is pressed. Therefore text does not exist when you try to assign it to A
The callback function works perfectly fine, it gets the current string within the Number_of_chances Entry you have, and returns it.
That being said your question is very unclear, since you provide no context to what you want to do with the text you get from the Entry when you press enter, if you provide some context I or someone else might be able to help fix your problem better.
Here is a solution so then A will contain the value you want.
from tkinter import *
window = Tk()
window.geometry('500x500')
text = ""
def callback(event):
text = No_of_chances.get()
print(text)
return text
No_of_chances = Entry(window)
No_of_chances.place(x=50, y=300)
No_of_chances.bind('<Return>', callback)
A=text
print(A)
window.mainloop()
I am having some issues wrapping my head around something I encountered in python recently.
So, basically, I want to allow for a user to load several json files, all listed in a python list. These files contain parameters used to create buttons with, namely, the color the button should have, the text that should be displayed in it and the command that it needs to execute once clicked.
def createTags(self):
for items in self.LoadedInstallProfiles:
with open(items, "r") as jsonfiles:
self.loadeddata = json.load(jsonfiles)
self.tag = Button(self.tagmenu, text=self.loadeddata.get("profilename"), background=
self.loadeddata.get("profilecolor"), command=print(self.loadeddata.get("profilename")))
self.tag.pack(side="top",fill="x")
The problem is: the buttons show up with their individual color and text, but all seem to print out the same profilename when clicked, which is that in the last json file in the list.
I common way is to store the created button widgets in a list. I have modified your method. See below.
def createTags(self):
# First create the widget and append to list variable
self.tags = [] #List to store button widgets
for items in self.LoadedInstallProfiles:
with open(items, "r") as jsonfiles:
loadeddata = json.load(jsonfiles)
text = loadeddata.get("profilename")
bg = loadeddata.get("profilecolor")
tag = Button( self.tagmenu, text=text, background=bg, command=print(text) )
self.tag.append( tag )
# Then display the widgets
for tag in self.tags:
tag.pack(side="top",fill="x")
I imagine the problem with command=print(self.loadeddata.get("profilename")) is similar to the problem with lambda statements (that said I am surprised your buttons work at all They should print once at init and then never work after that because you are calling print at button creation instead of saving a reference to print).
Due to the nature of how lambda works here in a loop like this you end up only printing the last value in the loop for all commands. Instead you need to use a lambda statement and also define the value in the lambda for each loop to accurately record the correct data for the print statement.\
I created 3 test files for this:
test.json:
{"profilename":"test", "profilecolor": "green"}
test2.json:
{"profilename":"test2", "profilecolor": "blue"}
test3.json:
{"profilename":"test3", "profilecolor": "orange"}
Example code:
import tkinter as tk
import json
class Window(tk.Tk):
def __init__(self):
super().__init__()
self.btn_list = []
for file in ['test.json', 'test2.json', 'test3.json']:
with open(file, 'r') as f:
self.btn_list.append(json.load(f))
self.create_tags()
def create_tags(self):
for item in self.btn_list:
tk.Button(self, text=item.get("profilename"), background=item.get("profilecolor"),
command=lambda x=item.get("profilename"): print(x)).pack(side="top", fill="x")
if __name__ == '__main__':
Window().mainloop()
Results: