im looking to output a list of text to both a text file as well as a tkinter textbox. Currently I have it working to print to a text file being held in the same folder. I would like this same list to be printed on screen into the outputToScreen textbox
From my research I think I am meant to use .insert(index , text) but I can not get this method to work. I have also seen some old code using a .set function but when I tried this I came across an error saying that textbox's don't have that method
#file -> gui.py
# IMPORT tkinter for GUI creation and import scripts for functions
from tkinter import *
from tkinter.ttk import *
import scripts
import customtkinter
windowDim = str(750)+'x'+str(600)
window = customtkinter.CTk()
window.title("INFO GENERATOR")
window.geometry(windowDim)
window.resizable(True, True)
# Modes: system (default), light, dark
customtkinter.set_appearance_mode("dark")
# Themes: blue (default), dark-blue, green
customtkinter.set_default_color_theme("customTkinterTheme.json")
outputToScreen = customtkinter.CTkTextbox(window , width=400 , height=200)
outputToScreen.place(x=200, y=300)
def popupmsg(msg):
popup = customtkinter.CTk()
popup.title("!")
label = customtkinter.CTkLabel(popup, text=msg,)
label.pack(side="top", fill="x", pady=10)
B1 = customtkinter.CTkButton(popup, text="Okay", command=popup.destroy)
B1.pack()
popup.mainloop()
# create main window
# window specs are 700 x 350 and window is not able to be resizeable
# CREATING USER CONTROLS
# each button will print a list of items (number of items will be come from the entry userValue)
userEntry = customtkinter.CTkEntry(window)
# userValue = int(userValue)
userValue = ""
userEntry.place(x=325, y=200)
userEntry.insert(0, userValue)
userValueLabel = customtkinter.CTkLabel(
window, text="ENTER AMOUNT OF RECORDS YOU WOULD LIKE").place(x=275, y=170)
label = customtkinter.CTkLabel(window, text="INFOMATION GENERATOR by Noah Mackay "
).pack()
def outputEmails(userValue):
# function receives the amount of records the user wants to print
# function will be called when email button is clicked
# this function will clear the output file and then read open it
# will call the generateEmail function from scripts.py file
# outputs the amount of records based on the user input in the entry text box
userValue = int(userEntry.get())
outputFile = scripts.generateEmail(userValue)
file = open('output.txt', 'w').close()
file = open('output.txt', 'w')
file.write(str(outputFile))
outputToScreen.set(outputFile)
popupmsg("PRINTING WORKED")
def outputNames(userValue):
# function receives the amount of records the user wants to print
# function will be called when email button is clicked
# this function will clear the output file and then read open it
# will call the generateEmail function from scripts.py file
# outputs the amount of records based on the user input in the entry text box
userValue = int(userEntry.get())
outputFile = scripts.generateName(userValue)
file = open('output.txt', 'w').close()
file = open('output.txt', 'w')
file.write(str(outputFile))
outputToScreen.set(outputFile)
popupmsg("PRINTING COMPLETED")
def outputCost(userValue):
userValue = int(userEntry.get())
outputFile = scripts.generateCost(userValue)
file = open('output.txt', 'w').close()
file = open('output.txt', 'w')
file.write(str(outputFile))
outputToScreen.set(outputFile)
popupmsg("PRINTING COMPLETED")
def outputProduct(userValue):
userValue = int(userEntry.get())
outputFile = scripts.generateProduct(userValue)
file = open('output.txt', 'w').close()
file = open('output.txt', 'w')
file.write(str(outputFile))
outputToScreen.set(outputFile)
popupmsg("PRINTING COMPLETED")
def outputPhoneNumber(userValue):
userValue = int(userEntry.get())
outputFile = scripts.generatePhoneNumber(userValue)
file = open('output.txt', 'w').close()
file = open('output.txt', 'w')
file.write(str(outputFile))
outputToScreen.insert(0,outputFile)
popupmsg("PRINTING COMPLETED")
# creates 5 buttons each have their respective output function attached using command=
emailButton = customtkinter.CTkButton(window, text="EMAILS",
command=lambda: outputEmails(userValue)).place(x=5, y=40)
productButton = customtkinter.CTkButton(window, text="PRODUCTS",
command=lambda: outputProduct(userValue)).place(x=150, y=40)
phoneNumberButton = customtkinter.CTkButton(
window, text="PHONE NUMBERS" , command= lambda:outputPhoneNumber(userValue)).place(x=300, y=40)
costButton = customtkinter.CTkButton(window, text="PRICES",
command=lambda: outputCost(userValue)).place(x=450, y=40)
nameButton = customtkinter.CTkButton(
window, text="FIRST + LAST NAMES", command=lambda: outputNames(userValue)).place(x=600, y=40)
window.mainloop()
#file -> scripts.py
import random
def generateName(numberOfItemsNeed):
# opens 2 files. One containing first names and the other containing last names
firstNameFile = open('dataFiles\FirstNamesData.txt', 'r')
lastNameFile = open('dataFiles\LastNamesData.txt', 'r')
# builds values for the while statement and the return string
returnValue = ""
counter = 0
# builds the return string using a while loop and removing the newline character
# after each line from both files when being read
while counter < int(numberOfItemsNeed):
returnValue += str(firstNameFile.readline().strip("\n")
) + " " + str(lastNameFile.readline().strip("\n")) + "\n"
counter = counter + 1
# returns a list of "human" names in a single string divided by a newline character
return (returnValue)
def generateEmail(numberOfItemsNeed):
# opens a file containing a records of first names
firstNameFile = open('dataFiles\dictonary.txt', 'r')
counter = 0
# A list of commonly used email address suffixs
suffix = ['#gmail.com', '#gmail.ca', '#hotmail.com',
'#hotmail.ca', '#mail.com ', '#mail.ca', '#gov.ca']
returnValue = ""
while counter < int(numberOfItemsNeed):
returnValue += firstNameFile.readline().strip("\n") + \
str((random.randrange(0, 100))) + \
suffix[random.randrange(0, len(suffix))]+'\n'
counter = counter + 1
return (returnValue)
def generateCost(numberOfItemsNeed):
# generates a random item price in the inclusive range of 0.00$ to 1000.99$
counter = 0
cost = ""
while counter < int(numberOfItemsNeed):
cost += '$' + str(random.randrange(0, 1000)) + \
"." + str(random.randrange(0, 99)) + '\n'
counter = counter+1
return cost
def generateProduct(numberOfItemsNeed):
counter = 0
returnValue = ""
productList = open('dataFiles\itemData.txt', 'r')
while counter < int(numberOfItemsNeed):
returnValue += str(productList.readline()
).strip("\n") + str(generateCost(1))
counter = counter + 1
return (returnValue)
def generatePhoneNumber(numberOfItemsNeed):
counter = 0
returnValue = ""
while counter < int(numberOfItemsNeed):
firstNumber = str(random.randrange(100, 999))
secondNumber = str(random.randrange(1000, 9999))
thirdNumber = str(random.randrange(100, 999))
returnValue += firstNumber + "-" + secondNumber + "-" + thirdNumber + '\n'
counter = counter + 1
return (returnValue)
def shuffleFile(filePath):
lines = open(filePath).readlines()
random.shuffle(lines)
open(filePath, 'w').writelines(lines)
# shuffleFile('dataFiles\dictonary.txt')
Text widget indexes are strings of the form line.character with lines starting at 0 and characters starting at 1. So, to insert at the start you need to use the index "1.0", not 0. If you want to insert at the end you can use the special index "end". If the widget is empty, "1.0" and "end" yield identical results.
outputToScreen.insert("1.0", outputToFile)
Related
I'm making a user interface but my for loop is not working. i wanted to say somthing when th username was alredy used butmy code yust skips the for loop and then append the username and password to the list. in the txt file stand in each line username;password
import tkinter as tk
from tkinter import *
root = Tk()
root.title("WRTS oefentoets")
root.geometry("735x355")
def sign():
userfile = open("users.txt", "a+")
users = list(userfile.readlines())
found = 0
for line in users:
parts = line.split(";")
if parts[0] == username.get():
found = 1
break;
if found == 1:
bestaatal.place(x= 300, y= 200)
else:
with open('users.txt', "a+") as file_object:
# Move read cursor to the start of file.
file_object.seek(0)
# If file is not empty then append '\n'
data = file_object.read()
if len(data) > 0:
file_object.write("\n")
# Append text at the end of file
file_object.write(username.get() + ";" + password.get())
username = Entry(root, bg = 'black', fg = 'magenta')
password = Entry(root, bg = 'black', fg = 'magenta')
signin = Button(root, bg = 'black', fg = 'magenta', text = 'sign up', command = sign, width = 7)
signin.place(x= 343, y= 181)
username.place(x=262.5, y= 135)
password.place(x=262.5, y= 157.5)
.readlines on a file in append mode starts reading from the end of that file
So, since from userfile you're only reading, just open it in read mode:
with open("users.txt", 'r') as userfile:
... # your code
I'm making a typing speed test and hope when I click space (on_space function) that I could check the user's input with the word list and also delete the typed words in the word list. However, I'm having trouble that the checking and deleting condition is not looping rather than stopping after the 1st word. The issue either be the variable wpm (the word per minute) is not defined when execute at the time the countdown stop or the wpm is always 1, which retains the 1st value typed.
from tkinter import *
import random
import csv
import sys
import time
window = Tk()
# setting tkinter window size
window.state("zoomed")
window.update_idletasks()
window.configure(bg="gray")
window.title("Typing Test")
# opens csv file and converts to list for data management
with open("typingwords.csv", "r") as read_obj: # read csv file as a list of lists
csv_reader = csv.reader(read_obj)
wordList = list(csv_reader)
# Randomizes the list and splices it to only have 150 words
random.shuffle(wordList)
splicedlist = wordList[:150]
# displays the words
fontTuple = ("Playfair Display", 16, "bold")
x1 = Label(window, text=splicedlist, wraplength=1100, fg="white")
x1.config(bg="gray")
x1.config(font=fontTuple)
x1.pack(ipadx=500, ipady=20)
# defines the function used to delete the inside of entry after every space
typedValue = []
def on_space(e1):
global typedValue
global wpm
x = " ".join(splicedlist.pop(0)) # after the word is being typed
if e1.widget.get() != x:
e1.widget.delete(0, "end")
x1.config(text=splicedlist)
pass
else:
typedValue.append(x)
wpm = len(typedValue)
print(wpm)
e1.widget.delete(0, "end")
x1.config(text=splicedlist)
# Timer
sec = int(60)
time = str(f"00:{sec}")
c1 = Label(window, text=time, wraplength=500, fg="white")
c1.config(bg="gray")
c1.config(font=fontTuple)
c1.pack(ipadx=500, ipady=200)
def countdown(count):
if count > 0:
window.after(1000, countdown, count - 1)
c1.config(text=count)
if count == 0:
sys.exit(f"Time's Up! Your words per minute is {wpm}")
fontTuple = ("Playfair Display", 16, "bold")
e1 = Entry(window)
e1.config(font=fontTuple)
e1.bind("<space>", on_space)
e1.bind("<Button-1>", countdown(60))
e1.pack()
window.mainloop()
i'm very new to Tkinter but i tried to read all the documentation that i could and could not understand if i'm heading in the right direction or not.
Firstly, thank you for reading this.
In summary i'm trying to create a Text Editor with Tkinter. This text editor however must display the exact same file for every user which opens it in the same private network as it is to be used as a display Panel in order for everyone to be able to read anyone else's notices.
I Have still a lot to do but where i'm blocking right now and couldn't find an answer for is to be able to store the configurations changes that are applied to the text (Bold, color etc..)
the text itself is stored in a txt file that is automatically opened at the start of the program but i don't know a way to store the color and font style.
To apply the font and color to the text i use a counter that i apply to each tag change that is done (so the first area selection that will be changed will be named "colortag1" the second "colortag2" etc ..)
I don't know if it is possible to keep theses tags configurations and the count of my variable "counter" stored without reseting everything.
Would someone possibly have an idea?
I'm really sorry if it's not very understandable.
Here is my code:
import tkinter
import os
from tkinter import *
from tkinter.messagebox import *
from tkinter.filedialog import *
class Notepad:
#Creation of a Notepad Class
__root = Tk()
__countG = 1
__thisWidth = 300
__thisHeight = 300
__thisTextArea = Text(__root)
__thisMenuBar = Menu(__root)
__thisFileMenu = Menu(__thisMenuBar, tearoff=0)
__thisEditMenu = Menu(__thisMenuBar, tearoff=0)
__thisScrollBar = Scrollbar(__thisTextArea)
#The file that is always opened by the notepad
__file = "//srvad/echange/Python panel/paneltest.txt"
__thisTextArea.configure(font=("arial", "12" ,"normal"))
def __init__(self, **kwargs):
try:
self.__root.wm_iconbitmap("Notepad.ico")
except:
pass
try:
self.__thisWidth = kwargs['width']
except KeyError:
pass
try:
self.__thisHeight = kwargs['height']
except KeyError:
pass
#Creation of Edit Cascade
self.__thisMenuBar.add_cascade(label="Edit",
menu=self.__thisEditMenu)
#Name of the text editor
self.__root.title("Home Panel")
#Size and settings of the Notepad
screenWidth = self.__root.winfo_screenwidth()
screenHeight = self.__root.winfo_screenheight()
left = (screenWidth / 2) - (self.__thisWidth / 2)
top = (screenHeight / 2) - (self.__thisHeight / 2)
self.__root.geometry('%dx%d+%d+%d' % (self.__thisWidth,
self.__thisHeight,
left, top))
self.__root.grid_rowconfigure(0, weight=1)
self.__root.grid_columnconfigure(0, weight=1)
self.__thisTextArea.grid(sticky=N + E + S + W)
#Call of the Bold function
self.__thisEditMenu.add_command(label="Gras",font=("arial", "12", "bold"),
command=self.__gras)
self.__root.config(menu=self.__thisMenuBar)
self.__thisScrollBar.pack(side=RIGHT, fill=Y)
self.__thisScrollBar.config(command=self.__thisTextArea.yview)
self.__thisTextArea.config(yscrollcommand=self.__thisScrollBar.set)
file = open(self.__file, "r")
self.__thisTextArea.insert(1.0, file.read())
file.close()
#Bold function (the counter permit to generate a new tag name each time the function is called.
# The function check the counter number in order to decide if the text selection is in bold or normal font
# So the counter get +1 in one case an +2 in the other to differentiate them
def __gras(self):
sele=self.__thisTextArea.get(SEL_FIRST,SEL_LAST)
print (sele)
if self.__thisTextArea.tag_ranges('sel'):
if "colortag" + str(self.__countG -1) in self.__thisTextArea.tag_names(SEL_FIRST):
self.__thisTextArea.tag_add('colortag' + str(self.__countG), SEL_FIRST, SEL_LAST)
print ("le texte est gras")
self.__thisTextArea.tag_configure('colortag' + str(self.__countG),font=("arial", "12", "normal"))
self.__countG +=2
else:
self.__thisTextArea.tag_add('colortag' + str(self.__countG), SEL_FIRST, SEL_LAST)
print ('le texte est en normal')
self.__thisTextArea.tag_configure('colortag' + str(self.__countG), font=("arial", "12", "bold"))
self.__countG += 1
else:
pass
def __quitApplication(self):
self.__root.destroy()
#Save function that save the actual text in a .txt file
def __saveFile(self):
if self.__file == None:
self.__file = asksaveasfilename(initialfile='Untitled.txt',
defaultextension=".txt",
filetypes=[("All Files", "*.*"),
("Text Documents", "*.txt")])
if self.__file == "":
self.__file = None
else:
file = open(self.__file, "w")
file.write(self.__thisTextArea.get(1.0, END))
file.close()
self.__root.title(os.path.basename(self.__file) + " - Notepad")
else:
file = open(self.__file, "w")
file.write(self.__thisTextArea.get(1.0, END))
file.close()
def run(self):
self.__root.mainloop()
notepad = Notepad(width=600, height=400)
notepad.run()
'''
I recommend that you look into Pythons pickle functionality, there is no way to do what you want without saving the tags in a separate file or writing the tags into the file itself.
I want to make a GUI, which will take the data date entered by the user and pass it to a python script that would be executed when a button is pressed in the GUI. My code looks like this as of now:
import tkinter as tk
from tkinter.font import Font
from tkinter import *
from tkinter import filedialog, Text
import os
main_gui = tk.Tk()
main_gui.title("Widefield Analysis")
main_gui.geometry("600x500")
datadate = StringVar()
def data_date():
global ddate
ddate = datadate.get()
ddate_label.config()
return ddate
def image_files(ddate):
global varlist1
from Image_files import filepath, filepath2, list1, filelist2
varlist1 = [filepath, filepath2, list1, filelist2]
return varlist1
ddate_label = Label(main_gui, text='Enter Data Date', font='Ariel 13 bold')
ddate_label.pack()
ddate_label.place(x=20, y=13)
date = tk.Entry(main_gui, textvariable=datadate, font='Ariel 13 normal', width=10)
date.place(x=205, y=10)
button1 = tk.Button(main_gui, text="Done", font="Ariel 13 bold", command=lambda:[data_date(), image_files(ddate)])
button1.place(x=500, y=450)
main_gui.mainloop()
The main idea is to take the datadate entered by the user and feed it to the Image_files.py script (which is a part of the image_files function, that gets executed when the "Done" button gets pressed). From the Image_files.py script, I need to return these variables: filepath, filepath2, list1, filelist2, which will later be used for other scripts being run in the same GUI. I am unable to do it now and need help.
I'm providing the code for the Image_files.py script here as well:
#THIS CODE PRECEEDS THE Image_stack.py CODE
import os
#datadate = input("Enter data date: ")
datadate = "17032020"
filepath = ("/home/abhra/Documents/My_first_code/" + datadate)
os.chdir(filepath)
#print("Current Working Directory ", os.getcwd()) **TO KNOW WHAT IS THE CURRENT WORKING DIRECTORY**
filelist = os.listdir()
filecount = 0
#CREATES ARRAY FOR TSERIES FILES
for x in range (0,len(filelist),1):
aa = filelist[x].startswith("TSeries")
if aa == True:
filecount = filecount + 1
list1 = [0] * filecount
counter=0
for y in range (0,len(filelist),1):
bb = filelist[y].startswith("TSeries")
if bb == True:
list1[counter] = filelist[y]
counter = counter+1
del aa, bb, x, y
list1.sort() #good initial sort but doesnt sort numerically very well
sorted(list1) #sort numerically in ascending order
#IMPORT STUFF FROM .mat FILE FROM PP_FILES
filepath2 = ("/home/abhra/Documents/My_first_code/" + datadate + "/" + "PP_FILES")
os.chdir(filepath2)
filelist2 = os.listdir()
filelist2.sort()
sorted(filelist2)
os.chdir("/home/abhra/Documents/My_first_code/")
I am trying to make it so that the variable fpl is set when the button (command submit) is used. The problem is, it runs through the entire thing before the user has hit the button. How do i make it so the script beginning?
#Convert string to list
fpl = fpl.replace(" " , ".")
Is only run once the user has pressed the button? Rest of the code below.
import json
from tkinter import *
def submit():
fpl = entry.get()
window = Tk()
window.title ("Infinite FMS")
Label (window, text="Enter your flight plan
here:").grid(row=0,column=0,sticky=W)
entry = Entry(window, width = 75, bg = "light blue")
entry.grid(row=1,column=0,sticky=W)
Button (window, text="Submit",
command=submit).grid(row=2,column=0,sticky=W)
output = Text(window,width=75,height=6,background="light
blue")
output.grid(row=3,column=0,sticky=W)
#Convert string to list
fpl = fpl.replace(" " , ".")
"[" + fpl + "]"
fpllist = fpl.split(".")
#Length of fpllist
fpllen = len(fpllist)
#Loop through the flight plan missing first and last
entries
n = 1
Invalid = []
while n < fpllen - 1:
#Check for item in file
searchTerm = (fpllist[n])
searchTermF = "\'Name\': \'" + searchTerm + "\'"
searchTermV = "\'identifier\': \'" + searchTerm + "\'"
file = open('mydirectory', 'r')
data1 = json.load(file)
file.close()
file = open('mydirectory', 'r')
data2 = json.load(file)
file.close()
if searchTermF in str(data1):
Validity = "Your route is valid!"
n = n + 1
elif searchTermV in str(data2):
Validity = "Your route is valid!"
n = n + 1
else:
Validity = "Your route is invalid!\nInvalid
waypoints:"
Invalid.append(searchTerm)
n = n + 1
if len(Invalid) == 0:
print (Validity , ', '.join(Invalid))
else:
Validity = "Your route is invalid!\nInvalid
waypoints:"
print (Validity , ', '.join(Invalid))
output.delete(0.0, END)
output.insert(END, (Validity , ', '.join(Invalid)))
As PM 2Ring said if you put this
#Convert string to list
fpl = fpl.replace(" " , ".")
"[" + fpl + "]" #what is this supposed to do?
fpllist = fpl.split(".")
#Length of fpllist
fpllen = len(fpllist)
in your submit function it will be run when you click the button.
Also you don't need to replace the spaces with points fpllist = fpl.split() will give you the same result.
And you should really learn OOP(google it if you don't know what it is) it will make your program more readable and you can split diffrent parts of your program in diffrent functions.