Python Tkinter TextEditor how to save configuration changes - python

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.

Related

storing output text in a tkinter textbox

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)

Why does my if statement doesn't repeat when the condition is met?

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()

Cannot pass the entered variable from a function to a .py script

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/")

Python Tkinter return self.func(*args) and TypeError:list indices must be integers or slices, not str

The goal is to extract excel data and write it to a text file, based on an input through tkinter. The Tkinter box is popping up, but when the entry input is given, it produces an error in the terminal.
I have tried changing the line 30 int or float.
Thank you for any help you can give.
The code below is creating this error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\bob\AppData\Local\Programs\Python\Python37-
32\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "c:/Users/bob/Dropbox/Financial/PERSONAL FINANCES/budget.py",
line 30, in click
result = np.array(sheet.cell_value(i,budget_col))
File "C:\Users\bob\AppData\Local\Programs\Python\Python37-
32\lib\site-packages\xlrd\sheet.py", line 419, in cell_value
return self._cell_values[rowx][colx]
TypeError: list indices must be integers or slices, not str
My code:
import os
from tkinter import *
import time
import xlrd
import numpy as np
os.system('cls' if os.name == 'nt' else 'clear')
def click():
file_location = 'C:/Users/bob/Dropbox/Financial/PERSONAL FINANCES/NEW DOUBLE ENTRY PERSONAL.xlsx'
workbook = xlrd.open_workbook(file_location)
sheet = workbook.sheet_by_index(6)
budget_col = textentry.get()
excel_col1 = np.array([])
array_length = sheet.nrows
for i in range(array_length):
result = np.array(sheet.cell_value(i,0))
excel_col1 = np.append(excel_col1,[result])
excel_col2 = np.array([])
for i in range(array_length): # 0 to total rows
result = np.array(sheet.cell_value(i,1))
excel_col2 = np.append(excel_col2,[result])
excel_col_bud_col = np.array([])
for i in range(array_length): # 0 to total rows
result = np.array(sheet.cell_value(i,budget_col))
excel_col_bud_col = np.append(excel_col_bud_col,[result])
#Writing text file to desktop
# CREATING THE textfile:
created_name = '\curr_budget.txt'
if os.name == 'nt':
desktop = str(os.path.join(os.path.join(os.environ['USERPROFILE']), 'Desktop'))
query_if_windows = "windows"
else:
desktop = str(os.path.join(os.path.join(os.path.expanduser('~')), 'Desktop'))
query_if_windows = "not windows"
filename = desktop + created_name
text_file = open(filename,"w")
text_file.write(time.strftime("%c\n"))
text_file.write("\n")
text_file.write('Accounts - Budget\n')
text_file.write("\n")
for n in range(4,sheet.nrows-2):
x = excel_col_bud_col[n]
y = excel_col2[n]
z = excel_col1[n]
text_file.write(z + " " + x + " " + y)#,"{bud:8.8} {name}".format(name=y,bud=x))
text_file.write("\n")
text_file.write("\n")
text_file.write('Note, some debit card transactions will take a few days so will not appear above\n')
text_file.close()
window = Tk()
window.title("Print Budget to Desktop")
window.configure(background="white")
Label (window,text="Enter column across, starting at 0, where this month's budget is located", bg="white", fg = "black", font="none 12 bold") .grid(row=0, column=0, sticky=W)
textentry = Entry(window, width=20,bg="white") #column '15' for August budget (starts at 0)
textentry.grid(row=1,column=0,sticky=W)
Button(window, text="Print Budget to Desktop",width=23,command=click) .grid(row=2,column=0,sticky=W)
window.mainloop()
The error telling you precisely what the problem is. It is saying you need to pass an integer rather than a string to a particular function. That is happening because of these two lines:
budget_col = textentry.get()
...
result = np.array(sheet.cell_value(i,budget_col))
budget_col is a string, but sheet.cell_value requires an integer. You need to convert the value you get from textentry.get() to an integer before you can pass it to that function.

Python 3.3 TKinter image doesn't exist

I am trying to open an image with ImageTk.PhotoImage from PIL but I keep hitting the same error. I have the image and can see that it is there when it downloads it, it opens it, but then I get the error that it is not there.
Here is the error
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python33\lib\tkinter\__init__.py", line 1475, in __call__
return self.func(*args)
File "S:/Projects/xmlParser.py", line 128, in updateSelected
self.threadLabelImage.config(text = self.threadImage)
File "C:\Python33\lib\tkinter\__init__.py", line 1263, in configure
return self._configure('configure', cnf, kw)
File "C:\Python33\lib\tkinter\__init__.py", line 1254, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: image "pyimage1" doesn't exist
Relevant Code
if self.threadLinkList[self.y].find('imgur') != -1:
url = self.threadLinkList[self.y]+'.gif'
imageName=self.threadLinkList[self.y][-11:-4]+'.gif'
print(imageName)
urllib.request.urlretrieve(self.threadLinkList[self.y],imageName)
imgfile = Image.open(imageName)
imgfile = imgfile.resize((150,150),Image.ANTIALIAS)
# img = Image.open(file)
print(imgfile)
self.threadImage = ImageTk.PhotoImage(imgfile)
self.threadLabelImage.config(text = self.threadImage)
self.threadImage.image = imgfile
Entire program to run.
import xml.etree.ElementTree as ET
import webbrowser,time,urllib.request,re,os
import tkinter as tk
import urllib
from PIL import Image,ImageTk
main = tk.Tk()
os.getcwd()
class Application(tk.Frame):
def __init__(self, master=None):
self.threadTitle = tk.StringVar()
self.threadAuth = tk.StringVar()
self.threadPub = tk.StringVar()
self.threadArtLink = tk.StringVar()
self.threadLink = tk.StringVar()
self.threadImg = tk.StringVar()
self.threadArtLink.set('Click something to display thread info')
photo = Image.open("temp.png")
photo = photo.resize((150,150), Image.ANTIALIAS)
self.threadImage = ImageTk.PhotoImage(photo)
# Intializes tkinter gui framework
tk.Frame.__init__(self, master)
# Packs widgets needed
self.grid()
# Creates the widgets functions
self.createWidgets()
# Intializes the man rss.xml
self.initial()
# self.threadLabelArtLink = None
# self.threadLabelTitle = None
# self.threadLabelThreadLink = None
# self.threadLabelArtLink = None
# self.threadImgLink = None
def createWidgets(self):
# Create entrybox and align to grid
self.send_entry = tk.Entry(self)
self.send_entry.grid(row=0,column=0)
# Create button,allign to grid, get xml
self.change_sub = tk.Button(self,text='Change Subreddit',padx=5, pady=5, command=lambda :self.getXML(self.send_entry.get()))
self.change_sub.grid(row=0 , column=3)
# Create scrollbar on Y-Axis
self.lb_scrollY = tk.Scrollbar(self,orient=tk.VERTICAL)
# On grid next to Listbox(sticky means fill whole row
self.lb_scrollY.grid(row=1,column=4,sticky=tk.NS,rowspan=6)
# Create Listbox and get Y from scrollbar
self.thread_lb = tk.Listbox(self,yscrollcommand=self.lb_scrollY.set,height=20)
# Calls function whenever a new item is selected & open thread if double click 1
self.thread_lb.bind('<<ListboxSelect>>',self.updateSelected)
self.thread_lb.bind('<Double-Button-1>',self.openPage)
# scrolly will change the view of listbox
self.lb_scrollY['command']=self.thread_lb.yview
self.thread_lb.grid(row=1,column=0,sticky=tk.NS+tk.EW,columnspan=4)
self.threadFrame = tk.LabelFrame(main,text='Reddit',width=450,height=350,labelanchor='n')
self.threadLabelTitle = tk.Label(self.threadFrame,textvariable=self.threadTitle,wraplength=400,padx=20, pady=5)
self.threadLabelTitle.grid(row=1,column=10,sticky= tk.EW)
self.threadLabelAuth = tk.Label(self.threadFrame, textvariable=self.threadAuth,wraplength=400,padx=20, pady=5)
self.threadLabelAuth.grid(row=2,column=10,sticky = tk.EW)
self.threadLabelPub = tk.Label(self.threadFrame, textvariable=self.threadPub,wraplength=400,padx=20, pady=5)
self.threadLabelPub.grid(row=3,column=10,sticky = tk.EW)
self.threadLabelArtLink = tk.Label(self.threadFrame, textvariable=self.threadArtLink,wraplength=400,padx=20, pady=5)
self.threadLabelArtLink.grid(row=4,column=10,sticky = tk.EW)
self.threadLabelThreadLink = tk.Label(self.threadFrame, textvariable=self.threadLink,wraplength=400,padx=20, pady=5)
self.threadLabelThreadLink.grid(row=5,column=10,sticky = tk.EW)
self.threadImgLink = tk.Label(self.threadFrame, textvariable=self.threadImg,wraplength=400,padx=20, pady=5)
self.threadImgLink.grid(row=6,column=10,sticky = tk.EW)
self.threadLabelImage = tk.Label(self.threadFrame,image=self.threadImage,wraplength=400,padx=20,pady=5)
self.threadLabelImage.grid(row=7,column=10,sticky = tk.EW)
self.threadFrame.grid(row=0,column=10,sticky=tk.EW,rowspan=8)
self.QUIT = tk.Button(self, text="QUIT", fg="red", command=main.destroy,padx=5, pady=5)
self.QUIT.grid(row=7)
self.threadFrame.grid_propagate(0)
def updateSelected(self, event):
# getting selected listbox item
i=self.thread_lb.curselection()
# Returns tuple that must be split
x,self.y,z = re.split("\D+",str(i))
self.y=int(self.y)
print(self.threadTitleList[self.y])
print(self.threadPubDateList[self.y])
print(self.threadLinkList[self.y])
print(self.threadDescList[self.y])
self.threadTitle.set(self.threadTitleList[self.y])
self.threadAuth.set(self.threadAuthList[self.y])
self.threadPub.set(self.threadPubDateList[self.y])
self.threadArtLink.set(self.threadLinkList[self.y])
self.threadLink.set(self.threadDescList[self.y])
# self.threadImg.set('Will put image here')
if self.threadLinkList[self.y].find('imgur') != -1:
url = self.threadLinkList[self.y]+'.gif'
imageName=self.threadLinkList[self.y][-11:-4]+'.gif'
print(imageName)
urllib.request.urlretrieve(self.threadLinkList[self.y],imageName)
imgfile = Image.open(imageName)
imgfile = imgfile.resize((150,150),Image.ANTIALIAS)
# img = Image.open(file)
print(imgfile)
self.threadImage = ImageTk.PhotoImage(imgfile)
self.threadLabelImage.config(text = self.threadImage)
self.threadImage.image = imgfile
# # threadTitle = self.threadTitleList[y]
# print(self.threadLabelTitle["text"])
# # self.threadLabelTitle['text']=threadTitle
# self.threadLabelAutPub['text']=self.threadPubDateList[y]
# self.threadImgLink['text']=self.threadLinkList[y]
# self.threadLabelThreadLink['text']=self.threadDescList[y]
# main.update()
def openPage(self,event):
webbrowser.get('windows-default').open_new(self.threadLinkList[self.y])
def descStripper(self,desc):
# Intialize values
l1,l2,l2Start = 0,0,0
t1,t2,t2start = 0,0,0
link = ""
thread = ""
# Where to start looking for each in description element
l1=int(desc.find('<br/> <a href="'))
t1=int(desc.find('</a> <a href="'))
a1=int(desc.find('"> '))
# If both of the tags are found then continue
if l1 != -1 and t1 != -1 and a1 != 1:
# Start looking for end of quotes 16 characters from beginning of tag
l2Start = l1+16
l2=int(desc.find('"',l2Start))
# Link is created from what is in the quotes
link = desc[l1+15:l2]
# Same as above but to find thread link
t2start = t1+15
t2=int(desc.find('"',t2start))
thread = desc[t1+14:t2]
a2start = a1+4
a2 = int(desc.find(' <',a2start))
author = desc[a1+3:a2]
return link,thread,author
else:
# If it can't find one it will return an error
link = "Couldn't find the stuff :("
thread = "Couldn't find the thread link :("
return link, thread
def lbPopulator(self,title,pub,link):
# Delete old entries from listbox
self.thread_lb.delete(0,tk.END)
# Iterate through all the items and append them to the listbox
for item in title:
self.thread_lb.insert(tk.END,item)
def getXmlData(self):
# Intialize lists
self.threadPubDateList = []
self.threadTitleList = []
self.threadLinkList = []
self.threadDescList = []
self.threadThumbNailList = []
self.threadAuthList = []
# Use the downloaded rss.xml for XML parsing
tree=ET.parse('rss.xml')
# define root as the base of the XML parsing tree
root=tree.getroot()
for channel in root:
# Iterate through all the channels
for SubChannel in channel:
# Iterate through all the items in the channel
if SubChannel.tag == 'item':
# If the SubChannel is called item then search for the items below
for threadInfo in SubChannel:
# iterate through all the items in the 'item'
if threadInfo.tag == 'title':
# append the tag from the title to the list
self.threadTitleList.append(threadInfo.text)
if threadInfo.tag == 'pubDate':
# Append the pubdate info to the list but remove excess characters
self.threadPubDateList.append(threadInfo.text[:-6])
if threadInfo.tag == 'description':
# Pass all the information from the description to the stripper to get the useful
# information and links
link,thread,author = self.descStripper(threadInfo.text)
self.threadLinkList.append(link)
self.threadDescList.append(thread)
self.threadAuthList.append(author)
# if threadInfo.tag == ''
# Populate the listbox with the newly generated lists
self.lbPopulator(self.threadTitleList,self.threadPubDateList,self.threadLinkList)
def getXML(self,subreddit):
try:
# Try to download the xml file using the user input subreddit
url = 'http://www.reddit.com'+subreddit+'.rss'
source = urllib.request.urlretrieve(url,'rss.xml')
self.getXmlData()
except urllib.error.HTTPError as err:
# Error caused by reddit API limiting connections
print('Too many requests-Try again')
def initial(self):
try:
# Same as above but downloads the front page
source = urllib.request.urlretrieve('http://www.reddit.com/.rss','rss.xml')
self.getXmlData()
except urllib.error.HTTPError as err:
print('Too many requests-Trying again 3')
# If error occurs program waits 3 seconds and then restarts
time.sleep(3)
self.__init__()
# main.geometry("350x400")
app = Application(master=main)
# Begins the applications GUI loop
app.mainloop()
I was attempting to apply the image to the text attribute of the label instaed of the image. Here is the fixed code.
url = self.threadLinkList[self.y]+'.gif'
imageName=self.threadLinkList[self.y][-11:-4]+'.gif'
print(imageName)
urllib.request.urlretrieve(self.threadLinkList[self.y],imageName)
imgfile = Image.open(imageName)
imgfile = imgfile.resize((150,150),Image.ANTIALIAS)
# img = Image.open(file)
print(imgfile)
self.threadImage = ImageTk.PhotoImage(imgfile)
self.threadLabelImage.config(***image*** = self.threadImage)
self.threadImage.image = imgfile

Categories