4
\$\begingroup\$

Module: https://amueller.github.io/word_cloud/

I really enjoyed the python WordCloud module, so I wanted to give it a GUI so I could share it with family and friends. I also wanted a platform where one could generate their own WordClouds within their own pictures, without word limitations (like many of the online wordcloud programs).

The GUI provides a number of options to modify the WordCloud, and instructions are presented via a tooltip. I've also added some additional advanced options (things I think might be a bit less intuitive, but are still there if the user wants to modify them).

I'm basically looking for feedback on my code structure, and specifically how I implement modifications of the various arguments. This is my first time making a window within a window in Tkinter, and I had to use various globals to try and get it to work properly (which I know is a big no no).

#main.py import tkinter as tk import numpy as np import matplotlib.pyplot as plt import os from wordcloud import WordCloud,STOPWORDS from collections import Counter from PIL import Image as img from tkinter import filedialog from tkinter import * from collections import Counter import traceback root = tk.Tk() root.title('Word Cloud Generator') root.geometry('600x600') class CreateToolTip(object): """ create a tooltip for a given widget """ def __init__(self, widget, text='widget info'): self.waittime = 100 #miliseconds self.wraplength = 280 #pixels self.widget = widget self.text = text self.widget.bind("<Enter>", self.enter) self.widget.bind("<Leave>", self.leave) self.widget.bind("<ButtonPress>", self.leave) self.id = None self.tw = None def enter(self, event=None): self.schedule() def leave(self, event=None): self.unschedule() self.hidetip() def schedule(self): self.unschedule() self.id = self.widget.after(self.waittime, self.showtip) def unschedule(self): id = self.id self.id = None if id: self.widget.after_cancel(id) def showtip(self, event=None): x = y = 0 x, y, cx, cy = self.widget.bbox("insert") x += self.widget.winfo_rootx() + 25 y += self.widget.winfo_rooty() + 20 # creates a toplevel window self.tw = tk.Toplevel(self.widget) # Leaves only the label and removes the app window self.tw.wm_overrideredirect(True) self.tw.wm_geometry("+%d+%d" % (x, y)) label = tk.Label(self.tw, text=self.text, justify='left', background="#ffffff", relief='solid', borderwidth=1, wraplength = self.wraplength) label.pack(ipadx=1) def hidetip(self): tw = self.tw self.tw= None if tw: tw.destroy() label0=tk.Label(root, text="Hover over line for instructions") label0.grid(row=0) label1=tk.Label(root, text="Load File") label1.grid(row=1) label1_tooltip=CreateToolTip(label1,'Load a text file containing your words') label2=tk.Label(root, text="Words") label2.grid(row=2) label2_tooltip=CreateToolTip(label2,'Type in the words you want in your wordcloud, the more words, the better the word cloud will look. \n Words are case-sensitive (i.e. The is different form the)\n Separate words with space') label3=tk.Label(root, text="Frequency of word") label3.grid(row=3) label3=CreateToolTip(label3,'This signifies the size of the above words. The more frequent a word, the larger it will be.\n Type in a number that represents the size of the word \n' 'The larger the number, the larger the word. I.E. Family Love Health in order of size, would be 200 100 50') label4=tk.Label(root, text="Background Color") label4.grid(row=4) label4=CreateToolTip(label4,'Background Color of the Word Cloud, Default is white') label5=tk.Label(root, text="Wordcloud Width") label5.grid(row=5) label5=CreateToolTip(label5,'The higher this number, the better the resolution of the words within your word cloud. Default is 400') label6=tk.Label(root, text="Wordcloud Height") label6.grid(row=6) label6=CreateToolTip(label6,'Same as the width. Default is 400') label7=tk.Label(root, text="Window Width") label7.grid(row=7) label7=CreateToolTip(label7,'Size of the WordCloud picture. \nThe higher the number, the larger the figure. Default is 5') label8=tk.Label(root, text="Window Height") label8.grid(row=8) label8=CreateToolTip(label8,'Same as width. Default is 5') label9=tk.Label(root, text="Words not to use") label9.grid(row=9) label9=CreateToolTip(label9,'A list of words to ignore. \nSeparate multiple words with space. I.E. Hello Goodbye.\nWords are case-sensitive (i.e. The is different form the)') tk.Label(root, text="Image Options").grid(row=10) label10=tk.Label(root, text="Load Image") label10.grid(row=11) label10=CreateToolTip(label10,'Image to insert the wordcloud into. \n Use photos that have a white background, and black filling where you want the words to be in.') label11=tk.Label(root, text="Image Outline Thickness") label11.grid(row=12) label11=CreateToolTip(label11,'This defines the outline of the image. Default is 3') label12=tk.Label(root, text="Image Outline Color") label12.grid(row=13) label12=CreateToolTip(label12,'The color of the outline. Default is black') load_file=tk.Entry(root) load_file.grid(row=1, column=1,sticky=W) word_list=tk.Entry(root) word_list.grid(row=2, column=1,ipadx=100,sticky=W+E) multiplyer=tk.Entry(root) multiplyer.grid(row=3, column=1,ipadx=100,sticky=W+E) background_color_input=tk.Entry(root) background_color_input.grid(row=4,column=1,sticky=W) width_input=tk.Entry(root) width_input.grid(row=5,column=1,sticky=W) height_input=tk.Entry(root) height_input.grid(row=6,column=1,sticky=W) window_width_input=tk.Entry(root) window_width_input.grid(row=7,column=1,sticky=W) window_height_input=tk.Entry(root) window_height_input.grid(row=8,column=1,sticky=W) stopwords_input=tk.Entry(root) stopwords_input.grid(row=9,column=1,sticky=W) image_input=tk.Entry(root) image_input.grid(row=11,column=1,sticky=W) contour_width_input=tk.Entry(root) contour_width_input.grid(row=12,column=1,sticky=W) contour_color_input=tk.Entry(root) contour_color_input.grid(row=13,column=1,sticky=W) text=() text_directory=() image=() image_directory=() def input_file(): fullpath = filedialog.askopenfilename(parent=root, title='Choose a file') global text_directory global text text_directory=os.path.dirname(fullpath) text= os.path.basename(fullpath) label2=Label(root,text=fullpath).grid(row=1,column=1,sticky=W) def image_file(): fullpath = filedialog.askopenfilename(parent=root, title='Choose a file') global image global image_directory image_directory=os.path.dirname(fullpath) image= os.path.basename(fullpath) label2=Label(root,text=fullpath).grid(row=11,column=1,sticky=W) new_top_flag=False new_top=None def run(): print('Program is Running') try: global new_top stopwords = set(STOPWORDS) width_value,height_value,background_colors,contour_color,contour_width,stopwords,window_width,window_height = defaults(stopwords) if new_top_flag != False: max_words,min_font_size,max_font_size,mode,relative_scaling=new_top.values() else: max_words,min_font_size,max_font_size,mode,relative_scaling=200,4,None,'RGB','auto' if word_list.get() != '': inputed_words=[] words_typed=word_list.get() multiplyer_value=multiplyer.get() for words,number in zip(words_typed.split(),multiplyer_value.split()): inputed_words+=((words+',')*int(number)).split(',') word_could_dict=Counter(inputed_words) if image == (): wc= WordCloud(width=width_value, height=height_value,background_color=background_colors,stopwords=stopwords,max_words=max_words,min_font_size=min_font_size,max_font_size=max_font_size,mode=mode,relative_scaling=relative_scaling).generate_from_frequencies(word_could_dict) else: os.chdir(image_directory) new_mask=np.array(img.open(image)) wc= WordCloud(width=width_value, height=height_value,background_color=background_colors,stopwords=stopwords,mask=new_mask,contour_color=contour_color,contour_width=contour_width,max_words=max_words,min_font_size=min_font_size,max_font_size=max_font_size,mode=mode,relative_scaling=relative_scaling).generate_from_frequencies(word_could_dict) wc.to_file('savefile.png') plt.figure(figsize = (window_width,window_height)) plt.imshow(wc, interpolation="bilinear") plt.tight_layout(pad=0) plt.axis("off") plt.show() else: os.chdir(text_directory) text_file = (open(text,encoding="utf8" ).read()).lower() if image ==(): wc= WordCloud(width=width_value, height=height_value,background_color=background_colors,stopwords=stopwords,max_words=max_words,min_font_size=min_font_size,max_font_size=max_font_size,mode=mode,relative_scaling=relative_scaling).generate(text_file) else: os.chdir(image_directory) new_mask=np.array(img.open(image)) wc= WordCloud(width=width_value, height=height_value,background_color=background_colors,stopwords=stopwords,mask=new_mask,contour_color=contour_color,contour_width=contour_width,max_words=max_words,min_font_size=min_font_size,max_font_size=max_font_size,mode=mode,relative_scaling=relative_scaling).generate(text_file) wc.to_file('savefile.png') plt.figure(figsize = (window_width,window_height)) plt.imshow(wc, interpolation="bilinear") plt.tight_layout(pad=0) plt.axis("off") plt.show() new_top=None except: print('Error Running Program. Report below error report\n') traceback.print_exc() def defaults(stopwords): if width_input.get() == '': width_value=400 else: width_value=int(width_input.get()) if height_input.get() == '': height_value=400 else: height_value=int(height_input.get()) if stopwords_input.get() != '': for values in (stopwords_input.get()).split(): stopwords.add(values) if background_color_input.get() == '': background_colors='white' else: background_colors=background_color_input.get() if contour_color_input.get() == '': contour_color='black' else: contour_color=contour_color_input.get() if contour_width_input.get() == '': contour_width=3 else: contour_width=int(contour_width_input.get()) if window_width_input.get() == '': window_width = 5 else: window_width=int(window_width_input.get()) if window_height_input.get() == '': window_height=5 else: window_height=int(window_height_input.get()) return width_value,height_value,background_colors,contour_color,contour_width,stopwords,window_width,window_height def new_window(): global new_top global new_top_flag from advanced import newTopLevel new_top = newTopLevel(root) new_top_flag=True newWindow = new_top.newWindow tk.Button(root,text='browse',command=input_file).grid(row=1,column=2) tk.Button(root,text='browse',command=image_file).grid(row=11,column=2) tk.Button(root,text='Advanced Settings',command=new_window).grid(row=34,column=1) tk.Button(root,text='run',command=run).grid(row=14,column=1,sticky=W) root.mainloop() 
#advanced.py from tkinter import * import tkinter as tk class CreateToolTip(object): """ create a tooltip for a given widget """ def __init__(self, widget, text='widget info'): self.waittime = 100 #miliseconds self.wraplength = 280 #pixels self.widget = widget self.text = text self.widget.bind("<Enter>", self.enter) self.widget.bind("<Leave>", self.leave) self.widget.bind("<ButtonPress>", self.leave) self.id = None self.tw = None def enter(self, event=None): self.schedule() def leave(self, event=None): self.unschedule() self.hidetip() def schedule(self): self.unschedule() self.id = self.widget.after(self.waittime, self.showtip) def unschedule(self): id = self.id self.id = None if id: self.widget.after_cancel(id) def showtip(self, event=None): x = y = 0 x, y, cx, cy = self.widget.bbox("insert") x += self.widget.winfo_rootx() + 25 y += self.widget.winfo_rooty() + 20 # creates a toplevel window self.tw = tk.Toplevel(self.widget) # Leaves only the label and removes the app window self.tw.wm_overrideredirect(True) self.tw.wm_geometry("+%d+%d" % (x, y)) label = tk.Label(self.tw, text=self.text, justify='left', background="#ffffff", relief='solid', borderwidth=1, wraplength = self.wraplength) label.pack(ipadx=1) def hidetip(self): tw = self.tw self.tw= None if tw: tw.destroy() max_words=0 min_font_size=0 max_font_size=0 mode=0 relative_scaling=0 class newTopLevel(object): def __init__(self, root): self.newWindow = Toplevel(root) self.newWindow.title("Advanced") self.newWindow.geometry("400x400") label1=tk.Label(self.newWindow, text="Max words") label1.grid(row=0) label1_tooltip=CreateToolTip(label1,'The maximum number of words. Default is 200') label2=tk.Label(self.newWindow, text="Min Font Size") label2.grid(row=1) label2_tooltip=CreateToolTip(label2,'The smallest font size to use. Word Cloud will not generate any words smaller than this \n Default is 4') label3=tk.Label(self.newWindow, text="Max Font Size") label3.grid(row=2) label3_tooltip=CreateToolTip(label3,'The maximum font size for the largest word') label4=tk.Label(self.newWindow, text="Mode") label4.grid(row=3) label4_tooltip=CreateToolTip(label4,'If a transparent background is desired, type in RGBA, and change the background to None') label5=tk.Label(self.newWindow, text="Relative Scaling") label5.grid(row=4) label5_tooltip=CreateToolTip(label5,'A scale of 0, only word ranks are considered. A scale of 1,the more frequent word will be 2x the size as before.\n A scale of 0.5 uses word frequencies and rank. Defaulse is 0.5') self.max_word_input=tk.Entry(self.newWindow) self.max_word_input.grid(row=0,column=1) self.min_font_input=tk.Entry(self.newWindow) self.min_font_input.grid(row=1,column=1) self.max_font_input=tk.Entry(self.newWindow) self.max_font_input.grid(row=2,column=1) self.mode_input=tk.Entry(self.newWindow) self.mode_input.grid(row=3,column=1) self.scaling_input=tk.Entry(self.newWindow) self.scaling_input.grid(row=4,column=1) tk.Button(self.newWindow,text='Apply Settings',command=self.input_values).grid(row=7,column=1) tk.Button(self.newWindow,text='Restore Default',command=self.input_values).grid(row=7,column=2) def input_values(self): global max_words global min_font_size global max_font_size global mode global relative_scaling if self.max_word_input.get() == '': max_words=200 else: max_words=int(self.max_word_input.get()) if self.min_font_input.get() == '': min_font_size=4 else: min_font_size=int(self.min_font_input.get()) if self.max_font_input.get() == '': max_font_size=None else: max_font_size=int(self.max_font_input.get()) if self.mode_input.get() == '': mode='RGB' else: mode=self.mode_input.get() if self.scaling_input.get() == '': relative_scaling='auto' else: relative_scaling=float(self.scaling_input.get()) def values(self): return max_words,min_font_size,max_font_size,mode,relative_scaling 
\$\endgroup\$

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.