I have been trying to learn tkinter and have created something that post the results of a bunch of functions, and in the terminal the string formats works, but in the gui the string format does not work at all. I am super confused on why?
The code is below:
from tkinter import *
import ForFeesCovered
root = Tk()
root.title("Staff Fee Calculator")
root.geometry("375x400")
myLabel = Label(root,
text="Staff Fee Calculator")
e = Entry(root,
width=50,
borderwidth=5)
def output():
input_file = e.get()
f = ForFeesCovered.readfile(input_file)
file = ForFeesCovered.readfile(input_file)
staff = ForFeesCovered.getnamesofstaff(f)
staff.sort(reverse=False)
dic = ForFeesCovered.sort_dic(staff)
line_skip = 1
for lines in file:
line = lines.strip().split(",")
if line_skip != 1:
total = float("
{:.2f}".format(ForFeesCovered.getfeesforline(line)))
name = ForFeesCovered.get_name_of_staff(line, staff)
dic = ForFeesCovered.populating_dic(dic, name, total)
else:
line_skip += 1
string_dic = ""
result_file = open("result.txt", "w+")
for key in dic:
result_file.write("{} : {}\n".format(key, dic[key]))
string_dic = string_dic + "{:30} : {:>30}\n".format(key,
dic[key])
print(string_dic)
result_file.close()
output_dic = Label(root, text=string_dic, justify=LEFT)
output_dic.grid(row=2, column=0, pady=20)
submit = Button(root, text="Submit", command=output)
myLabel.grid(row=0, column=0)
e.grid(row=1, column=0,)
submit.grid(row=1, column=2)
root.mainloop()
The terminal is using a fixed-width font, the GUI is using a variable-width font.
If you are trying to line things up with spaces, you will need to used a fixed-width font.
Related
I'm trying to create a factorial calculator GUI.
The program works fine, but the problem I'm having is that when there are too many numbers coming in from the output, the screen automatically increases in width. I've tried using tk.Text to create a limit to the size of the textbox and so the text continues to the next row when the columns are filled.
But when I had to input text in to the tk.Text it didn't work since the variable I used is being processed in the function that gets called when the button is pressed. I have tried googling this problem but I couldn't find anything, I did find some people explaining how to use variables that get created/processed inside of a function, but that didn't work so I think I have done something wrong in my code.
Note: I am using lambda to call my function (not sure if this is important or not).
TLDR: Text gets too long when too much information is outputted. tk.Text didn't work for me since I couldn't figure out how to use the variable that is created/processed inside of a function that is only called when the button is pressed.
Here is my entire code: https://pastebin.com/1MkdRjVE
Code for my function:
def start_calc():
output_array = ["placehold"]
start_text.set("Loading...")
i = 1
global e1
global e2
output_array.clear()
string = e1.get()
string2 = e2.get()
integr = int(string)
integr2 = int(string2)
if string == "":
error_message.set("Please enter correct numbers.")
elif string2 == "":
error_message.set("Please enter correct numbers.")
else:
while integr2 >= i:
calc = integr ** i
calcstr = (str(calc))
output_array.append(calcstr)
i += 1
start_text.set("Start!")
output_array_str = (', '.join(output_array))
output_msg.set("Output: " + output_array_str)
print(output_array_str) #This is just so I know if it's working or not in the terminal
Code for my output:
output_msg = tk.StringVar()
output_text = tk.Label(root, textvariable=output_msg, font="Raleway")
output_msg.set("Output: ")
output_text.grid(columnspan=3, column=0, row=14)
I think this is what you are looking for:
#Imports
import tkinter as tk
#Variables
root = tk.Tk()
#Tkinter GUI setup basic
canvas = tk.Canvas(root, width= 400, height=400)
canvas.grid(columnspan=3, rowspan=120)
#Title
text = tk.Label(root, text="Calculating factorials", font="Raleway")
text.grid(column=1, row=1)
#Function
def start_calc():
output_array = ["", ""]
start_text.set("Loading...")
i = 1
global e1
global e2
output_array.clear()
string = e1.get()
string2 = e2.get()
integr = int(string)
integr2 = int(string2)
if string == "":
error_message.set("Please enter correct numbers.")
elif string2 == "":
error_message.set("Please enter correct numbers.")
else:
while integr2 >= i:
calc = integr ** i
calcstr = (str(calc))
output_array.append(calcstr)
i += 1
start_text.set("Start!")
output_array_str = (', '.join(output_array))
# Change the output
output_text.config(state="normal")
# delete last output:
output_text.delete("0.0", "end")
# insert new output:
output_text.insert("end", output_array_str)
output_text.config(state="disabled")
print(output_array_str) #This is just so I know if it's working or not in the terminal
#input
tk.Label(root, text="Number :").grid(row=10)
tk.Label(root, text="Factorial :").grid(row=11)
e1 = tk.Entry(root)
e2 = tk.Entry(root)
e1.grid(row=10, column=1)
e2.grid(row=11, column=1)
#Error message if the input is invalid
error_message = tk.StringVar()
error_text = tk.Label(root, textvariable=error_message, font="Raleway")
error_message.set(" ")
error_text.grid(column=1, row=12)
#Startbutton
start_text = tk.StringVar()
start_btn = tk.Button(root, textvariable=start_text, command=start_calc, font="Raleway", bg="#20bebe", fg="white", height=2, width=15)
start_text.set("Start!")
start_btn.grid(column=1, row=13, pady=10)
#output
output_text = tk.Text(root, height=1, width=20, wrap="none", font="Raleway")
output_text.insert("end", "Output")
output_text.config(state="disabled")
output_text.grid(columnspan=3, column=0, row=14, sticky="news")
#Adding a scrollbar
scrollbar = tk.Scrollbar(root, orient="horizontal", command=output_text.xview)
scrollbar.grid(columnspan=3, column=0, row=15, sticky="news")
output_text.config(xscrollcommand=scrollbar.set)
#disclaimer message
disclaimer_text = tk.Label(root, text="Disclaimer: The factorials will be printed from 1 to the number you entered.")
disclaimer_text.grid(columnspan=3, column=0, row=110)
root.mainloop()
I used a <tkinter.Text> widget with wrap="none", height=1 and width=20 to make the output box. I disabled the entry so that the user can't change the results but can still copy it.
I buid a code which takes python user input and insert it into a text file when pressing apply as shown in the picture bellow
and the text file will always be updated when the user inserts a new text, how to create an new button next to apply to show up to date text file to the user
and want prevent to enter the same text
example if the text file has a (go) the program do not enter (go) again
this is my code
root = Tk()
ivn = StringVar()
inputVarName = Entry(root, textvariable=str(ivn))
ivn.set(str("text1"))
inputVarName.grid(row=0, column=0)
ivn2 = StringVar()
inputVarName2 = Entry(root, textvariable=str(ivn2))
ivn2.set(str("text2"))
inputVarName2.grid(row=1, column=0)
def writetofile():
content_list = [ivn.get(), ivn2.get()]
print("\n".join(content_list))
with open("help.txt", "a") as f:
for item in content_list:
f.write("%s\n" % item)
applyButton = Button(root, text="Apply", command=writetofile)
applyButton.grid(row=2, column=1)
root.mainloop()
To prevent a user from inserting the same text just empty the two entries, and you can check if entries are not empty before saving to a file.
You can use a top-level window to show the file content.
Check the following example:
from tkinter import Tk, Toplevel, Button, Entry, StringVar, Text, DISABLED, END, W, E
import tkinter.ttk as ttk
import tkMessageBox
root = Tk()
ivn = StringVar()
inputVarName = Entry(root, textvariable=str(ivn))
ivn.set(str("text1"))
inputVarName.grid(row=0, column=0,columnspan=2)
ivn2 = StringVar()
inputVarName2 = Entry(root, textvariable=str(ivn2))
ivn2.set(str("text2"))
inputVarName2.grid(row=1, column=0,columnspan=2)
def writetofile():
content_list = [ivn.get(), ivn2.get()]
if any(content_list):
print("\n".join(content_list))
with open("help.txt", 'r+') as inFile:
for item in content_list:
if ("%s\n" % item).encode('UTF-8') in inFile:
tkMessageBox.showwarning("Warning", "'%s': Already exists!" % item)
return
with open("help.txt", "a") as f:
for item in content_list:
f.write( ("%s\n" % item).encode('UTF-8'))
ivn.set('')
ivn2.set('')
def showfile():
top = Toplevel()
top.title("help.txt")
textArea = Text(top)
scrollbar = ttk.Scrollbar(top, command=textArea.yview)
scrollbar.grid(row=0, column=1, sticky='nsew')
textArea['yscrollcommand'] = scrollbar.set
with open("help.txt", "r") as infile:
textArea.insert(END, infile.read())
textArea.grid(row=0, column=0)
textArea.config(state=DISABLED)
applyButton = Button(root, text="Apply", command=writetofile)
applyButton.grid(row=2, column=0, sticky=W+E)
showButton = Button(root, text="Show", command=showfile)
showButton.grid(row=2, column=1, sticky=W+E)
root.mainloop()
Edited to answer #IbrahimOzaeri question in comments.
You can use tkFileDialog.askopenfilename to ask user to select a file:
from Tkinter import Tk
import Tkinter, Tkconstants, tkFileDialog
root = Tk()
root.filename = tkFileDialog.askopenfilename(initialdir = "/",title = "Select file",filetypes = (("text files","*.txt"),("all files","*.*")))
print (root.filename)
I was trying something same but with one output
import tkinter.ttk as ttk
import tkMessageBox
root = Tk()
root.geometry("500x300")
root.title("The Gatway company")
ivn = StringVar()
inputVarName = Entry(root, textvariable=str(ivn))
ivn.set(str("text1"))
inputVarName.grid(row=0, column=0,columnspan=2)
def writetofile():
content_list = [ivn.get()]
if any(content_list):
with open("help.txt", 'r+') as inFile:
for item in content_list:
if ("%s\n" % item).encode('UTF-8') in inFile:
tkMessageBox.showwarning("Warning", "'%s': Already exists!" % item)
return
with open("help.txt", "a") as f:
for item in content_list:
f.write( ("%s\n" % item).encode('UTF-8'))
ivn.set('')
def showfile():
top = Toplevel()
top.title("help.txt")
textArea = Text(top)
scrollbar = ttk.Scrollbar(top, command=textArea.yview)
scrollbar.grid(row=0, column=1, sticky='nsew')
textArea['yscrollcommand'] = scrollbar.set
with open("help.txt", "r") as infile:
textArea.insert(END, infile.read())
textArea.grid(row=0, column=0)
textArea.config(state=DISABLED)
applyButton = Button(root, text="Apply", command=writetofile)
applyButton.grid(row=2, column=0, sticky=W+E)
applyButton.config( height = 5, width = 10 )
showButton = Button(root, text="Show", command=showfile)
showButton.grid(row=2, column=1, sticky=W+E)
showButton.config( height = 5, width = 10 )
root.mainloop()
it's same as your code but for one entry, I'm thinking to edit it in a such way that the user chooses the help.txt file like a file requester.
I want to create a python GUI with one user input which will be inserted to an excel sheet whenever the user Enters insert button, and another button called e.g Show words, which will read all the words which are inserted into the excel sheet, any ideas how to do that ?
the excel sheet shoud be like this
and the user interface should be something simple like this
some code that I created for GUI but its for text file not excel
from tkinter import *
root = Tk()
root.geometry("700x700")
ivn = StringVar()
inputVarName = Entry(root, textvariable=str(ivn))
ivn.set(str("text1"))
inputVarName.grid(row=0, column=0)
ivn2 = StringVar()
inputVarName2 = Entry(root, textvariable=str(ivn2))
ivn2.set(str("text2"))
inputVarName2.grid(row=1, column=0)
def writetofile():
content_list = [ivn.get(), ivn2.get()]
print("\n".join(content_list))
with open("help.txt", "a") as f:
for item in content_list:
f.write("%s\n" % item)
applyButton = Button(root, text="Apply", command=writetofile)
applyButton.grid(row=2, column=1)
root.mainloop() ```
sorry if its silly question but this will be my first python GUI program
You can create GUI using python tkinter, you can also create input fields using this library and accept the entered value. After this you can simple use python csv library to insert a record into sheet.
You can find more information about tkinter Here
Use this code to read data from test.txt (use your txt file) file, insert data into file also as you asked it will also check if same data exist. You can view the data by clicking on view data button.
from tkinter import *
root = Tk()
root.geometry("700x700")
ivn = StringVar()
inputVarName = Entry(root, textvariable=str(ivn))
ivn.set(str("text1"))
inputVarName.grid(row=0, column=0)
ivn2 = StringVar()
inputVarName2 = Entry(root, textvariable=str(ivn2))
ivn2.set(str("text2"))
inputVarName2.grid(row=1, column=0)
def printSomething():
with open('help.txt') as f:
r = f.read()
label = Label(root, text=r)
label.grid()
def checkdata():
with open('help.txt') as f:
r = f.read()
return r.split("\n")
def writetofile():
exist_data = checkdata()
content_list = [ivn.get(), ivn2.get()]
with open("help.txt", "a") as f:
for item in content_list:
if item in exist_data:
msg = "Already exist "+item
label = Label(root, text=msg)
label.grid()
elif not item in exist_data:
f.write("%s\n" % item)
applyButton = Button(root, text="Add Data", command=writetofile)
applyButton.grid(row=2, column=1)
veiwButton = Button(root, text='View Data', command=printSomething)
veiwButton.grid(row=3, column=1)
root.mainloop()
Note: There are multiple ways to achieve this, one of them is this one.
What I need is to make the view orders button to get the text from the Customer.txt file and set it inside a textfield i made.
#make order,cancel,view
from tkinter import *
import tkinter.messagebox
root = Tk()
file = open("Customer.txt", "w")
def textW():
outFile = open("Customer.txt", "wt")
def CancelOrder():
outFile=open("Customer.txt", "w")
outFile.write("")
tkinter.messagebox.showinfo("Cancel Order", "Your order has been canceled")
def ViewOrder():
outFile = open('Customer.txt', 'r')
test = outFile.read()
#tViewOrder.set(test)
print (test)
#test.set(tViewOrder)
#outFile.close()
def MakeOrder():
outFile=open("Customer.txt", "w")
outFile.write("" + tMakeOrder.get())
tkinter.messagebox.showinfo("Make Order", "Order has been placed. Thank you!")
#Labels
lMakeOrder = Label(root, text="Make an order")
lViewOrder = Label(root, text="View Order")
#TextFields
tMakeOrder = Entry(root)
tViewOrder = Entry(root, state="disabled")
#Buttons
bMakeOrder = Button(root, text="Make order",bg="black",fg="green", command=MakeOrder)
bCancelOrder = Button(root, text="Cancel order",bg="black",fg="green", command=CancelOrder)
bViewOrder = Button(root, text="View orders",bg="black",fg="green", command=ViewOrder)
#Position
lMakeOrder.grid(row=0)
lViewOrder.grid(row=1)
tMakeOrder.grid(row=0, column=2)
tViewOrder.grid(row=1, column=2)
bMakeOrder.grid(row=4)
bViewOrder.grid(row=4, column=2)
bCancelOrder.grid(row=4, column=4)
#Window stuff
root.title("Sky is a shit name service - Customer")
root.geometry("300x300")
root.mainloop()
You can put text inside your Entry by calling insert function on it.
MyEntry.insert(POSITION, TEXT)
Oh and one more thing. You can't insert anything in the entry if it's disabled.
So here is your modified function:
def ViewOrder():
outFile = open('Customer.txt', 'r')
test = outFile.read()
tViewOrder['state'] = 'normal'
tViewOrder.delete(0, 'end') #Remove everything before
tViewOrder.insert(0, test)
tViewOrder['state'] = 'disabled'
outFile.close()
Someone please help me figure this out.
I have the following problem in Tkinter Python. The problem is that the text is overlaying with the previous text. and/or is copying below that.
I've tried to use label.config(root).pack() instead of Label(root, text="").pack()
This kinda solves the problem it starts to write over the previous text but there are 2 problems with this.
1: the text old text/Entrys all still there, it just overlays.
2: this only works with label.config, and I would also like this to work with buttons and Entrys(textbox)
I've also tried .pack_forget() and .destroy() but unfortunately it did nothing.
CODE
from tkinter import *
import pickle
import time
import os
def new_profile():
global Var1, Var2
var1 = StringVar()
var2 = StringVar()
Label(root, text="Create a new profile").pack()
Label(root, text="User Name").pack()
Entry(root, textvariable=var1).pack()
Label(root, text="Password").pack()
Entry(root, textvariable=var2).pack()
Button(root, text="Create", command=create_profile).pack()
Var1, Var2 = var1, var2
return
def create_profile():
text1 = Var1.get()
text2 = Var2.get()
print(text1)
dict = {}
dict['Name'] = text1
dict['Password'] = text2
pickle.dump(dict, open("test.txt", "wb"))
dict1 = pickle.load(open("test.txt", "rb"))
if dict1['Name'] == text1 and dict1['Password'] == text2:
Label(root, text="").pack()
Label(root, text="Profile creation successful", ).pack()
Label(root, text="Name:" + " " + text1).pack()
Label(root, text="Password:" + " " + text2).pack()
else:
Label(root, text="Something went wrong while creating your profile.", ).pack()
return
def load_profile():
select = "Load profile.."
label.config(text=select)
return
root = Tk()
root.geometry("500x400+300+300")
root.title("client")
menubar = Menu(root)
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label="New Profile", command=new_profile)
filemenu.add_command(label="Load Profile", command=load_profile)
menubar.add_cascade(label="Profile Options", menu=filemenu)
root.config(menu=menubar)
label = Label(root)
label.pack()
root.mainloop()
create a array such as
on_screen = []
at the start then name your widgets and and add them to the array
password_label = Label(root, text="Password").pack()
password = Entry(root, textvariable=var2).pack()
on_screen.append(password)
on_screen.append(password_label)
then use a for loop to destroy all the widgets in the array
for w in on_screen:
w.destroy()