This is shortened example. I have 2 frames: Page1 and Page2. prj_conf is default dictionary.
In Page1,
Browse button specify text file, Load button read the text file and update the values of prj_conf from the text file. Next button jumps to Page2.
In Page2, Entryproj entry shows the value of prj_conf["_cal_input_pwr"].
The target is when I load text file and update the values of prj_conf, then press Next button in Page1. my GUI jumps to Page2 and the value of prj_conf["_cal_input_pwr"] in Entryproj entry should be come from the text file.
However there are many widgets in original Page2, so I want to update all widget values in Page2 when Next button is pressed. How do I do that?
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
from tkinter import messagebox as mBox
# create dafault dictionary
prj_keys = ["_time", "_projet", "_DUT", "_user", "_project_dir", "_cal_input_pwr"]
prj_conf = {key: "0" for key in prj_keys}
#read text file
def read_settingfile():
print("test")
class main_win(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.geometry(self)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.rowconfigure(0, weight=1)
container.columnconfigure(0, weight=1)
self.frames = {}
for F,geometry in zip(( Page1, Page2), ( "900x617"
, "993x817")):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = (frame, geometry)
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("Page1")
def show_frame(self, page_name):
frame, geometry = self.frames[page_name]
self.geometry(geometry)
frame.tkraise()
class Page1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.configure(bg = "#d8d8d8")
self.controller = controller
self.labelframe_newfile = tk.LabelFrame(self)
self.loadLabelframe = tk.LabelFrame(self)
self.button_next = tk.Button(self, command = lambda: self.setnextdata())
self.button_next.place(relx=0.811, rely=0.891, height=41, width=150)
self.button_next.configure(activebackground="#ececec")
self.button_next.configure(activeforeground="#000000")
self.button_next.configure(background="#d9d9d9")
self.button_next.configure(disabledforeground="#a3a3a3")
self.button_next.configure(foreground="#000000")
self.button_next.configure(highlightbackground="#d9d9d9")
self.button_next.configure(highlightcolor="black")
self.button_next.configure(pady="0")
self.button_next.configure(text='''Next''')
self.loadLabelframe.place(relx=0.033, rely=0.25, relheight=0.6
, relwidth=0.933)
self.loadLabelframe.configure(relief='groove')
self.loadLabelframe.configure(font="-family {微軟正黑體} -size 14")
self.loadLabelframe.configure(foreground="black")
self.loadLabelframe.configure(text='''Load File''')
self.loadLabelframe.configure(background="#d9d9d9")
self.loadLabelframe.configure(highlightbackground="#d9d9d9")
self.loadLabelframe.configure(highlightcolor="black")
self.loadprojfile_path = tk.StringVar()
self.Entry_loadprojfile = tk.Entry(self.loadLabelframe, textvariable = self.loadprojfile_path)
self.Entry_loadprojfile.place(relx=0.048, rely=0.723, height=31, relwidth=0.755
, bordermode='ignore')
self.Entry_loadprojfile.configure(background="white")
self.Entry_loadprojfile.configure(disabledforeground="#a3a3a3")
self.Entry_loadprojfile.configure(font="TkFixedFont")
self.Entry_loadprojfile.configure(foreground="#000000")
self.Entry_loadprojfile.configure(highlightbackground="#d9d9d9")
self.Entry_loadprojfile.configure(highlightcolor="black")
self.Entry_loadprojfile.configure(insertbackground="black")
self.Entry_loadprojfile.configure(selectbackground="#c4c4c4")
self.Entry_loadprojfile.configure(selectforeground="black")
self.button_browse_proj_fle = tk.Button(self.loadLabelframe,
command = lambda:self.dir_browse_old())
self.button_browse_proj_fle.place(relx=0.82, rely=0.723, height=31
, width=65, bordermode='ignore')
self.button_browse_proj_fle.configure(activebackground="#ececec")
self.button_browse_proj_fle.configure(activeforeground="#000000")
self.button_browse_proj_fle.configure(background="#d9d9d9")
self.button_browse_proj_fle.configure(disabledforeground="#a3a3a3")
self.button_browse_proj_fle.configure(foreground="#000000")
self.button_browse_proj_fle.configure(highlightbackground="#d9d9d9")
self.button_browse_proj_fle.configure(highlightcolor="black")
self.button_browse_proj_fle.configure(pady="0")
self.button_browse_proj_fle.configure(text='''Browse''')
self.button_load = tk.Button(self.loadLabelframe, command = lambda:self.loadfile())
self.button_load.place(relx=0.912, rely=0.723, height=31, width=49
, bordermode='ignore')
self.button_load.configure(activebackground="#ececec")
self.button_load.configure(activeforeground="#000000")
self.button_load.configure(background="#d9d9d9")
self.button_load.configure(disabledforeground="#a3a3a3")
self.button_load.configure(foreground="#000000")
self.button_load.configure(highlightbackground="#d9d9d9")
self.button_load.configure(highlightcolor="black")
self.button_load.configure(pady="0")
self.button_load.configure(text='''Load''')
def setnextdata(self):
self.controller.show_frame("Page2")
def dir_browse_old(self):
self.old_work_directory = filedialog.askopenfilename( filetypes = (("project files", "*.prj"),("all files","*.*")) )
self.loadprojfile_path.set(self.old_work_directory)
def loadfile(self):
read_settingfile(self.old_work_directory)
print("load"+str(prj_conf["_cal_input_pwr"]))
class Page2(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.configure(bg = "#d8d8d8")
self.TSeparator1 = ttk.Separator(self)
self.TSeparator1.place(relx=0.005, rely=0.092, relwidth=0.987)
self.label_title = tk.Label(self)
self.label_title.place(relx=0.07, rely=0.018, height=55, width=793)
self.label_title.configure(activebackground="#f9f9f9")
self.label_title.configure(activeforeground="black")
self.label_title.configure(background="#d9d9d9")
self.label_title.configure(disabledforeground="#a3a3a3")
self.label_title.configure(font="-family {新細明體} -size 30")
self.label_title.configure(foreground="#000000")
self.label_title.configure(highlightbackground="#d9d9d9")
self.label_title.configure(highlightcolor="black")
self.label_title.configure(text='''Step 2. Calibration Setting''')
self.button_last = tk.Button(self, command = lambda: self.last_update())
self.button_last.place(relx=0.03, rely=0.93, height=41, width=150)
self.button_last.configure(activebackground="#ececec")
self.button_last.configure(activeforeground="#000000")
self.button_last.configure(background="#d9d9d9")
self.button_last.configure(disabledforeground="#a3a3a3")
self.button_last.configure(foreground="#000000")
self.button_last.configure(highlightbackground="#d9d9d9")
self.button_last.configure(highlightcolor="black")
self.button_last.configure(pady="0")
self.button_last.configure(text='''Last''')
self.inpu_pow_leve_frame = tk.Frame(self)
self.inpu_pow_leve_frame.place(relx=0.081, rely=0.208, relheight=0.092
, relwidth=0.846)
self.inpu_pow_leve_frame.configure(relief='groove')
self.inpu_pow_leve_frame.configure(borderwidth="2")
self.inpu_pow_leve_frame.configure(relief="groove")
self.inpu_pow_leve_frame.configure(background="#d9d9d9")
self.inpu_pow_leve_frame.configure(highlightbackground="#d9d9d9")
self.inpu_pow_leve_frame.configure(highlightcolor="black")
self.label_inpu_pow_leve = tk.Label(self.inpu_pow_leve_frame)
self.label_inpu_pow_leve.place(relx=0.036, rely=0.267, height=36
, width=271)
self.label_inpu_pow_leve.configure(activebackground="#f9f9f9")
self.label_inpu_pow_leve.configure(activeforeground="black")
self.label_inpu_pow_leve.configure(background="#d9d9d9")
self.label_inpu_pow_leve.configure(disabledforeground="#a3a3a3")
self.label_inpu_pow_leve.configure(font="-family {微軟正黑體} -size 14")
self.label_inpu_pow_leve.configure(foreground="#000000")
self.label_inpu_pow_leve.configure(highlightbackground="#d9d9d9")
self.label_inpu_pow_leve.configure(highlightcolor="black")
self.label_inpu_pow_leve.configure(text='''Input Power Level (dBm)''')
self.var_inpu_pow_leve = tk.IntVar()
self.var_inpu_pow_leve.set(prj_conf["_cal_input_pwr"])
self.Entryproj = tk.Entry(self.inpu_pow_leve_frame,textvariable = self.var_inpu_pow_leve)
self.Entryproj.place(relx=0.383, rely=0.267,height=31, relwidth=0.58)
self.Entryproj.configure(background="white")
self.Entryproj.configure(disabledforeground="#a3a3a3")
self.Entryproj.configure(font="TkFixedFont")
self.Entryproj.configure(foreground="#000000")
self.Entryproj.configure(highlightbackground="#d9d9d9")
self.Entryproj.configure(highlightcolor="black")
self.Entryproj.configure(insertbackground="black")
self.Entryproj.configure(selectbackground="#c4c4c4")
self.Entryproj.configure(selectforeground="black")
def last_update(self):
self.controller.show_frame("Page1")
app = main_win()
app.mainloop()
Related
I have a program that deals a lot with creating objects from data in files with the ability to edit the objects and then save them in the same file. I am implementing a GUI, and I am using tkinter to do it. The problem I am facing is the problem of frames not updating when I jump back and forth between frames, since the constructor method only runs once when the program begins, and which is where I produce most of the widgets on the screen. Below is an example of what I would like to accomplish:
import tkinter as tk
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
container = tk.Frame(self)
container.pack(side = "top", fill = "both", expand = True)
container.grid_rowconfigure(0, weight = 1)
container.grid_columnconfigure(0, weight = 1)
self.frames = {}
for F in (Homescreen, Menuscreen):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row = 0, column = 0, sticky = "nsew")
self.show_frame(Homescreen)
def show_frame(self, container):
frame = self.frames[container]
frame.tkraise()
class Homescreen(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
with open("test.txt", "r") as f:
text = f.readline()
tk.Label(self, text = text).pack()
tk.Button(self, text = "next page", command = lambda: controller.show_frame(Menuscreen)).pack()
class Menuscreen(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.entry = tk.StringVar()
tk.Entry(self, textvariable = self.entry).pack()
tk.Button(self, text = "back to page", command = self.writeToFile).pack()
def writeToFile(self):
with open("test.txt", "w") as f:
f.writelines(self.entry.get())
self.controller.show_frame(Homescreen)
app = App()
app.geometry("500x400")
app.mainloop()
If I have a textfile with just a simple word, in Homescreen i print it out on the screen. Then I move to the second frame, Menuscreen, where I allow the user to enter another word, and then I store the word in the same textfile. Then the program takes us back to the Homescreen, but the problem is that the printed out word, will still be the first word and not the updated word in the textfile.
I tried to use the methods .update() and .destroy(), one line before i execute frame.tkraise(), but the .update() method doesn't do anything and when I use the .destroy() method, I get an error saying _tkinter.TclError: bad window path name
You can't get the "printed out word" to change because the constructor for Homescreen is only run once. You need another method that changes the entry when you raise the Frame. The changes are commented below. There are only 4.
import tkinter as tk
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (Homescreen, Menuscreen):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row = 0, column = 0, sticky = "nsew")
self.show_frame(Homescreen)
def show_frame(self, container):
frame = self.frames[container]
#update the label
if container is Homescreen: frame.update_label()
frame.tkraise()
class Homescreen(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
#keep a reference to the label so it can be modified
self.label = tk.Label(self)
self.label.pack()
tk.Button(self, text = "next page", command = lambda: controller.show_frame(Menuscreen)).pack()
self.update_label()
#update the label
def update_label(self):
with open('test.txt', 'r') as f:
self.label['text'] = f.read()
class Menuscreen(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.entry = tk.StringVar()
tk.Entry(self, textvariable = self.entry).pack()
tk.Button(self, text = "back to page", command = self.writeToFile).pack()
def writeToFile(self):
with open('test.txt', 'w') as f:
f.write(self.entry.get())
#go back to homescreen
self.controller.show_frame(Homescreen)
app = App()
app.geometry("500x400")
app.mainloop()
If you'd like to make your script a little easier to work with, I refactored it below, and left comments.
import tkinter as tk
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
#you do not need `container`
#using root as the master makes it a more natural controller
#you were using it more like a proxy
self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=1)
#you created a convention with your class names of using "screen"
#use some kind of "screen" for everything that contains or directly relates to them
self.screens = {}
#don't "juggle"
#create a var, and use it
for screen in (Menuscreen, Homescreen):
self.screens[screen] = screen(self)
self.screens[screen].grid(row=0, column=0, sticky="nsew")
#renamed to reflect that it relates to your screens
def show_screen(self, screen):
target = self.screens[screen]
if screen is Homescreen: target.update_label()
target.tkraise()
class Homescreen(tk.Frame):
#whatever you put in master becomes the `self.master` of this widget
#ie.. we are keeping the names the same
def __init__(self, master, **kwargs):
tk.Frame.__init__(self, master, **kwargs)
self.label = tk.Label(self)
self.label.pack()
#this line illustrates how the root is the controller
tk.Button(self, text="next page", command=lambda: master.show_screen(Menuscreen)).pack()
#init the label text
self.update_label()
def update_label(self):
with open('test.txt', 'r') as f:
self.label['text'] = f.read()
class Menuscreen(tk.Frame):
def __init__(self, master, **kwargs):
tk.Frame.__init__(self, master, **kwargs)
self.entry = tk.StringVar()
tk.Entry(self, textvariable=self.entry).pack()
tk.Button(self, text="back to page", command=self.writeToFile).pack()
def writeToFile(self):
with open('test.txt', 'w') as f:
f.write(self.entry.get())
#illustrates again how the root is the controller
self.master.show_screen(Homescreen)
#this is good practice
if __name__ == "__main__":
app = App()
app.geometry("500x400")
app.mainloop()
able frame in tkinter, the frame consist of multiple mini long canvases(which contain some text and a button)which can be scrolled up and down with a scrollbar. I also used tkinter themes to make my gui look nice. But for some reason as soon as i added in the gui, the frame would lag abit when scrolled up and down, like the canvases are crashing into eachother, is their away to fix this?
Here is how it looks without scrolling
Here's how it looks sometimes, when its scrolled
Here's the code
from tkinter import *
from ttkthemes.themed_tk import ThemedTk
from tkinter import *
from tkinter.ttk import *
import tkinter as tk
from tkinter import ttk
class tkinterprogram(ThemedTk):
def __init__(self, *args, **kwargs):
ThemedTk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage,Task):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
frame.winfo_toplevel().geometry("1024x720")
class StartPage(tk.Frame):
def __init__(self, parent, controller):
ttk.Frame.__init__(self, parent)
l = Canvas(self, bg='#4A4949')
l.pack(fill='both', expand='True')
global canvascon
canvascon = Canvas(l, height=400,width=1500,bg='#4A4949',highlightthickness=0)
global frame2
frame2 = Frame(canvascon)
global myscrollbar
myscrollbar = Scrollbar(l, orient="vertical",command=canvascon.yview)
canvascon.create_window((0, 0), window=frame2,width=15000,anchor='nw')
canvascon.place(x=25,y=150,relheight=0.558,relwidth=0.87)
myscrollbar.pack(side=RIGHT, fill=Y,pady=25)
Button(l,text='go',command=lambda: meth()).pack()
def meth():
for count in range(25):
c = Canvas(frame2, height=50, bg="#1E2133",highlightthickness=5,highlightbackground='#4A4949')
lab = tk.Label(frame2, text='running',bg='#1E2133',fg='#EFEFEF')
lab_window = c.create_window(10,15, window=lab,anchor=tk.NW)
stop = tk.Button(frame2, text='STOP')
stop_window = c.create_window(200, 15, window=stop, anchor=tk.NW)
c.pack(fill=X,expand=True)
frame2.update() # update frame2 height so it's no longer 0 ( height is 0 when it has just been created )
canvascon.configure(yscrollcommand=myscrollbar.set, scrollregion="0 0 0 %s" % frame2.winfo_height())
class Task(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
app = tkinterprogram()
app.get_themes()
app.set_theme('scidgrey')
app.mainloop()
Thanks for any help in advance.
I am making an app for a project called the organizer. It is an organization app. I have an issue that when you check one check box, they all check off.
How do I fix this?
After ran go to: Checklist -> Enter A Value -> Click "Add Assignment" -> Repeat A few times -> try to click one
Also, my .update() works, but still seems to cause an error? Do you know why?
Thanks!
import tkinter as tk
root = tk
AsgnList = []
#Initialization
class TheOrganizer(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
self.geometry('500x500')
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, AddAsgnPage):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
def RunApp():
app = TheOrganizer()
app.title('The Organizer')
app.mainloop()
#Making New Pages
'''
Make sure for very new page, you add it to the 'for loop'
'''
HeadFont = ("Verdana", 40)
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
LabTitle = tk.Label(self, text="The Organizer", font=HeadFont)
LabTitle.pack()
AddAsgnBtn = tk.Button(self, text='Checklist', command=lambda: controller.show_frame(AddAsgnPage))
AddAsgnBtn.place(x=100,y=250)
class AddAsgnPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
LabTitle = tk.Label(self, text="Assignments", font=HeadFont)
LabTitle.pack()
#Input Assignment
def getEntry():
entryInput = AsgnEntry.get()
AsgnList.append(entryInput)
yVal = 300
while 1:
var = tk.IntVar()
for z in AsgnList:
tk.Checkbutton(self, text=z, variable=var).place(x=200,y=yVal)
yVal += 25
TheOrganizer.update()
AsgnEntry = tk.Entry(self)
AsgnEntry.place(x=175,y=205)
SubBtn = tk.Button(self, text='Add Assignment', command=getEntry)
SubBtn.place(x=25,y=200)
BackBtn = tk.Button(self, text='Back', command=lambda: controller.show_frame(StartPage))
BackBtn.place(x=250,y=400)
You are using the same variable for both checkboxes. Move the variable creation to inside the loop, to use different variables.
var_list = []
for z in AsgnList:
var = tk.IntVar()
tk.Checkbutton(self, text=z, variable=var).place(x=200,y=yVal)
yVal += 25
var_list.append(var)
That said, you probably want to store the variables so you can check which checkboxes are marked later. So I added a var_list list object to store all created vars.
Im trying to code a simple tkinter program that returns reddit information back to the user. In doing so, I'm receiving the error message:
Traceback (most recent call last):
File "redditscraper4.py", line 111, in <module>
app = RedditScraper()
File "redditscraper4.py", line 23, in __init__
frame = F(container, self)
File "redditscraper4.py", line 93, in __init__
get_user_entry_string = get_user_entry.addBrackets()
File "redditscraper4.py", line 62, in addBrackets
user_entry = StartPage()
TypeError: __init__() missing 2 required positional arguments: 'parent' and 'controller'
I have absolutely no clue as to what I've done wrong with my code. Im lost, and nowhere on the Web seems to have a coherent answer to this problem.
Here is my code:
import tkinter as tk
from functools import partial
from webbrowser import open
from datetime import date
import praw
'''Initialising the Applicaiton'''
class RedditScraper(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, redditReturn):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
'''The First Page the User will see'''
class StartPage(tk.Frame, object):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label1 = tk.Label(self, text="Start Page")
label1.pack(pady=10, padx=10)
button1 = tk.Button(self, text="Scrape This Subreddit", command=lambda: controller.show_frame(redditReturn))
button1.pack(pady=10, padx=10)
self.entry_var = tk.StringVar()
e1 = tk.Entry(self,textvariable=self.entry_var)
e1.pack(pady=10, padx=10)
StartPage.entry1 = self.entry_var.get()
'''Adding brackets around the user's entry to the label to suffice the praw api'''
class bracketEntry(object):
def addBrackets(self):
user_entry = StartPage()
get_user_entry_string = user_entry.entry1()
user_entry_plus_brackets = '"' + get_user_entry_string + '"'
print(user_entry_plus_brackets)
return user_entry_plus_brackets
'''Collecting data from reddit'''
class redditCollect(object):
def getSubreddit(self):
user_agent = "Simple Subreddit Scraper"
r = praw.Reddit(user_agent=user_agent)
'''remember to add the ability to get the user-defined subreddit information'''
user_entry = bracketEntry()
user_entry_variable = user_entry.addBrackets()
posts = r.get_subreddit("pics").get_hot(limit = 10)
return posts
'''The window containing the information from Reddit for the user'''
class redditReturn(tk.Frame, object):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
"""Creates all the buttons and frames for the GUI"""
get_user_entry = bracketEntry()
get_user_entry_string = get_user_entry.addBrackets()
intro = get_user_entry_string + " on Reddit: "
newFrame = tk.LabelFrame(self, text = intro)
newFrame.pack(fill="both", expand= True , anchor="nw")
row = 0
redditCollectGetter = redditCollect()
local_posts = redditCollectGetter.getSubreddit()
for p in local_posts:
gotoArticle = partial(open, p.url)
title = "(" + str(p.score) +") " + p.title
tk.Label(newFrame, text= title, pady= 10, wraplength= 700, justify= "left").grid(row= row, column= 0, sticky= "w")
tk.Button(newFrame, text= "Read more!", command= gotoArticle).grid(row= row+1, column= 0, sticky= "w")
tk.row = row + 2
app = RedditScraper()
app.mainloop()
Any help is appreciated!
Thanks!
In your bracketEntry class, in the addBrackets method, you call user_entry = StartPage(). However, you declare StartPage's __init__ method as def __init__(self, parent, controller):, which means you have to provide parent and controller arguments.
Edit: To fix the method, you are going to have to pass the parent and controller objects all the way down the call stack or find another way of getting them into the addBrackets method. E.g., you could redefine def addBrackets(self, parent, controller), and then update the infringing line: user_entry = StartPage(parent, controller). You would then have to update all calls to addBracket to include the new argument.
You've defined the __init__ method of StartPage to take two required arguments, parent and controller. But in the line that's causing the error, you are just calling StartPage() without passing those arguments. As the error says, you need to pass them.
import tkinter as tk
from functools import partial
from webbrowser import open
from datetime import date
import praw
'''Initialising the Applicaiton'''
class RedditScraper(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, redditReturn):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
'''The First Page the User will see'''
class StartPage(tk.Frame, object):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label1 = tk.Label(self, text="Start Page")
label1.pack(pady=10, padx=10)
button1 = tk.Button(self, text="Scrape This Subreddit", command=lambda: controller.show_frame(redditReturn))
button1.pack(pady=10, padx=10)
self.entry_var = tk.StringVar()
e1 = tk.Entry(self, textvariable=self.entry_var)
e1.pack(pady=10, padx=10)
global save
save = tk.StringVar()
save = e1.get()
# StartPage.entry1: str = self.entry_var.get()
def entry1(self):
global save
user_input = tk.StringVar()
user_input = save
return save
'''Adding brackets around the user's entry to the label to suffice the praw api'''
class bracketEntry(object):
def addBrackets(self, parent, controller):
user_entry = StartPage(parent, controller)
# * Takes in inputs as parent and the controller
get_user_entry_string = user_entry.entry1()
user_entry_plus_brackets = '"' + get_user_entry_string + '"'
print(user_entry_plus_brackets)
return user_entry_plus_brackets
'''Collecting data from reddit'''
class redditCollect(object):
def getSubreddit(self, parent, controller):
user_agent = "Simple Subreddit Scraper"
r = praw.Reddit(user_agent=user_agent)
'''remember to add the ability to get the user-defined subreddit information'''
user_entry = bracketEntry()
user_entry_variable = user_entry.addBrackets(parent,controller)
print(user_entry_variable) # prints the quoted string in the Entry field
posts = r.get_subreddit("pics").get_hot(limit=10)
return posts
'''The window containing the information from Reddit for the user'''
class redditReturn(tk.Frame, object):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
"""Creates all the buttons and frames for the GUI"""
get_user_entry = bracketEntry()
# * takes in no inputs
get_user_entry_string = get_user_entry.addBrackets(parent, controller)
intro = get_user_entry_string + " on Reddit: "
newFrame = tk.LabelFrame(self, text=intro)
newFrame.pack(fill="both", expand=True, anchor="nw")
row = 0
redditCollectGetter = redditCollect()
local_posts = redditCollectGetter.getSubreddit(parent,controller)
for p in local_posts:
gotoArticle = partial(open, p.url)
title = "(" + str(p.score) + ") " + p.title
tk.Label(newFrame, text=title, pady=10, wraplength=700, justify="left").grid(row=row, column=0, sticky="w")
tk.Button(newFrame, text="Read more!", command=gotoArticle).grid(row=row + 1, column=0, sticky="w")
tk.row = row + 2
app = RedditScraper()
How would I create a new window when the user clicks a button (still needs creating)? I have took some code out to make this shorter. I need a button creating and when they hit that button, a new window opens. I haven't created the button because the button has to be linked to the new window. Please help
My imports...
class App:
def __init__(self, master):
self.master = master
# call start to initialize to create the UI elemets
self.start()
def start(self):
self.master.title("E-mail Extranalyser")
self.now = datetime.datetime.now()
tkinter.Label(
self.master, text=label01).grid(row=0, column=0, sticky=tkinter.W)
# CREATE A TEXTBOX
self.filelocation = tkinter.Entry(self.master)
self.filelocation["width"] = 60
self.filelocation.focus_set()
self.filelocation.grid(row=0, column=1)
# CREATE A BUTTON WITH "ASK TO OPEN A FILE"
# see: def browse_file(self)
self.open_file = tkinter.Button(
self.master, text="Browse...", command=self.browse_file)
# put it beside the filelocation textbox
self.open_file.grid(row=0, column=2)
# now for a button
self.submit = tkinter.Button(
self.master, text="Execute!", command=self.start_processing,
fg="red")
self.submit.grid(row=13, column=1, sticky=tkinter.W)
def start_processing(self):
#code here
def browse_file(self):
# put the result in self.filename
self.filename = filedialog.askopenfilename(title="Open a file...")
# this will set the text of the self.filelocation
self.filelocation.insert(0, self.filename)
root = tkinter.Tk()
app = App(root)
root.mainloop()
Use a Toplevel to open a new one. Modify your code as shown below.
self.NewWindow = tkinter.Button(self.master,
text="New Window",
command=self.CreateNewWindow)
def CreateNewWindow(self):
self.top = tkinter.Toplevel()
self.top.title("title")
Take a look at https://www.youtube.com/watch?v=jBUpjijYtCk. Working through this tutorial would probably help you but this specific video shows how to work with multiple pages.
Something like this:
from tkinter import *
class Sample(Tk):
def __init__(self,*args, **kwargs):
Tk.__init__(self, *args, **kwargs)
container = Frame(self)
container.pack(side="top", fill="both", expand = True)
self.frames = {}
for F in (MainPage, OtherPage):
frame=F(container, self)
self.frames[F]=frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(MainPage)
def show_frame(self, page):
frame = self.frames[page]
frame.tkraise()
class MainPage(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
Label(self, text="Start Page").pack()
Button(self, text="other page?", command=lambda:controller.show_frame(OtherPage)).pack()
class OtherPage(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
Label(self, text="Next Page").pack()
Button(self, text="back", command=lambda:controller.show_frame(MainPage)).pack()
app = Sample()
app.mainloop()