Use textvariable for Text box without Entry in TKinter - python

I'm writing a GUI program where I want to create text to speech. There I am facing some problem. I am calling textvariable without using Entry Wedge. That's not working. Do you have any solution or alternative?
&
have you any suggestion to inert text box in GUI or multiline Entry?
Thanks in advance
from tkinter import *
from gtts import gTTS
from playsound import playsound
from tkinter import scrolledtext
root = Tk()
root.geometry("450x400")
root.resizable(0, 0)
root.configure(bg='ghost white')
root.title("TEXT TO SPEECH")
L1 = Label(root, text="TEXT_TO_SPEECH", font="arial 15 bold",
fg="#20bebe", bg='white smoke').pack()
L2 = Label(root, text="Enter Text", font='arial 10 bold',
bg='white smoke').place(x=20, y=60)
Msg = StringVar()
textareaframe = Frame(root)
textareaframe.pack()
textareaframe.place(x=20, y=80)
TextArea = Text(textareaframe, textvariable=Msg)
ScrollBar = Scrollbar(textareaframe)
ScrollBar.config(command=TextArea.yview)
TextArea.config(yscrollcommand=ScrollBar.set, width=40, height=10)
ScrollBar.pack(side=RIGHT, fill=Y)
TextArea.pack()
def Convert():
Message = TextArea.get()
speech = gTTS(text=Message)
speech.save('T2S.mp3')
playsound('T2S.mp3')
def Play():
pass
def Exit():
root.destroy()
def Reset():
Msg.set("")
buttonframe = Frame(root)
buttonframe.pack(padx=5, pady=5)
buttonframe.place(y=280)
Button(buttonframe, text="Convert", font='arial 14 bold',
command=Convert).pack(side=LEFT, padx=5)
Button(buttonframe, text="PLAY", font='arial 14 bold',
command=Play).pack(side=LEFT, padx=5)
Button(buttonframe, text='EXIT', font='arial 14 bold',
command=Exit, bg="#20bebe").pack(side=LEFT, padx=5)
Button(buttonframe, text='RESET', font='arial 14 bold',
command=Reset).pack(side=LEFT, padx=5)
L_end = Label(text="SAAD QURESHI", font='arial 12 bold', fg="#20bebe",
bg='white smoke', width='20').pack(side='bottom')
root.mainloop()
output Error
_tkinter.TclError: unknown option "-textvariable"
If I use Entry then its work, but I want to use a multiple line text box.
entry_field = Entry(root, textvariable=Msg, width='50')
entry_field.pack()
entry_field.place(x=20, y=80)

TextArea = Text(textareaframe)#Remove the textvariable keyword argument
TextArea.pack()
To get the contents of the Text box you can do something like :
contents = TextArea.get('1.0','end')
TextArea.get('1.0','end') returns all the contents of the text box from the 0 index to the last index

Related

How to create a mandatory window in tkinter

I am using python 3.7 and tkinter for making a GUI which saves all my important passwords which are saved in a file passwords.txt. In this I want to create a button in my main window which pops up another window with an entry box and a button(which will close the window) and till this window is not closed it will not let the user to interact with my old window.
Here's my codes:
from tkinter import *
from tkinter import ttk
root = Tk()
f = open("passwords.txt", "r")
list1 = []
for item in f.readlines():
item = item.replace("\n", "")
list1.append(item)
def secondwindow():
root2 = Tk()
root2.title("Secure Your Password")
root2.configure(bg="black")
root2.geometry('700x600')
frame_color = "#%02x%02x%02x" % (150,150,150)
# Create A Main frame
main_frame = Frame(root2, bg=frame_color)
main_frame.pack(fill=BOTH,expand=1)
# Create Frame for X Scrollbar
sec = Frame(main_frame, bg=frame_color)
sec.pack(fill=X,side=BOTTOM)
# Create A Canvas
my_canvas = Canvas(main_frame, bg="black")
my_canvas.pack(side=LEFT,fill=BOTH,expand=1)
# Add A Scrollbars to Canvas
x_scrollbar = ttk.Scrollbar(sec,orient=HORIZONTAL,command=my_canvas.xview)
x_scrollbar.pack(side=BOTTOM,fill=X)
y_scrollbar = ttk.Scrollbar(main_frame,orient=VERTICAL,command=my_canvas.yview)
y_scrollbar.pack(side=RIGHT,fill=Y)
# Configure the canvas
my_canvas.configure(xscrollcommand=x_scrollbar.set)
my_canvas.configure(yscrollcommand=y_scrollbar.set)
my_canvas.bind("<Configure>",lambda e: my_canvas.config(scrollregion= my_canvas.bbox(ALL)))
# Create Another Frame INSIDE the Canvas
second_frame = Frame(my_canvas, bg=frame_color)
# Add that New Frame a Window In The Canvas
my_canvas.create_window((0,0),window=second_frame, anchor="nw")
f = Frame(second_frame, borderwidth=2, relief=SUNKEN, bg=frame_color)
f.pack(side=TOP, fill=X)
Label(f, text="Secure Your Password", fg="white", bg=frame_color, font="Algerian 35 italic").pack()
f1 = Frame(second_frame, bg="black")
f1.pack(fill=BOTH, side=TOP, expand=1)
Label(f1, text="Application", fg="red", bg="black", font="Calibri 20 bold", pady=10, padx=60).grid(row=1, column=1)
Label(f1, text="Username", fg="red", bg="black", font="Calibri 20 bold", pady=10, padx=210).grid(row=1, column=2)
Label(f1, text="Password", fg="red", bg="black", font="Calibri 20 bold", pady=10, padx=198).grid(row=1, column=3, padx=140)
for i in range(len(list1)):
application = list1[i].split(";;;")[0]
username = list1[i].split(";;;")[1]
password = list1[i].split(";;;")[2]
Label(f1, text=application, fg="white", bg="black", font="Calibri 20 bold", pady=5).grid(row=i+2, column=1)
Label(f1, text=username, fg="white", bg="black", font="Calibri 20 bold", pady=5).grid(row=i+2, column=2)
Label(f1, text=password, fg="white", bg="black", font="Calibri 20 bold", pady=5).grid(row=i+2, column=3)
root2.mainloop()
def checkPassword(password, l):
if password == "a":
root.destroy()
secondwindow()
else:
l.config(text="Wrong Password")
def password_window():
root.geometry('450x270')
root.title("Secure Your Password")
root.minsize(450, 270)
root.maxsize(450, 270)
root.configure(bg="black")
Label(root, text="Secure Your Password", fg="white", bg="black", font="Algerian 24 italic").pack(side=TOP)
Label(root, text="Your Password", fg="white", bg="black", font="Clibri 15").pack(pady=10)
password = StringVar()
Entry(root, textvariable=password, bg="grey", fg="white", font="Calibri 15 bold").pack(pady=10)
Button(root, text="Login", bg="grey", fg="white", activebackground="grey", font="Calibri 10", command=lambda: checkPassword(password.get(), l)).pack(pady=8)
l = Label(root, fg="red", bg="black", font="Clibri 10 bold")
l.pack()
password_window()
root.mainloop()
And my passwords.txt:
StackOverflow;;;PomoGranade;;;PomoGranade_StackOverflow
GitHub;;;Pomogranade;;;PomoGranade_GitHub
I am new to python and tkinter. Thanks for help in advance :)
I do not recommend using * imports, though it may not be exactly wrong in this case.
Use the TopLevel widget instead of initialising another Tk window. See why using another Tk is not good.
Use .grab_set() (Look at #TheLizzard's link in the comment for a better example)
Look at this example -
import tkinter as tk
root = tk.Tk()
def f1():
top1 = tk.Toplevel(root)
b2 = tk.Button(top1,text='Close New Window',command=top1.destroy)
b2.pack()
top1.grab_set()
b1 = tk.Button(root,text='Create Mandatory Window',command=f1)
b1.pack()
root.mainloop()
If you run this code, you will see that the first window does not react to any mouse press etc... and also you cannot close the first window after opening the new window until the it is closed

Why aren't my buttons properly aligned with python TKinter

I am creating a password manager which includes some buttons, but for some reason these buttons aren't aligning properly, could someone help out?
Here is the code i've done usint Tkinter for these buttons:
btn = Button(window, text="Exit Securely", command=exit)
btn.grid(column=2)
btn = Button(window, text="Add Entry", command=addEntry)
btn.grid(column=1)
btn = Button(window, text="Generate", command=run)
btn.grid(column=0)
lbl = Label(window, text="Website")
lbl.grid(row=3, column=0, padx=80)
lbl = Label(window, text="Username")
lbl.grid(row=3, column=1, padx=80)
lbl = Label(window, text="password")
lbl.grid(row=3, column=2, padx=80)
which makes my program look like this:
Any general tips or helpful links for how to make a nicer GUI would be appreciated as well, as I have been struggling with that.
As #acw1668 said if you don't specify row in grid(), it will take the next available row.
# Code to make this example work:
from tkinter import *
def addEntry():pass
def run():pass
window = Tk()
# Added `row=0` for each one of them
btn = Button(window, text="Exit Securely", command=exit)
btn.grid(row=0, column=2)
btn = Button(window, text="Add Entry", command=addEntry)
btn.grid(row=0, column=1)
btn = Button(window, text="Generate", command=run)
btn.grid(row=0, column=0)
# Changed the row to 1 for all of them
lbl = Label(window, text="Website")
lbl.grid(row=1, column=0, padx=80)
lbl = Label(window, text="Username")
lbl.grid(row=1, column=1, padx=80)
lbl = Label(window, text="password")
lbl.grid(row=1, column=2, padx=80)
By the way it is a good idea to use different names for the different buttons/labels.
I have been trying various method of aligning the widgets of tkinter in the program window lately and well I have found a better working solution to this.
In you program you have been using grid for aligning. I would say that you replace with place instead.
place will allow you to set a definite x and y coordinate for the widget and it would be easy to use.
If I alter your code accordingly, I can show you the code (after alteration) and the image of the output.
Code (After Alteration)
# Code to make this example work:
from tkinter import *
def addEntry():pass
def run():pass
window = Tk()
# Adding geometry ettig.
window.geometry('500x500')
btn = Button(window, text="Exit Securely", command=exit)
btn.place(x=410, y=20)
btn = Button(window, text="Add Entry", command=addEntry)
btn.place(x=210, y=20)
btn = Button(window, text="Generate", command=run)
btn.place(x=10, y=20)
lbl = Label(window, text="Website")
lbl.place(x=10, y=50)
lbl = Label(window, text="Username")
lbl.place(x=210, y=50)
lbl = Label(window, text="password")
lbl.place(x=410, y=50)
The Output Screen

How to add multiline text dynamically in tkinter python?

I have created a chat application, in which i use ListBox for showing the chat history. It looks good until I enter a long sting which goes beyond the screen. Is there a way to break the string and show in new line or any other way to show the complete string. I'm new to Tkinter and im not aware of many widgets available.
Here is my sample code
from tkinter import *
class Actions:
def chatUpdate(chat):
chatlist.insert(Actions.chatLast,chat)
Actions.chatLast=Actions.chatLast+1
chatlist.pack( side=LEFT, fill=BOTH)
chatBox.config(command=chatlist.yview)
def callUpdater():
txt=textBox.get()
text_text.set("")
Actions.chatUpdate(txt)
root = Tk()
root.title("Chat App")
frame1 = Frame(root, bd=4)
frame1.pack(side=TOP)
frame2 = Frame(root, bd=4)
frame2.pack(side=TOP)
frame3 = Frame(root, bd=4)
frame3.pack(side=TOP)
# chat box
chatBox = Scrollbar(frame1)
chatBox.pack(side=RIGHT, fill=Y)
chatlist = Listbox(frame1, yscrollcommand = chatBox.set, width=50)
Actions.chatLast=0
Actions.chatUpdate(" ")
# text box
textView = Label(frame2, text="Input: ")
textView.pack(side=LEFT)
text_text = StringVar()
textBox = Entry(frame2, textvariable=text_text, bd=0, width=40, bg="pink")
textBox.pack(side=RIGHT)
# send button
button = Button(frame3, text="Send", fg="black", command=callUpdater)
button.pack(side=TOP)
root.mainloop()
You can replace the Listbox by a Text widget in 'disabled' mode which automatically wraps long lines. You will just need to put the widget back in 'normal' mode each time you insert text:
from tkinter import *
def callUpdater():
text = textBox.get()
textBox.delete(0, 'end')
chat.configure(state='normal')
chat.insert('end', text + '\n')
chat.configure(state='disabled')
root = Tk()
chatBox = Scrollbar(root)
chat = Text(root, wrap='word', state='disabled', width=50,
yscrollcommand=chatBox.set)
chatBox.configure(command=chat.yview)
chat.grid(row=0, columnspan=2, sticky='ewns')
chatBox.grid(row=0, column=2, sticky='ns')
Label(root, text="Input: ").grid(row=1, column=0)
textBox = Entry(root, bd=0, width=40, bg="pink")
textBox.grid(row=1, column=1)
Button(root, text="Send", command=callUpdater).grid(row=2, columnspan=2)
root.mainloop()
By the way, both the Listbox and Text widgets support the index 'end' so you don't have to keep track of how many lines you have inserted.

Multiple Windows using Python with Tkinter

I have a school project and I need to create my GUI soon and I cant find an efficient way to do so and I need to make a ceaser Cipher button which brings up a window with an input in there and I need it all to look nice. Here is my code for now. Its not finished and needs to be finished but don't know how to?
from tkinter import *
root = Tk()
root.geometry("180x135")
class Welcome:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.button1 = Button(topFrame, text ="Decrypter Mode", bg='Black', fg="red", command = self.new_window)
self.button1.pack(side=RIGHT)
self.quitButton = Button(frame, bg='black', fg='white', text='Quit', command=master.destroy)
self.quitButton.pack(side=LEFT)
def new_window(self):
self.newWindow = tk.Toplevel(self.master)
self.app = Demo2(self.newWindow)
topFrame = Frame(root)
topFrame.pack()
bottomFrame = Frame(root)
bottomFrame.pack(side=BOTTOM)
one = Label(root, text='Welcome to Crypto-coder', bg='black', fg='white')
one.pack(fill=X)
one = Label(root, text='', bg='black', fg='white')
one.pack(fill=X,)
one = Label(root, text='', bg='black', fg='white')
one.pack(fill=X,)
one = Label(root, text='', bg='black', fg='white')
one.pack(fill=X,)
button1 = Button(topFrame, text ="Decrypter Mode", bg='Black', fg="red",)
button2 = Button(topFrame, text ="Encoder Mode", bg='black', fg="blue")
button1.pack(side=RIGHT)
button2.pack(side=LEFT)
W=Welcome(root)
root.mainloop()
I had to move some things for the code to show so you may have to fix it if you try it.

grid_remove on an Entry widget

Im new to Tkinter and am trying to build a simple GUI using grid manager which upon the push of button1, button2 appears along with an adjacent entry box. If you then press button2 the entry box and button2 dissapear. Below is a slice from the GUI code, the button dissapears but the entry box does not:
import Tkinter
from Tkinter import *
master = Tk()
CreateTestButton = Button(master, text="Create Test", command = CreateTest, fg="red", bg="white", font="Helvetica 10 bold")
CreateTestButton.grid(column=7, row=1)
def CreateTest():
TestEntry = Entry(master, text="", width = 100).grid(row=4,columnspan=6)
Label(self, text="Enter Test Name:").grid(row=3, column=0)
SaveTestButton = Button(master, text="Save to database", command=saveTest, fg="green", bg="white", font="Helvetica 10 bold")
SaveTestButton.grid(row=4, column=5)
def saveTest():
SaveTestButton.grid_remove()
TestEntry.grid_remove() #ERROR
mainloop()
How is one to remove entry boxes using grid manager in Tkinter? And other widgets for that matter I will also be needing to remove a list box, labels and widgets uppon a button click or event.
Regards,
Daniel
grid return nothing; By executing TestEntry = Entry(..).grid(...), TestEntry become None instead of Entry object.
Replace following line:
TestEntry = Entry(self, text="", width = 100).grid(row=4,columnspan=6)
with:
TestEntry = Entry(self, text="", width = 100)
TestEntry.grid(row=4,columnspan=6)
Complete code
from Tkinter import *
def CreateTest():
def saveTest():
SaveTestButton.grid_remove()
TestEntry.grid_remove() #ERROR
TestEntry = Entry(master, text="", width = 100)
TestEntry.grid(row=4,columnspan=6)
Label(master, text="Enter Test Name:").grid(row=3, column=0)
SaveTestButton = Button(master, text="Save to database", command=saveTest, fg="green", bg="white", font="Helvetica 10 bold")
SaveTestButton.grid(row=4, column=5)
master = Tk()
CreateTestButton = Button(master, text="Create Test", command = CreateTest, fg="red", bg="white", font="Helvetica 10 bold")
CreateTestButton.grid(column=7, row=1)
mainloop()

Categories