Grey overlay in the middle of my GUI - TKinter - python

I'm having trouble to understand why there is a grey row in my GUI. It's like a overlay, you can write "behind" it but it's is bothering me. Anyone any idea where it comes from?
I'm trying out classes for the first time, when I write the code without classes the problem doesn't occur.
Code:
class LabelInput(tk.Frame):
def __init__(self, parent, label, var, input_class=ttk.Entry,input_args=None, label_args=None, **kwargs):
super().__init__(parent, **kwargs)
input_args = input_args or {}
label_args = label_args or {}
self.variable = var
self.variable.label_widget = self
if input_class in (ttk.Checkbutton, ttk.Button):
input_args["text"] = label
else:
self.label = ttk.Label(self, text=label, **label_args)
self.label.grid(row=0, column=0, sticky=(tk.W + tk.E))
if input_class in (ttk.Checkbutton, ttk.Button, ttk.Radiobutton):
input_args["variable"] = self.variable
else:
input_args["textvariable"] = self.variable
if input_class == ttk.Radiobutton:
self.input = tk.Frame(self)
for v in input_args.pop('values', []):
button = ttk.Radiobutton(self.input, value=v, text=v, **input_args)
button.pack(side=tk.LEFT, ipadx=10, ipady=2, expand=True, fill='x')
else:
self.input = input_class(self, **input_args)
self.input.grid(row=1, column=0, sticky=(tk.W+tk.E))
self.columnconfigure(0, weight=1)
def grid(self, sticky=(tk.E + tk.W), **kwargs):
super().grid(sticky=sticky, **kwargs)
Problem:

Related

why my list changes to a string as I move to another window in tkinter?

I wrote an app using that basis learned there, and this app reads a text file and removes the redundant lines, and returns a list of numbers. The code below returns a list of numbers in PageOne, But as I want to use that list in PageTwo, it changes to a string. I know I have initially introduced variables as strings, but it does not work under other types as well. How I can keep that as a list?
To run this code you can put a few numbers with space separation in a text file and open it using the app.
import tkinter as tk
from tkinter import filedialog
class Data:
def __init__(self):
self.Tot_grids = tk.IntVar()
self.NO = tk.StringVar()
self.NEW = tk.StringVar()
self.NEW2 = tk.StringVar()
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.geometry("500x200")
container = tk.Frame(self)
container.pack()
self.data = Data()
self.frames = {}
for F in (PageOne, PageTwo):
frame = F(container, self.data)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.frames[PageOne].button2.config(command=self.go_to_page_two)
self.show_frame(PageOne)
def go_to_page_two(self):
self.show_frame(PageTwo)
def show_frame(self, c):
frame = self.frames[c]
frame.tkraise()
class PageOne(tk.Frame):
def __init__(self, parent, data):
super().__init__(parent)
self.data = data
def opentext():
my_file = filedialog.askopenfilenames(initialdir="/pycharm", title="Select your file")
for T in my_file: # this line should be here when opening multiple files
import re
with open(T, 'r') as infile1:
lines = infile1.read()
nums = []
for n in re.findall(r'(\d+\.\d+|\d+\*\d+)', lines):
split_by_ast = n.split("*")
if len(split_by_ast) == 1:
nums += [float(split_by_ast[0])]
else:
nums += [float(split_by_ast[1])] * int(split_by_ast[0])
nums = nums[1:len(nums)]
data.NO.set(nums)
label3.config(text=nums)
label4.config(text=type(nums))
self.button1 = tk.Button(self, text="Open file(s)", command=opentext)
self.button1.grid(row=0, column=0, columnspan=2, pady=20)
label1 = tk.Label(self, text="imported numbers:")
label1.grid(row=1, column=0, pady=10)
label2 = tk.Label(self, text="type of imported numbers:")
label2.grid(row=2, column=0, pady=5)
label3 = tk.Label(self)
label3.grid(row=1, column=1)
label4 = tk.Label(self)
label4.grid(row=2, column=1, pady=5)
self.button2 = tk.Button(self, text="Continue")
self.button2.grid(row=3, column=0, columnspan=2, pady=10)
class PageTwo(tk.Frame):
def __init__(self, parent, data):
super().__init__(parent)
self.data = data
self.label5 = tk.Label(self, textvariable=self.data.NEW)
self.label5.pack()
self.label5 = tk.Label(self, textvariable=self.data.NEW2)
self.label5.pack()
self.data.NO.trace_add('write', self.on_grids_updated)
def on_grids_updated(self, *args):
self.data.NEW.set(self.data.NO.get())
self.data.NEW2.set(type(self.data.NO.get()))
app = SampleApp()
app.mainloop()
I also wondered why the type of list in PageOne is shown with some random numbers? thanks
You can use Variable which is the base class of StringVar, IntVar, etc.
Variable.get() does not convert the stored data like StringVar.get() or IntVar.get(). However it seems that list will be converted to tuple by TCL internally.
class Data:
def __init__(self):
self.Tot_grids = tk.IntVar()
self.NO = tk.Variable() # used Variable instead of StringVar
self.NEW = tk.StringVar()
self.NEW2 = tk.StringVar()
Also change the line
label4.config(text=type(nums))
to
label4.config(text=str(type(nums)))
will show the type correctly.

Adding line numbers to text widget using Tkinter

I have text box my_text on gui at location
my_text = Text(root, width=98, height=35, font=("Helvetica", 10), bg="cyan", fg="black")
my_text.grid(row=4, column=0, padx=(20, 50), pady=(20, 0), rowspan=3, sticky="e")
I want to add lines numbers to this text box using Bryan Oakley code here.
My code:
import tkinter as tk
from tkinter import *
root = Tk()
my_text = Text(root, width=98, height=35, font=("Helvetica", 10), bg="cyan", fg="black")
my_text.grid(row=4, column=0, padx=(20, 50), pady=(20, 0), rowspan=3, sticky="e")
text_file = open("sample.xml", 'r')
s = text_file.read()
my_text.delete("1.0", "end")
my_text.insert(END, s)
class TextLineNumbers(tk.Canvas):
def __init__(self, *args, **kwargs):
tk.Canvas.__init__(self, *args, **kwargs)
self.root = Tk()
self.textwidget = None
def attach(self, text_widget):
self.textwidget = text_widget
def redraw(self, *args):
'''redraw line numbers'''
self.delete("all")
i = self.textwidget.index("#0,0")
while True :
dline= self.textwidget.dlineinfo(i)
if dline is None: break
y = dline[1]
linenum = str(i).split(".")[0]
self.create_text(2,y,anchor="nw", text=linenum)
i = self.textwidget.index("%s+1line" % i)
def run(self):
self.root.mainloop()
linenos = TextLineNumbers()
linenos.attach(my_text)
linenos.redraw()
root.mainloop()
Code is not displaying line number. It is displaying just text. How to display linenumbers in text box? Thanks in advance.
You mentioned this great example, why not just modify it to suit your needs? I was curious and modified the Example class from given link by adding a button to call a function load_xml which loads files via filechooser, deletes the previous data in the CustomText widget and inserts the new data:
import tkinter as tk
from tkinter import filedialog
import os
class TextLineNumbers(tk.Canvas):
def __init__(self, *args, **kwargs):
tk.Canvas.__init__(self, *args, **kwargs)
self.textwidget = None
def attach(self, text_widget):
self.textwidget = text_widget
def redraw(self, *args):
'''redraw line numbers'''
self.delete("all")
i = self.textwidget.index("#0,0")
while True:
dline = self.textwidget.dlineinfo(i)
if dline is None:
break
y = dline[1]
linenum = str(i).split(".")[0]
self.create_text(2, y, anchor="nw", text=linenum)
i = self.textwidget.index("%s+1line" % i)
class CustomText(tk.Text):
def __init__(self, *args, **kwargs):
tk.Text.__init__(self, *args, **kwargs)
# create a proxy for the underlying widget
self._orig = self._w + "_orig"
self.tk.call("rename", self._w, self._orig)
self.tk.createcommand(self._w, self._proxy)
def _proxy(self, *args):
# let the actual widget perform the requested action
cmd = (self._orig,) + args
result = self.tk.call(cmd)
# generate an event if something was added or deleted,
# or the cursor position changed
if (args[0] in ("insert", "replace", "delete") or
args[0:3] == ("mark", "set", "insert") or
args[0:2] == ("xview", "moveto") or
args[0:2] == ("xview", "scroll") or
args[0:2] == ("yview", "moveto") or
args[0:2] == ("yview", "scroll")):
self.event_generate("<<Change>>", when="tail")
# return what the actual widget returned
return result
class Example(tk.Frame):
def __init__(self, *args, **kwargs):
tk.Frame.__init__(self, *args, **kwargs)
self.text = CustomText(self)
self.vsb = tk.Scrollbar(self, orient="vertical", command=self.text.yview)
self.text.configure(yscrollcommand=self.vsb.set)
self.text.tag_configure("bigfont", font=("Helvetica", "24", "bold"))
self.linenumbers = TextLineNumbers(self, width=30)
self.linenumbers.attach(self.text)
self.vsb.pack(side="right", fill="y")
self.linenumbers.pack(side="left", fill="y")
self.text.pack(side="right", fill="both", expand=True)
# new button to call load_xml and show status
self.load_button = tk.Button(root, text="Load file", command=self.load_xml)
self.load_button.pack(side="top")
self.text.bind("<<Change>>", self._on_change)
self.text.bind("<Configure>", self._on_change)
self.text.insert("end", "one\ntwo\nthree\n")
self.text.insert("end", "four\n", ("bigfont",))
self.text.insert("end", "five\n")
def _on_change(self, event):
self.linenumbers.redraw()
def load_xml(self):
"""Load any file, delete current text and insert new data"""
input_file = filedialog.askopenfilename(title="Load a textfile",
filetypes=(("XML", "*.xml"),
("Text", "*.txt"),
("All files", "*.*")),
initialdir=os.getcwd())
if input_file:
self.text.delete("1.0", "end")
self.load_button.config(text=f"Currently loaded: {input_file.split(os.sep)[-1]}")
with open(input_file, 'r') as f:
self.text.insert("end", f.read())
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(side="top", fill="both", expand=True)
root.mainloop()

Tkinter Python- function which can access data from other tabs

I would like to create a function in Main_Application which would access data from other tabs... how can i achieve it?
I was trying to access it by typing "Page_2.entry2.insert(0, "test")" but it returns Attribute error
I would appreciate any kind of help as i am struggling with it for some time already
class Main_Application(tk.Tk):
def __init__(self):
super().__init__()
self.title("HAT")
first_label = ttk.Label(self, text="lol").pack()
#Notebook
nb = ttk.Notebook(self)
nb.pack()
#Frames
p1 = tk.Frame(nb)
p2 = tk.Frame(nb)
p3 = tk.Frame(nb)
p4 = tk.Frame(nb)
nb.add(p1, text="Page1")
nb.add(p2, text="Page2")
nb.add(p3, text="Page3")
nb.add(p4, text="Page4")
Page_1(p1).pack()
Page_2(p2).pack()
def load_it_all(self):
print(Page_01(self).user_input.get())
Page_02.entry2.insert(0, "test")
# <HERE I WOULD LIKE TO CALL THE DATA FROM
#First one prints the data from Page_01 and second i would like to insert data in Page_02.entry2
class Page_1(ttk.Frame):
def __init__(self, container):
super().__init__(container)
#Stringvar
self.user_input = tk.StringVar()
#Labels
label = ttk.Label(self, text="HU3: ")
#Entries
entry = ttk.Entry(self, textvariable=self.user_input)
#Inserts
entry.insert(0, "4500")
#Buttons
button = ttk.Button(self, text="Apply", command=lambda: Main_Application.load_it_all(self))
#Geo
label.pack()
entry.pack()
button.pack()
def test(self):
print(self.user_input.get())
class Page_2(ttk.Frame):
def __init__(self, container):
super().__init__(container)
self.user_input = tk.StringVar()
label = ttk.Label(self, text="Trend from last cycle ")
#Entries
entry2 = ttk.Entry(self, textvariable=self.user_input)
#Inserts
# self.entry2.insert(0, "4500")
#Buttons
# button = ttk.Button(self, text="Apply", command=self.test2)
#Geo
label.pack()
entry2.pack()
# button.pack()
Your issues included
improperly initiating super
too many containers
randomly using ttk widgets
poor understanding of scope
naming syntax errors
unnecessary vars
Below is a working example of what you are trying to do
import tkinter as tk, tkinter.ttk as ttk
class Main(tk.Tk):
def __init__(self):
#this is how to properly init a super
tk.Tk.__init__(self)
#make notebook fill display
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
#Notebook
nb = ttk.Notebook(self)
nb.grid(row=0, column=0, sticky='nswe')
#keep a reference to the pages
self.p1 = Page_1(self)
self.p2 = Page_2(self)
#tabs
nb.add(self.p1, text="Page 1")
nb.add(self.p2, text="Page 2")
def load_it_all(self):
#use the page references to access and share data
self.p2.input = self.p1.input
class Page_1(tk.Frame):
#property
def input(self):
return self.userinput.get()
#input.setter
def input(self, value):
self.userinput.delete(0, 'end')
self.userinput.insert(0, value)
def __init__(self, master, **kwargs):
tk.Frame.__init__(self, master, **kwargs)
tk.Label(self, text="HU3: ").grid(row=0, column=0)
self.userinput = tk.Entry(self)
self.userinput.grid(row=0, column=1)
self.input="4500"
tk.Button(self, text="Apply", command=master.load_it_all).grid(row=0, column=2)
class Page_2(tk.Frame):
#property
def input(self):
return self.userinput.get()
#input.setter
def input(self, value):
self.userinput.delete(0, 'end')
self.userinput.insert(0, value)
def __init__(self, master, **kwargs):
tk.Frame.__init__(self, master, **kwargs)
tk.Label(self, text="Trend from last cycle ").grid(row=0, column=0)
self.userinput = tk.Entry(self)
self.userinput.grid(row=0, column=1)
if __name__ == "__main__":
root = Main()
root.geometry('800x600')
root.title("HAT")
root.mainloop()

Defining a global function at the beginning, but it needs variables not defined yet

I´ve been working on a bhaskara equation solver with Interface(tkinter) on python. I´ve watched some tutorials and I´ve split the Pages into classes. The basic idea of this application is the following:
It starts at StartPage, where the user clicks on the select values button and this opens up PageOne. At this page the user should type the desired values and click the select values button (I´m sorry, I couldn't find a way to save all the values at one, if you know how to do this too, please let me know). After the user saves the values, he goes back to StartPage and clicks the Calculate button. If all values are OK, it shows the result variable.
import tkinter as tk
from tkinter import ttk, END
import math
LARGE_FONT =("Verdana", 12)
def calculate():
global value_a
global value_b
global value_c
value_list = [value_a, value_b, value_c]
if "" in value_list:
return False
else:
delta = (int(value_b.get())**2) - 4*int(value_a.get())*int(value_c.get())
if delta >= 0:
delta_root = math.sqrt(delta)
bhask_pos = int(-value_b.get()) + (delta_root)/2*int(value_a.get())
bhask_neg = int(-value_b.get()) - (delta_root)/2*int(value_a.get())
global result
result = "The equation", int(value_a.get()), "x² +", int(value_b.get()), "x +", int(value_c.get()), "has the results ", int(bhask_pos), "and ", int(bhask_neg)
else:
pass
return True
class App(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self,*args, **kwargs)
#self.geometry("720x360")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_columnconfigure(0, weight=1)
container.grid_rowconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, PageOne):
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()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
button = ttk.Button(self, text="Insert values", command=lambda: controller.show_frame(PageOne))
button.pack(side="top", padx=10, pady=20, expand=False)
canvas = tk.Canvas(self, width=400, height=200, bg="#C0C0C0", bd="10")
canvas.pack(side="bottom", padx=10, pady=20, expand=False)
if calculate() == False:
canvas.create_text(30, 30, text="Error. Check if you selected all values")
elif calculate() == True:
canvas.create_text(30, 30, text=result)
else:
pass
calculation_button = ttk.Button(self, text="Calculate", command=calculate)
calculation_button.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
def get_entry_data_a():
global value_1
value_1 = int(value_a.get())
entry_a.delete(0, END)
print(value_1)#just for debugging
def get_entry_data_b():
global value_2
value_2 = int(value_b.get())
entry_b.delete(0, END)
print(value_2)
def get_entry_data_c():
global value_3
value_3 = int(value_c.get())
entry_c.delete(0, END)
print(value_3)
def event_data_a(event):
value_1 = int(value_a.get())
entry_a.delete(0, END)
print(value_1)
def event_data_b(event):
value_2 = int(value_b.get())
entry_b.delete(0, END)
print(value_2)
def event_data_c(event):
value_3 = int(value_c.get())
entry_c.delete(0, END)
print(value_3)
text_a = tk.Label(self, text="value from a:", padx=10, pady=10)
text_a.grid(row=1, column=1)
text_b = tk.Label(self, text="value from b:", padx=10, pady=10)
text_b.grid(row=2, column=1)
text_c = tk.Label(self, text="value from c", padx=10, pady=10)
text_c.grid(row=3, column=1)
value_a = tk.IntVar()
entry_a = tk.Entry(self, textvariable=value_a)
entry_a.grid(row=1, column=2)
entry_a.delete(0, END)
button_a = ttk.Button(self, text="Save value", command=get_entry_data_a)
button_a.grid(row=1, column=3, padx=10, pady=10)
value_b = tk.IntVar()
entry_b = tk.Entry(self, textvariable=value_b)
entry_b.grid(row=2, column=2)
entry_b.delete(0, END)
button_b = ttk.Button(self, text="Save value", command=get_entry_data_b)
button_b.grid(row=2, column=3, padx=10, pady=10)
value_c = tk.IntVar()
entry_c = tk.Entry(self, textvariable=value_c)
entry_c.grid(row=3, column=2)
entry_c.delete(0, END)
button_c = ttk.Button(self, text="Save value", command=get_entry_data_c)
button_c.grid(row=3, column=3,padx=10, pady=10)
entry_a.bind("<Return>", event_data_a)
entry_b.bind("<Return>", event_data_b)
entry_c.bind("<Return>", event_data_c)
back_button = ttk.Button(self, text="Return to Start Page", command=lambda:controller.show_frame(StartPage))
back_button.grid(row=5, column=2, padx=20, pady=20)
app = App()
app.mainloop()
The results should appear in the canvas, as well as a message error if the user does not select a value. My actual problem is that the canvas object is created in StartPage, so I need to define the function before the StartPage class (because I need the boolean result returned from the function calculate() to create the text in the canvas), but the actual values that the user chooses comes only at the end of the code. How is it possible to use those values? Where should I define the function calculate() in this case?
This is the error message:
line 10, in calculate
value_list = [value_a, value_b, value_c]
NameError: name 'value_a' is not defined
To get the globals working properly, just make sure to give them initial values before their first used. The easiest way to do this is to assign them default values at the module level. For example:
value_a = ""
value_b = ""
value_c = ""
def calculate():
global value_a
global value_b
global value_c
# ...
That should get your code working. But while Python supports globals, they're almost never the right choice. Look at the logic of your application and think of ways to use local scope more. One possibility is to set value_a, value_b, and value_c as instance variable in your App class, since it's accessible as controller in both frames.
For example:
def calculate(value_a, value_b, value_c):
value_list = [value_a, value_b, value_c]
# ...
class App(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self,*args, **kwargs)
self.value_a = ""
self.value_b = ""
self.value_c = ""
# ...
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
# ...
if calculate(controller.value_a, controller.value_b, controller.value_c):
# ...
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
def get_entry_data_a():
value_1 = int(controller.value_a.get())
entry_a.delete(0, END)
print(value_1)#just for debugging
# ...
controller.value_a = tk.IntVar()

TypeError Missing Positional Arguments? What is going on? --Python and Tkinter

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

Categories

Resources