I'm new to Python and just started venturing into doing GUIs. I created a Tkinter window that is pretty basic: it has 3 Entry bars and 3 File Dialog buttons. When you chose the 3rd directory, the GUI file automatically makes a call to a separate file and receives a large text block which is then displayed in a Text box.
The whole thing works correctly, but my problem is that after receiving and inserting the text response, Tkinter stops working and doesn't allow the user to scroll down.
I read that one reason this happens is because people use both .pack( ) and .grid( ), but I'm not mixing those two functions.
Thanks in advance for any help!
Here's my GUI file
from tkinter import *
from tkinter import filedialog
from gui_GPSExtractor import *
import os
class Application(Frame):
def __init__(self, master):
""" Initialize Frame """
Frame.__init__(self, master)
self.grid( )
self.startGUI( )
""" Create Labels, Text Boxes, File Dialogs, and Buttons """
def startGUI(self):
# Label for Scan Path
self.dLabel = Label(self, text = "Scan Path")
self.dLabel.grid(row = 0, column = 0, columnspan = 2, sticky = W)
# Entry for Scan Path
self.dEntry = Entry(self, width = 60)
self.dEntry.grid(row = 1, column = 0, sticky = W)
# Button for Scan Path Directory Browse
self.dButton = Button(self, text = "Browse", command = lambda: self.browseFiles("d"))
self.dButton.grid(row = 1, column = 1, sticky = W)
# Label for CSV Path
self.cLabel = Label(self, text = "CSV Path")
self.cLabel.grid(row = 3, column = 0, columnspan = 2, sticky = W)
# Entry for CSV Path
self.cEntry = Entry(self, width = 60)
self.cEntry.grid(row = 4, column = 0, sticky = W)
# Button for CSV Path Directory Browse
self.cButton = Button(self, text = "Browse", command = lambda: self.browseFiles("c"))
self.cButton.grid(row = 4, column = 1, sticky = W)
# Label for Log Path
self.lLabel = Label(self, text = "Log Path")
self.lLabel.grid(row = 6, column = 0, columnspan = 2, sticky = W)
# Entry for Log Path
self.lEntry = Entry(self, width = 60)
self.lEntry.grid(row = 7, column = 0, sticky = W)
# Button for Log Path Directory Browse
self.lButton = Button(self, text = "Browse", command = lambda: self.browseFiles("l"))
self.lButton.grid(row = 7, column = 1, sticky = W)
# Text Box for Results
self.resultText = Text(self, width = 60, height = 30, wrap = WORD, borderwidth = 3, relief = SUNKEN)
self.resultText.grid(row = 9, column = 0, columnspan = 2, sticky = "nsew")
# Scrollbar for Text Box
self.scrollBar = Scrollbar(self, command = self.resultText.yview)
self.scrollBar.grid(row = 9, column = 2, sticky = "nsew")
self.resultText["yscrollcommand"] = self.scrollBar.set
def browseFiles(self, btnCalling):
if(btnCalling == "d"):
self.dName = filedialog.askdirectory(initialdir = "/python3-CH05")
self.dEntry.delete(0, END)
self.dEntry.insert(0, self.dName)
elif(btnCalling == "c"):
self.cName = filedialog.askdirectory(initialdir = "/python3-CH05")
self.cEntry.delete(0, END)
self.cEntry.insert(0, self.cName)
elif(btnCalling == "l"):
self.lName = filedialog.askdirectory(initialdir = "/python3-CH05")
self.lEntry.delete(0, END)
self.lEntry.insert(0, self.lName)
output = extractGPS(self.dName, self.cName, self.lName)
self.resultText.delete(0.0, END)
self.resultText.insert(0.0, output)
# Start the GUI
root = Tk( )
root.title("Python gpsExtractor")
root.geometry("650x650")
app = Application(root)
root.mainloop( )
Related
Application: Building a notes application (as an intro to GUI development in Python) which includes feature of a scrollbar to scroll through a textbox
Problem: I can't actually seem to scroll down through the textbox. I don't seem to get the grayed rectangle which lets me control the scrollbar and scroll up/down through the textbox
#importing necessary packages
from tkinter import *
from tkinter import font
from tkinter import ttk
#set up main window
root = Tk()
root.title("Notes")
root.geometry("400x650")
#functions
#functions to change all widget button's backgrounds when user hovers over it and leaves it
def enter_button(e):
e.widget.config(background = "#D4D4D4")
#SystemButtonFace is default colour
def leave_button(e):
e.widget.config(background = "SystemButtonFace")
#clear text in text-box
def clear():
#delete all text from text_box
text_box.delete(1.0,END)
def bold_it():
#create font
try:
bold_font = font.Font(text_box, text_box.cget("font"))
bold_font.configure(weight = "bold")
#creating tag called "bold" which bolds textll upon condition
text_box.tag_configure("bold", font = bold_font)
#creating a bold tag which highlights first character
bold_tag = text_box.tag_names("sel.first")
#condition for checking to see if tag is applied or not
#in the first highlighted character
#if tag is applied, remove the bold from first-highlighted text
#- last highlighted text
#"bold" needs to be matched in the tag
if "bold" in bold_tag:
text_box.tag_remove("bold","sel.first","sel.last")
else:
text_box.tag_add("bold","sel.first", "sel.last")
except TclError:
pass
def italics_it():
try:
#create a font
italics_font = font.Font(text_box, text_box.cget("font"))
italics_font.configure(slant = "italic")
#create a tag called "italic"
text_box.tag_configure("italics", font = italics_font)
italics_tag = text_box.tag_names("sel.first")
#condition to see whether tag has been applies or not
if "italics" in italics_tag:
text_box.tag_remove("italics", "sel.first","sel.last")
else:
text_box.tag_add("italics", "sel.first", "sel.last")
except TclError:
pass
#frames
top_frame = LabelFrame(root, padx = 30, pady = 10)
button_frame = LabelFrame(root, padx = 30, pady = 10)
text_frame = LabelFrame(root, padx = 10, pady = 10)
bottom_frame = LabelFrame(root, borderwidth = 0, highlightthickness = 5)
top_frame.grid(row = 0 , column = 0)
button_frame.grid(row = 1, column = 0, pady = 10)
text_frame.grid(row = 2, column = 0, pady = 1)
bottom_frame.grid(row = 3, column = 0, pady = 3)
#labels, textboxes, buttons
#top_frame content
Notes_label = Label(top_frame, text = "Notes", fg = "black", font = 1, padx = 141)
Notes_label.grid(row = 0 , column = 0)
save_button = Button(top_frame, text = "save")
#padx increases distance between buttons
#button_frame content
#bold button
#the ideal is that if u press ctrl + b, the bold_button is pressed by itself
#rn, it's gonna be a highlight technique
bold_button = Button(button_frame, text = "B", padx = 4, pady = 2, command = bold_it)
bold_button.grid(row = 0, column = 0)
#italicsize button
italics_button = Button(button_frame, text = "I", padx = 4, pady = 2, command = italics_it)
italics_button.grid(row = 0, column = 2, padx = 15)
#text_box frame button
text_box = Text(text_frame, width = 45, height = 27)
text_box.grid(row = 0, column = 0)
#text_box frame content
main_scrollbar = ttk.Scrollbar(text_frame, orient = "vertical", command = text_box.yview)
main_scrollbar.grid(row = 0, column = 1)
text_box["yscrollcommand"] = main_scrollbar.set
clear_button = Button(bottom_frame, text = "clear", padx = 2, pady = 2, command = clear)
clear_button.grid(row = 0, column = 0, padx = 15, pady = 10)
save_button = Button(bottom_frame, text = "save note", padx = 2, pady = 2)
save_button.grid(row = 0, column =1, padx = 15, pady = 10)
#binding all buttons for changing colours when user hovers over it and leaves it
bold_button.bind("<Enter>", enter_button)
bold_button.bind("<Leave>", leave_button)
italics_button.bind("<Enter>", enter_button)
italics_button.bind("<Leave>", leave_button)
clear_button.bind("<Enter>", enter_button)
clear_button.bind("<Leave>", leave_button)
save_button.bind("<Enter>", enter_button)
save_button.bind("<Leave>", leave_button)
# main program loop
root.mainloop()
here's an image of the problem image of problem
I would also be very grateful if one could explain the concept of scrollbar.set and like yview and why they are both needed for the scrollbar to work. Tutorials and videos don't seem to explain the concept, but just implement it
In line 145. You're missing sticky
main_scrollbar.grid(row = 0, column = 1, sticky=NS)
Output:
I am trying to make a Tkinter GUI that takes Excel documents, reads them, and exports them to the window. The issue is when I changed the code to below to incorporate class structure, I cannot make the GUI load properly anymore.
import tkinter as tk
from tkinter.filedialog import askopenfilename
def NewFile():
print("New File!")
def OpenFile():
name = askopenfilename()
print(name)
def About():
print("About works")
def deletelist():
listbox.delete(0, END)
class MainApplication(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.master = master
self.frame = tk.Frame(self.master)
self.load = tk.Button(self.frame, text = "Load XLSX File", command = OpenFile)
self.load.grid(row = 0, column = 0, padx = 5, pady = 5, sticky = 'w')
self.ckframe = tk.LabelFrame(self.frame, text="Currency Selections")
self.ckframe.grid(row = 1, column = 0, padx = 5, pady = 5, stick = 'nesw')
self.prochk = tk.Checkbutton(self.ckframe, text = '1 Currency').grid(row = 1, column = 0, columnspan = 2, sticky = 'w')
self.msnchk = tk.Checkbutton(self.ckframe, text = '2 Currency').grid(row = 1, column = 2, columnspan = 2, sticky = 'w')
self.nightschk = tk.Checkbutton(self.ckframe, text = '3 Currency').grid(row = 1, column = 4, columnspan = 2, sticky = 'w')
self.semichk = tk.Checkbutton(self.ckframe, text = '4 Currency').grid(row = 2, column = 0, columnspan = 2, sticky = 'w')
self.instqualCRchk = tk.Checkbutton(self.ckframe, text = '5 Currency').grid(row = 2, column = 2, columnspan = 2, sticky = 'w')
self.msnCRchk = tk.Checkbutton(self.ckframe, text = '6 Currency').grid(row = 2, column = 4, columnspan = 2, sticky = 'w')
self.listbox = tk.Listbox(self.frame, width = 83)
self.listbox.grid(row = 3, column = 0, columnspan = 1, sticky = 'w') # Fix width size function
self.listbox.insert(1, 'Test1')
self.listbox.insert(0, 'Test2')
self.save = tk.Button(self.frame, text = "Save").grid(row = 8, column = 0, padx = 5, pady = 5, stick = 'e')
self.delete = tk.Button(self.frame, text = "Delete", command = deletelist).grid(row = 8, column = 0, padx = 45, pady = 5, stick = 'e')
if __name__ == '__main__':
root = tk.Tk()
MainApplication(root)
root.mainloop()
I searched a lot trying to find a solution to using classes with tkinter GUI and the grid system but I mostly found ways to make GUIs with pack() solution.
The instance of MainApplication is a frame. You never call pack or place or grid on that instance so that frame and all of its children will be invisible.
This frame creates another frame that contains all of the other widgets, self.frame. You never call pack, place, or grid on it either, so it and all of its children will be invisible.
Since the widgets are in a frame that is invisible, and that frame itself is invisible, none of the other widgets will be visible.
The first thing to do is to get rid of self.frame. Remove the line that creates it, and everywhere you reference self.frame, replace it with self. Since self in this context is already a frame it makes no sense to create another frame inside.
Next, you need to add the instance of MainApplication to the window. Since it's the only widget directly in the root window, pack is the simplest choice.
root = tk.Tk()
app = = MainApplication(root)
app.pack(fill="both", expand=True)
I have this code I coded using tkinter.
def create_widgets(self):
self.submit_button = Button(self, text ="Submit", command = self.popupmsg)
self.submit_button.grid(row = 6, column = 0, sticky = W)
def popupmsg(self):
popupmsg = Tk()
popupmsg.wm_title("Test")
self.grid()
self.text = Text(popupmsg,text="test", width = 30, height = 10, wrap = WORD)
self.text.grid(row = 8, column = 0, columnspan = 2, sticky = W)
I was wondering if there is any way to open popupmsg and close create_widgets. I know about ____.destroy() but using that i can only get it to close it not close it and open a new window
I'm trying to make a text editor with Python 3.4.2 and tkinter/ttk. When my file is loaded in, the text is inserted into the Text widget from the bottom of the file up, making the file text "backwards". The last line of the file is inserted first, and the first line last. Anything will help. Thank you.
from tkinter import *
from tkinter import ttk
import os
class Main(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.grid()
self.create_widgets()
def create_widgets(self):
self.body = Text(self, width=50, height=15)
self.body.grid(row = 0, column = 0, sticky = W)
self.save_label = Label(self, text="File to Save to:")
self.save_label.grid(row = 2, column = 0, sticky = W)
self.save_entry = ttk.Entry(self)
self.save_entry.grid(row = 3, column = 0, sticky = W)
self.save_button = ttk.Button(self, text="Save File", command=self.save)
self.save_button.grid(row = 4, column = 0, sticky = W)
self.read_label = Label(self, text="File to Read:")
self.read_label.grid(row = 2, column = 1, sticky = W)
self.read_entry = ttk.Entry(self)
self.read_entry.grid(row = 3, column = 1, sticky = W)
self.read_button = ttk.Button(self, text="Read File", command=self.read)
self.read_button.grid(row = 4, column = 1, sticky = W)
scrollbar = ttk.Scrollbar(root, orient=VERTICAL, command=self.body.yview)
scrollbar.grid(row = 0, column = int(1), sticky = 'ns')
self.body.config(yscrollcommand=scrollbar.set)
self.quit_button = ttk.Button(self, text="Quit", command=self.close)
self.quit_button.grid(row = 5, column = 0, sticky = W)
def close(self):
root.destroy()
quit()
def save(self):
body = self.body.get('0.0', 'end-1c')
file = self.save_entry.get()
file = open(file, "w")
file.write(body)
file.close()
def read(self):
self.body.delete("0.0", END)
file = self.read_entry.get()
file = open(file, 'r')
file_data = file.readlines()
for i in file_data:
self.body.insert('1.0', str(i))
file.close()
root = Tk()
root.title("NotePad")
root.geometry("500x600")
root.attributes("-fullscreen", True)
app = Main(root)
root.mainloop()
You are telling tkinter to place each line at "1.0". If you want each line to be added to the end, use "end"
for i in file_data:
self.body.insert('end', str(i))
By the way, the first character of a text widget is at "1.0", not "0.0". While "0.0" will work as quirk of how tkinter is implemented, the correct index is "1.0".
For example, use this:
body = self.body.get('1.0', 'end-1c')
... rather than this:
body = self.body.get('0.0', 'end-1c')
I am working on a larger programming project, and since I am a beginner it is not that complex. I will try to keep it straight forward: I want to create a GUI program that reads from a text file with "elements of notes", i.e. as a calendar.
The interface should have "text entry box", where you can submit new notes, and there should also be two buttons that upon pressing them "scrolls" up and down among the existing notes, i.d. turning page. A single note should be displayed at all times in a text box under the two buttons.
So, to wrap this up, my question is: How is the best way to "load" the text file's notes to the program, so that I can make the buttons scroll between them? Should I read the text file into a list that I give my Application(Frame) object?
Here is some of my code so far:
from tkinter import *
class Application(Frame):
""" GUI application that creates diary. """
def __init__(self, master):
""" Initialize Frame. """
Frame.__init__(self, master)
self.grid()
self.create_widgets()
def create_widgets(self):
""" Create widgets to get info of choices and display notes. """
# create a label and text entry for new note
Label(self,
text = "Enter new note:"
).grid(row = 1, column = 0, sticky = W)
self.note_ent = Entry(self)
self.note_ent.grid(row = 1, column = 1, sticky = W)
# create a submit button for the new note
Button(self,
text = "Submit",
# command = self.add_note to a list within app obeject?
).grid(row = 2 column = 0, sticky = W)
# create a 'next note' button
Button(self,
text = "Next",
# command = self.next_note which goes to a list?
).grid(row = 6, column = 0, sticky = W)
# create a 'past note' button
Button(self,
text = "Back",
# command = self_past_note, or should I reuse next_note?
).grid(row = 6, column = 0, sticky = W)
# create a textbox (I am not sure?)
self.show_ent = Text(self, width = 75, height = 10, wrap = WORD)
self.show_ent.grid(row = 7, column = 0, columnspan = 4)
# main
text_file = open("diary.txt", "r")
note_list = text_file.readlines()
text_file.close()
# No idea where to put the note_list, which 'client' should receive it?
root = Tk()
root.title("Diary")
app = Application(root)
root.mainloop()
So now that you have examined my code, how to fill in the missing pieces?
Edit: I added the text_file and note_list under the # main.
Note: I have used calendar and diary interchangeably, but the program is more of a calendar.
You can use it inside Application class:
from Tkinter import *
class Application(Frame):
""" GUI application that creates diary. """
def __init__(self):
""" Initialize Frame. """
Frame.__init__(self)
self.note_list = []
with open("diary.txt", "r") as notes:
self.note_list = text_file.readlines()
self.grid()
self.create_widgets()
def create_widgets(self):
""" Create widgets to get info of choices and display notes. """
# create a label and text entry for new note
Label(self,
text = "Enter new note:"
).grid(row = 1, column = 0, sticky = W)
self.note_ent = Entry(self)
self.note_ent.grid(row = 1, column = 1, sticky = W)
# create a submit button for the new note
Button(self,
text = "Submit",
# command = self.add_note to a list within app obeject?
).grid(row = 2, column = 0, sticky = W)
# create a 'next note' button
Button(self,
text = "Next",
# command = self.next_note which goes to a list?
).grid(row = 6, column = 0, sticky = W)
# create a 'past note' button
Button(self,
text = "Back",
# command = self_past_note, or should I reuse next_note?
).grid(row = 6, column = 0, sticky = W)
# create a textbox (I am not sure?)
self.show_ent = Text(self, width = 75, height = 10, wrap = WORD)
self.show_ent.grid(row = 7, column = 0, columnspan = 4)
app = Application()
app.master.title("Diary")
app.mainloop()