I am new to python, the above figure is two UI, I was trying to insert the two tab from the right side UI into the left side UI. But I had met some error and no idea how to solve.
Now below is the original coding of the left side UI
import tkinter as tkk
from tkinter import *
from tkinter import messagebox
import os.path
import hashlib
import sys
import time
import getpass
from tkinter import filedialog
import platform
import getpass
import os,sys
import tkinter.font as font
from tkinter import ttk
from tkinter import StringVar
import Consts
import shutil
class Page(tkk.Frame):
def __init__(self, *args, **kwargs):
tkk.Frame.__init__(self, *args, **kwargs)
def show(self):
self.lift()
class Page1(Page):
def __init__(self, *args, **kwargs):
Page.__init__(self, *args, **kwargs,bg='white')
my_system=platform.uname()
#computer information
comsys=my_system.system
comnode=my_system.node
comrel=my_system.release
comver=my_system.version
commac=my_system.machine
compro=my_system.processor
comuser=getpass.getuser()
label1 = tkk.Label(self, text="System: "+comsys,bg='white')
label1.grid(row=1,column=1,pady=10,sticky='w')
label2 = tkk.Label(self, text="Computer Name: "+comnode,bg='white')
label2.grid(row=2,column=1,pady=10,sticky='w')
label3 = tkk.Label(self, text="Release: "+comrel,bg='white')
label3.grid(row=3,column=1,pady=10,sticky='w')
label4 = tkk.Label(self, text="Version: "+comver,bg='white')
label4.grid(row=4,column=1,pady=10,sticky='w')
label5 = tkk.Label(self, text="Machine: "+commac,bg='white')
label5.grid(row=5,column=1, pady=10,sticky='w')
label6 = tkk.Label(self, text="Processor: "+compro,bg='white')
label6.grid(row=6,column=1, pady=10,sticky='w')
label7 = tkk.Label(self, text="Username: "+comuser,bg='white')
label7.grid(row=7,column=1,pady=10,sticky='w')
#computer usage hold first, no idea how to do
class Page2(Page):
def __init__(self, *args, **kwargs):
Page.__init__(self, *args, **kwargs,bg='white')
tabControl=ttk.Notebook(self)
qsFrame = ttk.Frame(tabControl)
fsFrame = ttk.Frame(tabControl)
csFrame = ttk.Frame(tabControl)
#tab
tabControl.add(qsFrame, text='Quick Scan')
tabControl.add(fsFrame, text='Full Scan')
tabControl.add(csFrame, text='Custom Scan')
tabControl.pack(expand=1,fill="both")
class Page3(Page):
def __init__(self, *args, **kwargs):
Page.__init__(self, *args, **kwargs,bg='white')
label = tkk.Label(self, text="This is page 3")
label.grid(row=2,column=1)
def mytools():
total, used, free = shutil.disk_usage("/")
print("Total:%d GB" %(total // (2**30)))
print("Used:%d GB" %(used // (2**30)))
print("Free:%d GB" %(free // (2**30)))
if free <= total/2:
clean = os.popen('Cleanmgr.exe/ sagerun:1').read()
#print(clean)
def btn1():
if __name__ =="__main__":
mytools()
button1=ttk.Button(self,text="Clean Up",command=btn1)
button1.grid(row=3,column=2)
class Page4(Page):
def __init__(self, *args, **kwargs):
Page.__init__(self, *args, **kwargs,bg='white')
label = tkk.Label(self, text="This is page 4")
label.grid(row=2,column=1)
class MainView(tkk.Frame):
def __init__(self, *args, **kwargs):
tkk.Frame.__init__(self, *args, **kwargs)
p1 = Page1(self)
p2 = Page2(self)
p3 = Page3(self)
p4 = Page4(self)
buttonframe = tkk.Frame(self)
container = tkk.Frame(self,bg='white')
buttonframe.pack(side="left", fill="x", expand=False)
container.pack(side="left", fill="both", expand=True)
buttonframe.grid_rowconfigure(0,weight=1)
buttonframe.grid_columnconfigure(0,weight=1)
container.grid_rowconfigure(0,weight=1)
container.grid_columnconfigure(0,weight=1)
p1.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
p2.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
p3.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
p4.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
stats_btn = tkk.PhotoImage(file='C:/FYP/SecuCOM2022/icon&pic/stats.png')
scanner_btn = tkk.PhotoImage(file='C:\FYP\SecuCOM2022\icon&pic\scanner.png')
speedup_btn = tkk.PhotoImage(file='C:\FYP\SecuCOM2022\icon&pic\speedup.png')
settings_btn = tkk.PhotoImage(file='C:\FYP\SecuCOM2022\icon&pic\settings.png')
#logo
logo=tkk.PhotoImage(file="C:\FYP\SecuCOM2022\icon&pic\g (1).png")
label=tkk.Label(buttonframe,image=logo)
label.grid(row=0,column=0, padx=10,pady=10)
logo.image = logo
b1 = tkk.Button(buttonframe, image=stats_btn, command=p1.show, borderwidth=0)
b2 = tkk.Button(buttonframe, image=scanner_btn, command=p2.show, borderwidth=0)
b3 = tkk.Button(buttonframe, image=speedup_btn, command=p3.show, borderwidth=0)
b4 = tkk.Button(buttonframe, image=settings_btn, command=p4.show, borderwidth=0)
b1.image = stats_btn
b2.image = scanner_btn
b3.image = speedup_btn
b4.image = settings_btn
b1.grid(row=1,column=0,padx=10,pady=10)
b2.grid(row=2,column=0,padx=10,pady=10)
b3.grid(row=3,column=0,padx=10,pady=10)
b4.grid(row=4,column=0,padx=10,pady=10)
if __name__ == "__main__":
root= Tk()
main = MainView(root)
main.pack(side="top", fill="both", expand=True)
main.grid_rowconfigure(0,weight=1)
main.grid_columnconfigure(0,weight=1)
root.title("SecuCOM2022")
root.geometry("600x300")
root.maxsize(600,375)
root.minsize(600,375)
root.iconbitmap('C:\FYP\SecuCOM2022\icon&pic\g.png')
root.mainloop()
root.mainloop()
#GUI end`
Next below here is the right side UI coding, there are multiple files for it. I just show files related with the UI only.
Consts.py
ENTRY_WIDTH = 50
FileReportTab.py
from tkinter import filedialog
from tkinter import messagebox
from tkinter import ttk
from tkinter import StringVar
import time
import os.path
import sys
from VTPackage import Consts
class FileReportTab:
def __init__(self, root, frame, vtClient):
self.root = root
self.frame = frame
self.vtClient = vtClient
self.mainVTURLframe = ttk.LabelFrame(frame, text=' File report')
self.mainVTURLframe.grid(column=0, row=1, padx=8, pady=4)
ttk.Label(self.mainVTURLframe, text="Progress:").grid(column=0, row=1, sticky='W') # <== right-align
self.progressBar = ttk.Progressbar(self.mainVTURLframe, orient='horizontal', length=300, mode='determinate')
self.progressBar.grid(column=1, row=1)
ttk.Label(self.mainVTURLframe, text="File path:").grid(column=0, row=2, sticky='W') # <== right-align
self.filePath = StringVar()
filePathEntry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=self.filePath, state='readonly')
filePathEntry.grid(column=1, row=2, sticky='W')
ttk.Label(self.mainVTURLframe, text="Status:").grid(column=0, row=3, sticky='W') # <== right-align
self.status = StringVar()
statusEntry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=self.status, state='readonly')
statusEntry.grid(column=1, row=3, sticky='W')
ttk.Label(self.mainVTURLframe, text="Positive Indications:").grid(column=0, row=4, sticky='W') # <== right-align
self.positiveIndications = StringVar()
positiveIndicationsEntry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=self.positiveIndications, state='readonly')
positiveIndicationsEntry.grid(column=1, row=4, sticky='W')
ttk.Label(self.mainVTURLframe, text="SHA1:").grid(column=0, row=5, sticky='W') # <== right-align
self.sha1 = StringVar()
sha1Entry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=self.sha1, state='readonly')
sha1Entry.grid(column=1, row=5, sticky='W')
ttk.Label(self.mainVTURLframe, text="SHA256:").grid(column=0, row=6, sticky='W') # <== right-align
self.sha256 = StringVar()
sha256Entry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=self.sha256, state='readonly')
sha256Entry.grid(column=1, row=6, sticky='W')
chooseFileButton = ttk.Button(self.mainVTURLframe, text="Choose File", width=40, command=self._scanFile).grid(column=1, row=0)
self.scanCheckingTimeInterval = 25000 # This is the amount of time we are going to wait before asking VT again if it already processed our scan request
for child in self.mainVTURLframe.winfo_children():
child.grid_configure(padx=4, pady=2)
def showResults(self, results):
try:
#self.file_Path = self.filePath
self.sha1.set(results["sha1"])
self.sha256.set(results["sha256"])
self.positiveIndications.set(results["positives"])
if results["positives"] == 0:
messagebox.showwarning("Analysis Info","File is Safe.\nOur Scanners found nothing Malicious")
elif results["positives"] <= 5:
messagebox.showwarning("Analysis Alert", "Given File may be Malicious")
elif results["positives"] >= 5:
messagebox.showwarning("Analysis Alert", f"Given File is Malicious.\nAdvice you remove the file from your System!")
res = messagebox.askyesno("Analysis Alert","The given file is highly Malicious.\nDo you want to Delete it permanently?")
if res == 1:
print("Attemting to delete file...")
time.sleep(1)
os.remove(self.filePath1)
#if os.PathLike(_scanFile.filePath):
# os.remove(self.filePath)
else:
print("This file cannot be deleted. Please do not use the fie. It's Malicious")
except Exception as e:
messagebox.showerror('Error', e)
def checkStatus(self):
try:
self.scanResult = self.vtClient.get_file_report(self.scanID)
print(self.scanResult)
if self.scanResult["response_code"] == -2: # By reading the next line, you can understand what is the meaning of the -2 response ode
self.status.set("Scanning...")
self.progressBar['value'] = self.progressBar['value'] + 5
self.root.update_idletasks()
self.mainVTURLframe.after(self.scanCheckingTimeInterval, self.checkStatus)
else:
self.hasScanFinished = True
self.showResults(self.scanResult)
self.status.set("Finished!")
self.progressBar['value'] = 100
except Exception as e:
if "To much API requests" in str(e):
pass
def _scanFile(self):
try:
self.progressBar['value'] = 0
self.filePath1 = filedialog.askopenfilename(initialdir="/", title="Select file for VT", filetypes=(("EXE files", "*.exe"), ("all files", "*.*")))
if (self.filePath): # Only if the user chose a file, we will want to continue the process
self.filePath.set(self.filePath1)
self.status.set("Sending file...")
self.progressBar['value'] = 10
self.root.update_idletasks()
self.scanID = self.vtClient.scan_file(self.filePath1)
self.hasScanFinished = False
if not self.hasScanFinished:
self.scanResult = self.vtClient.get_file_report(self.scanID)
print(self.scanResult)
self.checkStatus()
# We could have been using time.sleep() or time.wait(), but then our UI would get stuck.
# by using after, we are initiating a callback in which does not blocks our event loop
except Exception as e:
messagebox.showerror('Error', e)
URLreportTab.py
from tkinter import ttk
from tkinter import StringVar
from VTPackage import Consts
class URLreportTab:
def __init__(self, root, frame, vtClient):
self.root = root
self.frame = frame
self.mainVTURLframe = ttk.LabelFrame(frame, text=' URL report tab!')
# using the tkinter grid layout manager
self.mainVTURLframe.grid(column=0, row=0, padx=8, pady=4)
ttk.Label(self.mainVTURLframe, text="URL:").grid(column=0, row=0, sticky='W') # What does sticky does? Sticky sayes where to stick the label to : N,S,E,W
urlEntry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH)
urlEntry.grid(column=1, row=0, sticky='E')
ttk.Label(self.mainVTURLframe, text="Positive Indications:").grid(column=0, row=1, sticky='W') # <== right-align
Positive = StringVar()
PositiveEntry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=Positive, state='readonly')
PositiveEntry.grid(column=1, row=1, sticky='W')
ttk.Label(self.mainVTURLframe, text="Detections:").grid(column=0, row=2, sticky='W') # <== right-align
detections = StringVar()
detectionsEntry = ttk.Entry(self.mainVTURLframe, width=Consts.ENTRY_WIDTH, textvariable=detections, state='readonly')
detectionsEntry.grid(column=1, row=2, sticky='W')
self.notificationFrame = ttk.LabelFrame(self.frame, text=' Notifications', width=40)
# using the tkinter grid layout manager
self.notificationFrame.grid(column=0, row=1, padx=8, pady=10, sticky='W')
ttk.Label(self.notificationFrame, text="Errors:").grid(column=0, row=0, sticky='W') # <== increment row for each
Error = StringVar()
ErrorEntry = ttk.Entry(self.notificationFrame, width=Consts.ENTRY_WIDTH, textvariable=Error, state='readonly')
ErrorEntry.grid(column=1, row=0, sticky='W')
def _cleanErrorMessage(): # We could have been doing this without a function, but it is more neat that way
Error.set("")
def _getReport():
# the _ notation before a function means that this function is internal to the class only. As python cannot really prevent you from using it outside the class (as C# for example) the notation is being used to warn other developers not to call this function outside the class
try:
_cleanErrorMessage() # Starting with cleaning the error message bar
if not urlEntry.get():
print('Please enter a URL')
Error.set("Please enter a URL!")
return
urlToCheck = urlEntry.get()
response = vtClient.get_url_report(urlToCheck)
print(response)
Positive.set(response["positives"])
scans = response["scans"]
findings = set()
for key, value in scans.items():
if value["detected"]:
findings.add(value["result"])
detections.set(",".join([str(finding) for finding in findings]))
except Exception as e:
print(e)
Error.set(e)
checkURLinVTButton = ttk.Button(self.mainVTURLframe, text='Check Now!', command=_getReport).grid(column=2, row=0)
# Instead of setting padding for each UI element, we can just iterate through the children of the main UI object.
for child in self.mainVTURLframe.winfo_children():
child.grid_configure(padx=4, pady=2)
for child in self.notificationFrame.winfo_children():
child.grid_configure(padx=4, pady=2)
VTApp.py
import tkinter as tk
import configparser
from tkinter import Menu
from tkinter import ttk
from tkinter import messagebox
from VTPackage import URLreportTab
from VTPackage import FileReportTab
from VTPackage import VTClient
config = configparser.ConfigParser()
config.read('config.ini')
class VTApp:
def __init__(self):
# Loading the config file
self.config = configparser.ConfigParser()
self.config.read('config.ini')
self.virusTotalAPIkey = config['VirusTotal']['apiKey']
self.vtClient = VTClient.VTClient(self.virusTotalAPIkey)
self.root = tk.Tk()
self.root.title("Virus Total UI")
self.menuBar = Menu()
self.root.config(menu=self.menuBar)
self.fileMenu = Menu(self.menuBar, tearoff=0)
self.fileMenu.add_command(label="New")
self.fileMenu.add_separator()
self.menuBar.add_cascade(label="File", menu=self.fileMenu)
if not self.vtClient.is_API_key_valid():
messagebox.showerror('Error', "API key is not valid! Check your config file")
def _quit():
self.root.quit() # The app will exist when this function is called
self.root.destroy()
exit()
self.fileMenu.add_command(label="Exit", command=_quit) # command callback
self.tabControl = ttk.Notebook(self.root) # Create Tab Control
self.urlFrame = ttk.Frame(self.tabControl)
self.urlTab = URLreportTab.URLreportTab(self.root, self.urlFrame, self.vtClient)
self.tabControl.add(self.urlFrame, text='URL')
self.fileFrame = ttk.Frame(self.tabControl)
self.fileTab = FileReportTab.FileReportTab(self.tabControl, self.fileFrame, self.vtClient)
self.tabControl.add(self.fileFrame, text='File')
self.tabControl.pack(expand=1, fill="both") # Pack to make visible
def start(self):
self.root.mainloop()
Main.py
from VTPackage import VTApp
vtApp = VTApp.VTApp()
vtApp.start()
This is the original code, Sorry for the spacing error, I copy&paste from vsc and it seem like the got some spacing error after Class. So basically this is the original code and I try like import VTApp and code inside class Page2 like
vtApp = VTApp.VTApp()
vtApp.start()
and change some coding in the VTApp.py but it doesn't work.... Does anyone know how to make the script works? I been trying and trying for a week and still couldn't get the solution.
You cannot move a widget from one window to another in tkinter. You will have to recreate the tab in the other window.
relatively new to coding and currently I am playing with tkinter in python, I am using a text widget within a function and want to send the input from the text box to another function. My global variable says undefined at module level, so How could I make it defined at a module level if its within a function?
When I press the send email button I get this error message "NameError: name 'user_message_entry' is not defined"
Any suggestions? Many thanks!
minimum reproduction:
import tkinter as tk
root = tk.Tk()
root.geometry("500x500")
def send_email():
global user_message_entry
subject = ":)"
body = user_message_entry.get("1.0", "end")
message = f"subject: {subject}\n\n {body}"
print(message)
def feedback():
feedback_window = tk.Toplevel()
feedback_window.geometry("690x650")
message_frame = tk.Frame(feedback_window)
message_frame.grid(row=0, column=0, columnspan=3)
user_message_entry = tk.Text(message_frame, height=10, width=60)
user_message_entry.grid(row=0, column=0)
send_email_button = tk.Button(feedback_window, command=send_email,
height=20, width=20, bg="yellow", text="send email")
send_email_button.grid(row=1, column=0)
open_feedback_button = tk.Button(root, command=feedback, height=20, width=20, bg="yellow", text="open feedback window")
open_feedback_button.grid(row=1, column=0)
root.mainloop()
You can use Object orient methodology to make access sympler, another option also you can use globals() to make variable global
One way
globals()['user_message_entry'] = tk.Text(message_frame, height=10, width=60)
....
and from another function you can call
body = globals()['user_message_entry'].get("1.0", "end")
Second way
Object oriented programming is good for every type of problem solving, so you can use class as well
import tkinter as tk
class CBased:
def __init__(self, master, *args, **kwargs):
super(CBased, self).__init__(*args, *kwargs)
self.master = master
master.geometry("500x500")
self.open_feedback_button = tk.Button(master, command=self.feedback, height=20, width=20, bg="yellow", text="open feedback window")
self.open_feedback_button.grid(row=1, column=0)
def send_email(self):
subject = ":)"
body = self.user_message_entry.get("1.0", "end")
message = f"subject: {subject}\n\n {body}"
print(message)
def feedback(self):
self.feedback_window = tk.Toplevel()
self.feedback_window.geometry("690x650")
self.message_frame = tk.Frame(self.feedback_window)
self.message_frame.grid(row=0, column=0, columnspan=3)
self.user_message_entry = tk.Text(self.message_frame, height=10, width=60)
self.user_message_entry.grid(row=0, column=0)
self.send_email_button = tk.Button(self.feedback_window, command=send_email,
height=20, width=20, bg="yellow", text="send email")
self.send_email_button.grid(row=1, column=0)
def main():
root = Tk()
myobj = CBased(root)
root.mainloop()
if __name__ == "__main__":main()
In this way you can call every single item by self.xyz
I want to display the selected options from my checkbox list in a new list in a new Tkinter window and when browsing it comes back to the main screen
(using Python 3.5 with Ubuntu 16.04).
import tkinter as tk
import tkMessageBox
lista=['jpeg','jfit','tiff','gif','png','bmp']
class PopUp(tk.Toplevel):
def __init__(self, number=10):
tk.Toplevel.__init__(self)
self.global_state = tk.BooleanVar()
cb = tk.Checkbutton(self, text="select/deselect all", variable=self.global_state, command=self.select_clear_states)
cb.grid(row=0, column=0, padx=5, pady=1)
self.states = []
for n in range(len(lista)):
var = tk.BooleanVar()
cb = tk.Checkbutton(self, text=str(lista[n]), variable=var)
cb.grid(row=n+1, column=0, padx=5, pady=1)
self.states.append(var)
def select_clear_states(self):
state = self.global_state.get()
for x in self.states:
x.set(state)
def popup(num):
win = PopUp(num)
root = tk.Tk()
b = tk.Button(root, text="5 checkboxes", command=lambda:popup(5))
b.pack()
root.mainloop()
Assuming I understand you correctly, if you wanted to do this with Checkbuttons you could do something like the below:
from tkinter import *
class App:
def __init__(self, root):
self.root = root
self.top = Toplevel(root)
self.frame = Frame(self.top)
self.frame.pack()
self.check = []
self.var = []
for i in range(10):
self.var.append(IntVar())
self.var[i].trace("w", self.callback)
self.check.append(Checkbutton(self.root, text="Option "+str(i), variable=self.var[i]))
self.check[i].pack()
def callback(self, *args):
self.frame.destroy()
self.frame = Frame(self.top)
self.frame.pack()
for i, c in zip(self.check, self.var):
if c.get() == 1:
Label(self.frame, text=i.cget("text")).pack()
root = Tk()
App(root)
root.mainloop()
Alternatively you might find that a Listbox accomplishes what you want and (IMO) looks a lot cleaner and more user friendly:
from tkinter import *
class App:
def __init__(self, root):
self.root = root
self.listbox = Listbox(self.root, selectmode=MULTIPLE)
self.listbox.pack()
for i in range(10):
self.listbox.insert(END, "Option "+str(i))
root = Tk()
App(root)
root.mainloop()
Using the Listbox you probably wouldn't even need two windows as the selection quite clearly shows which options are selected by highlighting them.
NameError: name 'onOpen' is not defined
There is something wrong with the command function. I am not sure what I did wrong here. I had the code tested before the onOpen function and it works fine.
import tkinter as tk
from tkinter import filedialog
class Application(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.pack()
self.createWidgets()
def onOpen():
""" Ask the user to choose a file and update the values of label change button"""
button_label.set(filedialog.askopenfilename(filetypes = ()))
def createWidgets(self):
#instruction label
self.labelInstruct = tk.Label(self, text="Instructions:", padx=10, pady=10)
self.labelInstruct = tk.Label(self, text="All you have to do is insert the file and save it.\n The conversion is instant", padx=10, pady=10)
self.labelInstruct.pack()
#insertfile button
self.ifbut = tk.Button(self, text="Insert File", command=onOpen)
self.ifbut.pack()
button_label = tk.StringVar(self)
text = tk.Label(self, textvariable = button_label)
text.pack()
#save button
self.saveLabel = tk.Label(self, text="Save File", padx=10, pady=10)
self.saveLabel.pack()
self.saveButton = tk.Button(self)
self.saveButton.pack()
#quit button
self.quitButton = tk.Button(self, text='Quit',
command=self.quit)
self.quitButton.pack()
app = Application()
app.master.title('Sample application')
app.mainloop()
Seeing that there are many problems with the way this code is written I am only going to point out a few of them and tackle the main question from the OP.
Lets start with the fact that you need to define the main window with something like root = tk.Tk() and you also need to make sure all your methods in your class have the argument self as the first argument.
Also any variable you are defining also should have self so that the class can interact with it. This (button_label) for example should be self.button_label.
There is no reason to use return the way you are trying to in the onOpen(self): method. Return does not work like that. Return is there so you can return a value to something that is calling the function/method to be used for something else and is not for setting the value of something.
Note that I also add the root window variable to the app = Application(root) line. This lets us pass the main window into the class.
all and all the following should work for the onOpen(self): function but the rest still needs some work.
import tkinter as tk
from tkinter import filedialog
class Application(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.parent = parent
self.pack()
self.createWidgets()
def onOpen(self):
""" Ask the user to choose a file and update the values of label change button"""
self.button_label.set(filedialog.askopenfilename(filetypes = ()))
def createWidgets(self):
#instruction label
self.labelInstruct = tk.Label(self.parent, text="Instructions:", padx=10, pady=10)
self.labelInstruct = tk.Label(self.parent, text="All you have to do is insert the file and save it.\n The conversion is instant", padx=10, pady=10)
self.labelInstruct.pack()
#insert file button
self.ifbut = tk.Button(self.parent, text="Insert File", command = self.onOpen)
self.ifbut.pack()
self.button_label = tk.StringVar()
self.text = tk.Label(self.parent, textvariable = self.button_label)
self.text.pack()
#save button
self.saveLabel = tk.Label(self.parent, text="Save File", padx=10, pady=10)
self.saveLabel.pack()
self.saveButton = tk.Button(self.parent, text = "Save")
self.saveButton.pack()
#quit button
self.quitButton = tk.Button(self.parent, text='Quit', command=self.quit)
self.quitButton.pack()
root = tk.Tk()
app = Application(root)
app.master.title('Sample application')
app.mainloop()
You need to return the function value as below:
def onOpen():
""" Ask the user to choose a file and update the values of label change button"""
return button_label.set(filedialog.askopenfilename(filetypes = ()))
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()