How can I pop up a messagebox from a menu? - python

I am a newbie in Python. I want to create a program with Tkinter that takes the entry from the entry "box" and then compares each character of it with the charset and finally pops up a messagebox that shows the phrase. I have almost complete it but I can not make this line work:
info_menu.add_command(label="About",
command=messagebox.showwarning(message="Creator: GakPower\nVersion: 1.0.0\nCreated at 1/5/2017")
Full code:
from tkinter import ttk
from tkinter import *
from tkinter import messagebox
import string as s
class Bruteforcer:
def output(self, result):
self.result = result
if result == "":
messagebox.showwarning(title="Enter a Phrase",
message="Please enter a Phrase!")
else:
messagebox.showinfo(title="Phrase Found!",
message=("The process completed Successfully!\n The Phrase Found!!!!\n", result))
def submit_button_pressed(self):
entry_val = self.entry_value.get()
charset = list(s.ascii_letters + "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω" + s.digits + s.punctuation)
result = ""
x = 0
while x <= len(entry_val)-1:
echar = entry_val[x]
for char in charset:
if char == echar:
result += echar
x += 1
break
return self.output(result)
def __init__(self, root):
self.entry_value = StringVar(root, "")
self.the_menu = Menu(root)
info_menu = Menu(self.the_menu, tearoff=0)
**info_menu.add_command(label="About",
command=messagebox.showwarning(message="Creator: GakPower\nVersion: 1.0.0\nCreated at 1/5/2017")**
)
info_menu.add_separator()
info_menu.add_command(label="Quit", command=root.quit)
self.the_menu.add_cascade(label="Info", menu=info_menu)
root.config(menu=self.the_menu)
text_fond = StringVar()
text_fond.set("Times")
root.title("Graphical Bruteforcer")
root.geometry("500x500")
root.resizable(width=False, height=False)
style = ttk.Style()
style.configure("TButton",
foreground="red",
fond="Times 20",
padding=10)
style.configure("TEntry",
foreground="red",
fond="Times 20",
padding=10)
style.configure("TLabel",
foreground="red",
fond="Times 35 Bold")
# ---------- Entry -----------
self.entry_value = ttk.Entry(root,
textvariable=self.entry_value, width=25, state="normal")
self.entry_value.grid(row=1, columnspan=2)
# ---------- Label ----------
self.secret_label = ttk.Label(root,
text="The Secret Phrase").grid(row=0, column=0)
# ---------- Button ---------
self.button_submit = ttk.Button(root,
text="Submit", command=self.submit_button_pressed)
self.button_submit.grid(row=1, column=2)
root = Tk()
brute = Bruteforcer(root)
root.mainloop()

As furas said in the comments, command= expects a function. So you should replace
info_menu.add_command(label="About",
command=messagebox.showwarning(message="Creator: GakPower\nVersion: 1.0.0\nCreated at 1/5/2017"))
by something like
def show_about():
''' show the about messagebox '''
messagebox.showwarning(message="Creator: GakPower\nVersion: 1.0.0\nCreated at 1/5/2017")
info_menu.add_command(label="About", command=show_about)

Related

Modules and classes in Python for a desktop application

This is to be a desktop application for opening multiple small databases and running queries on them. So far I've written some code for opening forms as necessary. Is this a good way to do it? Also - the code shown opens two copies of each form - what am I doing wrong? It's my first attempt at Python and I'm a rudimentary programmer so simple answers would be of most help please. TIA (Python 3.9.6)
link_1.py
from tkinter import Tk
import link_2
root = Tk()
class ClassLink_1:
#if another function in the class is called, the __init__ function is run at start up
def __init__(self):
print("in link_1 __init__ instruction")
#the call_function function can be called at start up, or not, and will act accordingly
def call_function(self):
print("in call_function")
#the line below is run at start up whether or not another function in the class is called
print("in link_1")
root.withdraw() #hides the blank form at start up
#if __name__ == "__main__":
#the line below shows the link_2 form, whether or not the if __name__==__main__ condition is used as its condition
link_2.ClassLink_2(root).__init__(root)
#link_3.ClassLink_3(root).__init__(root)
#the line below runs call_function on start up to print text
ClassLink_1().call_function()
root.mainloop()
link_2.py
from tkinter import Tk, Button
from tkinter import * #for Toplevel
import link_3
root = Tk()
class ClassLink_2:
def __init__(self, master):
self.openNewWindow()
def openNewWindow(self):
newWindow = Toplevel(root) #creates a top level widget with the parent root (first parameter)
newWindow.title("Title opened from link_1")
newWindow.geometry("500x500")
label = Label(newWindow, text ="Opened from link_1").grid(row=1, column=1)
self.add_button = Button(newWindow, text="in ClassLink_2", command= self.do_add)
self.add_button.grid(row=3, column=1)
def do_add(self):
print("button pressed")
link_3.ClassLink_3(root).__init__(root)
root.withdraw() #hides the blank form at start up
link_3.py
from tkinter import Tk, Button
from tkinter import * #for Toplevel
root = Tk()
class ClassLink_3:
def __init__(self, master):
self.openNewWindow()
def openNewWindow(self):
newWindow = Toplevel(root) #creates a top level widget with the parent root (first parameter)
newWindow.title("Title opened from link_2")
newWindow.geometry("500x500")
label = Label(newWindow, text ="Opened from link_2").grid(row=1, column=1)
self.add_button = Button(newWindow, text="in ClassLink_3", command= self.do_add)
self.add_button.grid(row=3, column=1)
def do_add(self):
print("button pressed")
# link_4.ClassLink_4(root).__init__(root) this file has not yet been made
root.withdraw() #hides the blank form at start up
This is a proposed solution, can be expanded as needed. Constructive suggestions for improvement of the structure or code would be appreciated. TIA. I've left in the details in case they are of use to anyone.
link_1
from tkinter import Tk
import link_2
root = Tk()
class ClassLink_1:
def __init__(self):
print("in link_1 __init__ instruction")
root.withdraw() #hides the blank form at start up
link_2.ClassLink_2(root).openNewWindow(0)
root.mainloop()
link_2
from tkinter import Tk, Button
from tkinter import *
import link_3
root = Tk()
class ClassLink_2:
root.withdraw() #hides the blank form at start up
class_var_1 = 0
inst_var_1 = 0
def __init__(self, incoming_inst_var_1):
pass
def openNewWindow(self, inst_var_1_to_open):
newWindow = Toplevel(root)
newWindow.title("Title opened from link_1")
newWindow.geometry("500x500")
label = Label(newWindow, text ="Opened from link_1").grid(row=1, column=1)
self.add_button = Button(newWindow, text="in ClassLink_2", command= self.do_add)
self.add_button.grid(row=3, column=1)
self.add_button = Button(newWindow, text="increment class_var_1", command= self.inc_class_var_1)
self.add_button.grid(row=5, column=1)
self.inst_var_1 = inst_var_1_to_open
def do_add(self):
print("button pressed")
link_3.ClassLink_3(root).openNewWindow(0)
def inc_class_var_1(self):
ClassLink_2.class_var_1 += 2
self.inst_var_1 += 1
print("self.class_var_1 = " + (str)(self.class_var_1))
print("self.inst_var_1 = " + (str)(self.inst_var_1))
link_3
from tkinter import Tk, Button
from tkinter import *
from tkinter.ttk import Combobox
import tkinter.scrolledtext as tkscrolled
# import link_4 <filename of next form>
root = Tk()
class ClassLink_3:
class_var_1 = 0
inst_var_1 = 0
# ------------------------------- START CLASS CONTROLS -----------------------------
root.withdraw()
def __init__(self, incoming_inst_var_1):
pass
def openNewWindow(self, inst_var_1_to_open):
new_window = Toplevel(root)
self.widget_factory(new_window)
self.inst_var_1 = inst_var_1_to_open
def do_add(self):
print("button pressed")
# link_4.ClassLink_4(root).openNewWindow(0) # <filename of next form>
# ---------------------------------- END CLASS CONTROLS -----------------------------
# -------------------------------------- START CALCS --------------------------------------
def inc_class_var_1(self):
ClassLink_3.class_var_1 += 2
self.inst_var_1 += 1
print("self.class_var_1 = " + (str)(self.class_var_1))
print("self.inst_var_1 = " + (str)(self.inst_var_1))
# ---------------------------------------- END CALCS --------------------------------------
# ---------------------------------------- START FACTORY SHOPS-----------------------------------------
def widget_factory(self, new_window):
self.shop_window(new_window)
self.shop_labels(new_window)
self.shop_buttons(new_window)
self.shop_menu(new_window)
self.shop_listbox(new_window)
self.shop_combobox(new_window)
self.shop_radiobuttons(new_window)
self.shop_checkbuttons(new_window)
self.shop_entries(new_window)
self.shop_canvas(new_window)
self.shop_scale(new_window)
self.shop_scrollbars(new_window)
self.shop_textbox(new_window)
self.shop_menu(new_window)
pass
# ------------------------
def shop_window(self, new_window):
new_window.title("Title opened from link_2")
new_window.geometry("800x900")
def shop_labels(self, new_window):
self.label_1 = Label(new_window, text ="Opened from link_2").grid(row=1, column=1)
def shop_buttons(self, new_window):
self.button_1 = Button(new_window, text="in ClassLink_3", command= self.do_add)
self.button_1.grid(row=3, column=1)
self.button_2 = Button(new_window, text="increment class_var_1", command= self.inc_class_var_1)
self.button_2.grid(row=5, column=1)
def shop_listbox(self, new_window):
data=("one", "two", "three", "four")
self.listbox_1 = Listbox(new_window, height=5, selectmode='multiple')
for num in data:
self.listbox_1.insert(END,num)
self.listbox_1.grid(row=7, column=1)
def shop_combobox(self, new_window):
data=("one", "two", "three", "four")
self.combobox_1 = Combobox(new_window, values=data)
self.combobox_1.grid(row=8, column=3)
def shop_radiobuttons(self, new_window):
var_1 = IntVar()
var_1.set(1)
self.rad_btn_1 = Radiobutton(new_window, text="male", variable=var_1, value=1)
self.rad_btn_2 = Radiobutton(new_window, text="female", variable=var_1, value=2)
self.rad_btn_1.grid(row=9, column=1)
self.rad_btn_2.grid(row=9, column=2)
def shop_checkbuttons(self, new_window):
var_1 = IntVar()
var_2 = IntVar()
self.checkbtn_1 = Checkbutton(new_window, text = "Cricket", variable = var_1)
self.checkbtn_2 = Checkbutton(new_window, text = "Tennis", variable = var_2)
self.checkbtn_1.grid(row=10, column=1)
self.checkbtn_2.grid(row=10, column=2)
def shop_entries(self, new_window):
self.entry_1 = Entry(new_window, width = 20)
self.entry_1.insert(0,'Username')
self.entry_1.grid(row= 11, column=2)
self.entry_2 = Entry(new_window, width = 15)
self.entry_2.insert(0,'password')
self.entry_2.grid(row= 12, column=2)
#might want to place on a frame, see example https://coderslegacy.com/python/list-of-tkinter-widgets/
def shop_canvas(self, new_window):
canvas = Canvas(new_window, bg= 'white', width = 260,height = 260) #this is the background for the figure
# left and top of figure is from [x from left, y from top] of canvas right and bottom of figure from [x from left, y from top] of canvas
coordinates = 20, 50, 210, 230
arc = canvas.create_arc(coordinates, start=0, extent=250, fill="blue") #start is from E, extent is in degrees CCW
arc = canvas.create_arc(coordinates, start=250, extent=50, fill="red")
arc = canvas.create_arc(coordinates, start=300, extent=60, fill="yellow")
canvas.grid(row=2, column=1)
def shop_scale(self, new_window):
self.scale_1 = Scale(new_window, from_=0, to=10, orient=VERTICAL)
self.scale_1.grid(row=15, column=2)
self.scale_2 = Scale(new_window, from_=0, to=10, orient = HORIZONTAL)
self.scale_2.grid(row=15, column=3)
def shop_scrollbars(self, new_window):
self.scroll_vert = Scrollbar(new_window)
self.scroll_vert.grid(row=19, column=3)
self.listbox_3 = Listbox(new_window, yscrollcommand = self.scroll_vert.set )
for line in range(1, 100):
self.listbox_3.insert(END, "Number " + str(line))
self.listbox_3.grid(row=19 , column=2)
self.scroll_vert.config(command = self.listbox_3.yview)
def shop_textbox(self, new_window):
#make a frame with parent new_window
self.frame_textbox_1 = Frame(new_window)
self.frame_textbox_1.grid(row=1, column=5)
#make the textbox with parent frame
self.textbox_1 = Text(self.frame_textbox_1)
self.textbox_1.config(wrap=NONE, width=15, height=8) #width, height are characters x rows permitted wrap values should be WORD CHAR, or NONE
#make the X scrollbar with parent frame
self.scroll_text_horiz = Scrollbar(self.frame_textbox_1, orient="horizontal")
self.scroll_text_horiz.config(command = self.textbox_1.xview)
#make the Y scrollbar with parent frame
self.scroll_text_vert = Scrollbar(self.frame_textbox_1, orient="vertical")
self.scroll_text_vert.config(command = self.textbox_1.yview)
#pack the scrollbars before the texbox to allow them to fill the frame width and height
self.scroll_text_horiz.pack(side=BOTTOM, fill=X)
self.scroll_text_vert.pack(side=RIGHT, fill=Y)
self.textbox_1.pack(fill="y")
#connect the scrollbars to the textbox
self.textbox_1["xscrollcommand"] = self.scroll_text_horiz.set
self.textbox_1["yscrollcommand"] = self.scroll_text_vert.set
message = "the quick brown fox"
self.textbox_1.insert(1.1, message)
# ----------------------------------------------
def shop_menu(self, new_window):
print("in shop menu1")
menubar = Menu(new_window)
print("in shop_menu2")
file = Menu(menubar, tearoff=0)
file.add_command(label="New")
file.add_command(label="Open")
file.add_command(label="Save")
file.add_command(label="Save as...")
file.add_command(label="Close")
file.add_separator()
file.add_command(label="Exit", command=new_window.quit)
menubar.add_cascade(label="File", menu=file)
edit = Menu(menubar, tearoff=0)
edit.add_command(label="Undo")
edit.add_separator()
edit.add_command(label="Cut")
edit.add_command(label="Copy")
edit.add_command(label="Paste")
edit.add_command(label="Delete")
edit.add_command(label="Select All")
menubar.add_cascade(label="Edit", menu=edit)
help = Menu(menubar, tearoff=0)
help.add_command(label="About")
menubar.add_cascade(label="Help", menu=help)
new_window.config(menu=menubar)
print("in shop menu3")
# --------------------------------------- END FACTORY SHOPS---------------------------------------

Python tkinter cannot print in same line?

So I am currently writing a program using python Tkinter where I enter details and it will enter each task on the same line. I left a photo of what I have done down below. I would like to have all of them print out on the same line.
I would like to have both 2s and the three buttons in the same line.
Here's my code
# This Python file uses the following encoding: utf-8
import os, sys
import tkinter as tk
from tkinter import *
from tkinter import ttk
import tkinter.font
import tkinter.messagebox
#Set up window
root = tk.Tk()
root.title("SNKRS Bot")
root.geometry("1000x600")
#Enter ID
IDHead = Label(root, text="ID:")
IDHead.grid(row=1, column=0)
IDInput = Entry(root, textvariable="", width='5')
IDInput.grid(row=1, column=1)
#Enter link
linkHead = Label(root, text="Link:")
linkHead.grid(row=2, column=0)
linkInput = Entry(root, textvariable="", width='60')
linkInput.grid(row=2, column=1)
ID = []
linkList = []
def createTask():
#Create variables for inputs
linkInput1 = linkInput.get()
IDInput1 = IDInput.get()
#Append to lists
linkList.append(linkInput1)
ID.append(IDInput1)
#print lists to check
print("ID: " + str(ID))
print("Links: " + str(linkList))
#Clear inputs
IDInput.delete(0, END)
linkInput.delete(0, END)
#Output values
# Label(root, text=(IDInput1 + " | " + linkInput1)).grid(column=0)
Label(root, text=linkInput1).grid(column=0)
Label(root, text=linkInput1).grid(column=1)
#Actions for each task
def startTask():
print("Task started")
def stopTask():
print("Task stopped")
def deleteTask():
print("Task deleted")
#Buttons for actions
startButton = tk.Button(root, text="start", command=startTask).grid(column=2)
stopButton = tk.Button(root, text="stop", command=stopTask).grid(column=3)
deleteButton = tk.Button(root, text="delete", command=deleteTask).grid(column=4)
#Create task
create = tk.Button(root, text="Create task", command=createTask)
create.grid(row=3, column=1)
root.mainloop()
Whenever you are packing a label,in the grid method you are passing only the column.by doing so,it will pack the widget in a new row.
To avoid that pass both the row and column arguments.
Ex:
Label(root,text="some text").grid(row=3,column=0)

How to use class and self here to get two different entries?

With my current code, it does not matter whether I click on "Input Folder" - Change or "JukeBox" change the result always gets displayed in "JukeBox" entry. This is incorrect, using class and self how can I change the code to display result from "Input Folder" - Change in "Input Folder" entry and the result from "Jukbox" - Change in "Jukebox" entry?
Also, how can I save the selected folders to a file so that it is there on app exit and re open?
My code:
import os
from tkinter import *
from tkinter import filedialog
inPut_dir = ''
jukeBox_dir = ''
def inPut():
opendir = filedialog.askdirectory(parent=root,initialdir="/",title='Input Folder')
inPut_dir = StringVar()
inPut_dir = os.path.abspath(opendir)
entry.delete(0, END)
entry.insert(0, inPut_dir)
def jukeBox():
opendir = filedialog.askdirectory(parent=root,initialdir="/",title='JukeBox')
jukeBox_dir = StringVar()
jukeBox_dir = os.path.abspath(opendir)
entry.delete(0, END)
entry.insert(0, jukeBox_dir)
root = Tk()
root.geometry("640x240")
root.title("Settings")
frametop = Frame(root)
framebottom = Frame(root)
frameright = Frame(framebottom)
text = Label(frametop, text="Input Folder").grid(row=5, column=2)
entry = Entry(frametop, width=50, textvariable=inPut_dir)
entry.grid(row=5,column=4,padx=2,pady=2,sticky='we',columnspan=20)
text = Label(frametop, text="JukeBox").grid(row=6, column=2)
entry = Entry(frametop, width=50, textvariable=jukeBox_dir)
entry.grid(row=6,column=4,padx=2,pady=2,sticky='we',columnspan=20)
ButtonA = Button(frametop, text="Change", command=inPut).grid(row=5, column=28)
ButtonB = Button(frametop, text="Change", command=jukeBox).grid(row=6, column=28)
ButtonC = Button(frameright, text="OK").grid(row=5, column=20, padx=10)
ButtonD = Button(frameright, text="Cancel").grid(row=5, column=15)
frametop.pack(side=TOP, fill=BOTH, expand=1)
framebottom.pack(side=BOTTOM, fill=BOTH, expand=1)
frameright.pack(side=RIGHT)
root.mainloop()
See attached image:enter image description here
Your code has both:
entry = Entry(frametop, width=50, textvariable=inPut_dir)
entry.grid(row=5,column=4,padx=2,pady=2,sticky='we',columnspan=20)
and
entry = Entry(frametop, width=50, textvariable=jukeBox_dir)
entry.grid(row=6,column=4,padx=2,pady=2,sticky='we',columnspan=20)
with jukeBox_dir/row 6 overriding inPut_dir/row 5
Therefore, in def input:
where you have:
entry.insert(0, inPut_dir)
You'll get the result in row 5 (jukebox_dir)

How to clear a label using tkinter when pressing a button?

I am using labels to show a generated password in my tkinter password generator program, but when I change the length of a password from a lower value than before (for example from a length of 20 to 10) the label displaying the password appears to be overwritten - it does not clear. I have searched methods to do this, but I cannot seem to find any.
Here is my code:
from tkinter import *
from random import *
import string
root = Tk()
root.wm_title("Password Generator")
topFrame = Frame(root)
topFrame.pack()
bottomFrame = Frame(root)
bottomFrame.pack(side=BOTTOM)
root.geometry("1000x1000")
title = Label(topFrame, text="Length", fg="blue")
title.grid(row=3,column=5)
var = DoubleVar()
Slider_1 = Scale(root,orient=HORIZONTAL,length=32*10,from_=0,to=32, variable
= var)
Slider_1.pack()
passLen = var.get()
uppercaseLetters = "QWERTYUIOPASDFGHJKLZXCVBNM"
lowercaseLetters = "qwertyuiopasdfghjklzxcvbnm"
symbols = "!£$%^&*()_+-=}{][~##':;?>/.<,"
digits = "1234567890"
def gen():
characters = uppercaseLetters + lowercaseLetters + symbols + digits
password = "".join(choice(characters) for x in range(int(var.get())))
passLabel = Label(topFrame, text=password)
passLabel.grid(row=4, column=5)
genButton = Button(topFrame, text="Generate Password", fg="blue",
command=gen)
genButton.grid(row=1, column=5)
root.mainloop()
When I set the length to 32 characters:
And when I set the length to 6 characters it does not clear the old password label - it simply overwrites it in the middle of the old password label:
First of all, move your gen method definition to just below imports so that they're recognized in the main body. Then take your widgets and mainloop out of the method. Just configure passLabel's text when needed:
def gen():
characters = uppercaseLetters + lowercaseLetters + symbols + digits
password = "".join(choice(characters) for x in range(int(var.get())))
passLabel['text'] = password
Entire code with suggested edits been made:
from tkinter import *
from random import *
import string
def gen():
characters = uppercaseLetters + lowercaseLetters + symbols + digits
password = "".join(choice(characters) for x in range(int(var.get())))
passLabel['text'] = password
root = Tk()
root.wm_title("Password Generator")
topFrame = Frame(root)
topFrame.pack()
bottomFrame = Frame(root)
bottomFrame.pack(side=BOTTOM)
root.geometry("1000x1000")
title = Label(topFrame, text="Length", fg="blue")
title.grid(row=3,column=5)
var = DoubleVar()
Slider_1 = Scale(root,orient=HORIZONTAL,length=32*10,from_=0,to=32, variable
= var)
Slider_1.pack()
passLen = var.get()
uppercaseLetters = "QWERTYUIOPASDFGHJKLZXCVBNM"
lowercaseLetters = "qwertyuiopasdfghjklzxcvbnm"
symbols = "!£$%^&*()_+-=}{][~##':;?>/.<,"
digits = "1234567890"
passLabel = Label(topFrame)
passLabel.grid(row=4, column=5)
genButton = Button(topFrame, text="Generate Password", fg="blue",
command=gen)
genButton.grid(row=1, column=5)
root.mainloop()
Change two things:
First:
bottomFrame = Frame(root)
bottomFrame.pack(side=BOTTOM)
passLabel = Label(topFrame)
root.geometry("1000x1000")
Second:
def gen():
characters = uppercaseLetters + lowercaseLetters + symbols + digits
password = "".join(choice(characters) for x in range(int(var.get())))
passLabel.config(text=password)
passLabel.grid(row=4, column=5)
"How to clear a label using tkinter when pressing a button?"
Below is an example that clears label's text when the button is pressed:
try: # In order to be able to import tkinter for
import tkinter as tk # either in python 2 or in python 3
except ImportError:
import Tkinter as tk
def clear_widget_text(widget):
widget['text'] = ""
if __name__ == '__main__':
root = tk.Tk()
label = tk.Label(root, text="This will be cleared.")
button = tk.Button(root, text="Clear",
command=lambda : clear_widget_text(label))
label.pack()
button.pack()
root.mainloop()
Below is an example that destroys label when button is pressed:
try: # In order to be able to import tkinter for
import tkinter as tk # either in python 2 or in python 3
except ImportError:
import Tkinter as tk
def clear_widget(widget):
widget.destroy()
if __name__ == '__main__':
root = tk.Tk()
label = tk.Label(root, text="This will be cleared.")
button = tk.Button(root, text="Clear",
command=lambda : clear_widget(label))
label.pack()
button.pack()
root.mainloop()

How do I get the current length of the Text in a Tkinter Text widget

I am writing a light webtexting application, and I'm trying to display the current number of characters in a TKinter Text widget used for writing the message to be sent in the webtext. The code I have at the moment can be seen below, I'm using python
root = Tk()
msgLabel = Label(text="Message")
msgLabel.grid(row=0, column=0)
msg = Text(width=40, height=4, wrap="word")
msg.grid(row=0, column=1, padx=10, pady=5)
#Try to display number of characters within message to user
charCount = Label(text="Character Count: "+str(len(meg.get("1.0", 'end-1c')))
charCount.grid(row=1, column=1, pady=5, padx=5)
root.mainloop()
I'd like to be able to display the number of characters in the message written by the user, since there is a 160 character limit to each webtext. Is it possible to display the current character length, that updates as text is inserted and removed? Thanks in advance
We use StringVar to set the new text to the label.
We need to bind msg for key pressing.
from Tkinter import *
root = Tk()
def update(event):
var.set(str(len(msg.get("1.0", 'end-1c'))))
msgLabel = Label(text="Message")
msgLabel.grid(row=0, column=0)
msg = Text(width=40, height=4, wrap="word")
msg.grid(row=0, column=1, padx=10, pady=5)
var = StringVar()
#Try to display number of characters within message to user
charCount = Label(textvariable=var)
charCount.grid(row=1, column=1, pady=5, padx=5)
msg.bind("<KeyRelease>", update)
root.mainloop()
In below example, the character count in the text is displayed in the label above at all times.
try:
import tkinter as tk
except:
import Tkinter as tk
def on_every_keyboard_input(event):
update_char_length(text, label)
def update_char_length(text_widget, display_widget):
string_in_text = text_widget.get('1.0', 'end-1c')
string_length = len(string_in_text)
display_widget['text'] = string_length
if __name__ == '__main__':
root = tk.Tk()
text = tk.Text(root)
label = tk.Label(root, text=0, justify='center')
text.bind('<KeyPress>', on_every_keyboard_input)
text.bind('<KeyRelease>', on_every_keyboard_input)
label.pack()
text.pack()
root.mainloop()
Below is a tiny example, in which the character count in the text is displayed in label above at all times.
try:
import tkinter as tk
except:
import Tkinter as tk
if __name__ == '__main__':
def update(event):
label['text'] = len(text.get('1.0', 'end-1c'))
root = tk.Tk()
text = tk.Text(root)
label = tk.Label(root, text=0, justify='center')
text.bind('<KeyPress>', update)
text.bind('<KeyRelease>', update)
label.pack()
text.pack()
root.mainloop()
Below script defines a class, TextWithCharLength, which has a Text and a Label in which the character length of the content in the text is displayed:
try:
import tkinter as tk
except:
import Tkinter as tk
class TextWithCharLength(tk.Frame):
def __init__(self, master, *args, **kwargs):
tk.Frame.__init__(self, master, *args, **kwargs)
self._events = ('<KeyPress>',
'<KeyRelease>',
'<ButtonRelease-1>',
'<ButtonRelease-2>',
'<ButtonRelease-3>',
'<Delete>',
'<<Cut>>',
'<<Paste>>',
'<<Undo>>',
'<<Redo>>')
self._create_widgets()
self._widgets_layout()
self.update_char_len(event=None)
self.bind_events_on_widget_to_callback( self._events,
self.text,
self.update_char_len)
def _create_widgets(self):
self.label = tk.Label(self, justify='center')
self.text = tk.Text(self)
def _widgets_layout(self):
self.label.pack(fill='x', expand=True)
self.text.pack(fill='both', expand=True)
#staticmethod
def bind_events_on_widget_to_callback(events, widget, callback):
""" Bind events on widget to callback.
"""
for _event in events:
widget.bind(_event, callback)
def update_char_len(self, event):
""" Update self.label's text with character length of content
in self.text.
"""
self.label['text'] = len(self.text.get('1.0', 'end-1c'))
if __name__ == '__main__':
root = tk.Tk()
text_frame = TextWithCharLength(root)
text_frame.pack()
root.mainloop()

Categories

Resources