How to inherit a class from another file/module? - python

I have two classes and am trying to inherit the class in one file from the class in another. However, my problem occurs when I try to put account_validation in another file, and inherit it in my PageTwo class. I am subject to the error:
Traceback (most recent call last):
File "C:\Users\stecd\Desktop\NEA - topLevel - client server\Frontend - Copy.py", line 1949, in <module>
customerEnd = selfService()
File "C:\Users\stecd\Desktop\NEA - topLevel - client server\Frontend - Copy.py", line 49, in __init__
self.frame = F(self.container, self)
File "C:\Users\stecd\Desktop\NEA - topLevel - client server\Frontend - Copy.py", line 91, in __init__
validation.account_validation.__init__(self)
TypeError: __init__() missing 2 required positional arguments: 'parent' and 'controller'
My code:
#Inheriting class from same file attempt
#file.py
class account_validation():
def __init__(self):
self.test = 'test2'
class PageTwo(tk.Frame,
validation.account_validation):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
account_validation.__init__(self)
print(self.test)
#inheriting class from another file
#validation.py
class account_validation():
def __init__(self):
self.test = 'test2'
#file.py
import validation
class PageTwo(tk.Frame, account_validation):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
account_validation.__init__(self)
print(self.test)

Inheriting from the same file.
import tkinter as tk
class account_validation:
def __init__(self):
self.test = 'test'
class PageTwo(tk.Frame, account_validation):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
account_validation.__init__(self)
print(self.test)
parent = tk.Tk()
page = PageTwo(parent, 'test')
parent.mainloop()
Inheriting from a different file. Assuming it's in the same path and under the name validation.py.
import tkinter as tk
from validation import account_validation
class PageTwo(tk.Frame, account_validation):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
account_validation.__init__(self)
print(self.test)
parent = tk.Tk()
page = PageTwo(parent, 'test')
parent.mainloop()
and in the file validation.py.
class account_validation:
def __init__(self):
self.test = 'test'

Related

Getting the Missing positional argument error

from src.view import *
from src.view import View
from src.model import Model
from pubsub import pub
import tkinter
from tkinter import *
class Controller:
def __init__(self, model, view):
# Variables
self.model = Model(controller=self) #point to Model Object
self.view = View(controller=self) #point to view object
def uploadAction(self, audios):
for audio in audios:
path = os.path.split(audio)
audio = path[1]
self.view.add_audio(audio)
`Model file`
class Model:
def __init__(self, controller):
self.controller = controller
`View file`
class View:
def __init__(self, container, controller):
self.controller = controller
self.annotation_box = None
super().__init__(container)
self.setup()
# set the controller
# self.controller = None
def setup(self):
#this class will run first
#calling the methos to setup the user interface
self.create_menu()
self.create_panedwindow()
self.create_audio_frame()
self.create_transcript_frame()
self.create_annotation_frame()
self.setup_menu()
self.setup_panedwindow()
self.setup_audio_frame()
self.setup_transcript_frame()
self.setup_annotation_frame()
`Main file`
from tkinter import *
from src.view import View
from src.model import Model
from src.controller import Controller
if __name__ == '__main__':
main_window = Tk()
main_window.geometry('1400x800')
main_window.title("Interview Elicitation Tool")
# controller = Controller(main_window)
view = View(Controller)
model = Model(Controller)
controller = Controller(model, view)
main_window.mainloop()
`
I am getting
Traceback (most recent call last):
File "C:\Users\santh\PycharmProjects\pythonProject\MVC-IET\src\main.py", line 13, in
view = View(Controller)
TypeError: View.init() missing 1 required positional argument: 'controller'
I tried to add controller=self in main.py also it is not working.
i am new to python. I don't know what to do

Get variable from parent using container class

I have Tkinter main class with a notebook:
class MainApplication(tk.Tk):
def __init__(self):
super().__init__()
self.color_widget = '#1B608E'
self.notebook = ttk.Notebook(self)
self.Page1 = Page1(self.notebook)
self.Page2 = Page2(self.notebook)
self.notebook.add(self.Page1, text='PCE Franchisés')
self.notebook.add(self.Page2, text='PVC Franchisés')
For each page of the notebook, I have a class defined as container:
class Page1(ttk.Frame):
def __init__(self, container):
super().__init__(container)
color = MainApplication.color_widget
self.label_INPUT = tk.Label(self, text='Settings', color=color,
)
self.label_INPUT.place(relx=0.03, rely=0.04)
class Page2(ttk.Frame):
def __init__(self, container):
super().__init__(container)
In each Page I want get the value of the variale color_widget defined in Main class. I tried MainApplication.color_widegt but it didn't work.
The simple way is to pass the instance of MainApplication to those pages, so that those pages can access the instance variable color_widget via the passed instance:
import tkinter as tk
from tkinter import ttk
class MainApplication(tk.Tk):
def __init__(self):
super().__init__()
self.geometry('800x600')
self.color_widget = '#1B608E'
self.notebook = ttk.Notebook(self)
self.notebook.pack(fill='both', expand=1)
self.Page1 = Page1(self.notebook, self) # pass instance of MainApplication as well
self.Page2 = Page2(self.notebook, self)
self.notebook.add(self.Page1, text='PCE Franchisés')
self.notebook.add(self.Page2, text='PVC Franchisés')
class Page1(ttk.Frame):
# added controller argument
def __init__(self, container, controller):
super().__init__(container)
self.controller = controller
# access MainApplication.color_widget
color = controller.color_widget
self.label_INPUT = tk.Label(self, text='Settings', fg=color)
self.label_INPUT.place(relx=0.03, rely=0.04, anchor='nw')
class Page2(ttk.Frame):
def __init__(self, container, controller):
super().__init__(container)
self.controller = controller
MainApplication().mainloop()

How to pass a data between different classes defined for tabs in my tkinter GUI?

I have this code below, and I want to pass variable n in class Data to be used in class tab1 and be used as the textvariable of entry1. however, I get this error:
AttributeError: 'dict' object has no attribute 'n'
or in general, I want to be able to pass variables between tabs.
import tkinter as tk
from tkinter import ttk
class Data:
def __init__(self):
self.n = tk.IntVar()
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.minsize(400, 400)
self.maxsize(400, 400)
self.my_notebook = ttk.Notebook(self)
self.my_notebook.pack(fill="both", expand=True)
self.app_data = {}
lst = [tab1, tab2, tab3]
for N, F in enumerate(lst):
tab = F(self.my_notebook, self.app_data)
self.my_notebook.add(tab, text="Tab"+str(N+1))
self.data = Data()
class tab1(tk.Frame):
def __init__(self, parent, data):
super().__init__(parent)
self.data = data
entry1 = tk.Entry(self, textvariable=data.n)
entry1.pack()
class tab2(tk.Frame):
def __init__(self, parent, data):
super().__init__(parent)
self.data = data
label2 = tk.Label(self, text="Tab2")
label2.pack()
class tab3(tk.Frame):
def __init__(self, parent, data):
super().__init__(parent)
self.data = data
label3 = tk.Label(self, text="Tab3")
label3.pack()
app = SampleApp()
app.mainloop()
You never create an instance of Data. Instead, you're initializing self.data to an empty dictionary. You need to create an instance of Data and pass that to the tabs.
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
...
self.app_data = Data()
...

Problem with Tkinter - Inheritance problems

I'm starting to work with classes with a Tkinter app, but I don't seem to understand how classes work, especially the relationship parent-controller. As you can see in the code down below, I was planning to have an outer class for a whole section, then 4 inner classes for every section within that frame. However, I cannot call those classes from the initial frame. Is there any better way to do this? What is it that I'm doing wrong?
class MainScreenFrameCenter(tk.Frame):
def __init__(self, parent, controller,*args,**kwargs):
tk.Frame.__init__(self,parent, bg="white",height=680, width=640,highlightbackground="black", highlightthickness=1)
self.controller = controller
self.pack(side="top", fill="both", expand=True)
self.widgets_nw = MainScreenFrameCenterNW(parent=self,controller=self)
self.widgets_sw = MainScreenFrameCenterSW(parent=self,controller=self)
self.widgets_ne = MainScreenFrameCenterNE(parent=self,controller=self)
self.widgets_se = MainScreenFrameCenterSE(parent=self,controller=self)
class MainScreenFrameCenterNW(tk.Frame):
def __init__(self, parent, controller,*args,**kwargs):
tk.Frame.__init__(self,parent,height=350,width=640,bg="white",highlightbackground="black",highlightthickness=1)
self.controller = controller
self.grid(row=0,column=0,sticky="nsew")
class MainScreenFrameCenterSW(tk.Frame):
def __init__(self, parent, controller,*args,**kwargs):
tk.Frame.__init__(self,parent,height=350,width=640,bg="white",highlightbackground="black",highlightthickness=1)
self.controller = controller
self.grid(row=1,column=0,sticky="nsew")
class MainScreenFrameCenterNE(tk.Frame):
def __init__(self, parent, controller,*args,**kwargs):
tk.Frame.__init__(self,parent,height=350,width=640,bg="white",highlightbackground="black",highlightthickness=1)
self.controller = controller
self.grid(row=0,column=1,sticky="nsew")
class MainScreenFrameCenterSE(tk.Frame):
def __init__(self, parent, controller,*args,**kwargs):
tk.Frame.__init__(self,parent,height=350,width=640,bg="white",highlightbackground="black",highlightthickness=1)
self.controller = controller
self.grid(row=1,column=1,sticky="nsew")
You need to move all of the class definitions to global scope by putting them all at the same level of indentation.
class MainScreenFrameCenter(tk.Frame):
...
class MainScreenFrameCenterNW(tk.Frame):
...
class MainScreenFrameCenterSW(tk.Frame):
...
class MainScreenFrameCenterNE(tk.Frame):
...
class MainScreenFrameCenterSE(tk.Frame):
...
It seems you are attempting to make a small grid. Classes are generally not nested inside of another class. If you create a class that represents 1 grid cell, you can use a loop to create a grid from it.
import tkinter as tk
class Cell(tk.Frame):
def __init__(self, master, column:int=0, row:int=0, **kwargs):
kwargs = {**{'bg':'white', 'highlightbackground':'black','highlightthickness':1}, **kwargs}
tk.Frame.__init__(self, master, **kwargs)
self.grid(column=column, row=row, sticky='nswe')
class App(tk.Tk):
def __init__(self, **kwargs):
tk.Tk.__init__(self)
self.configure(**kwargs)
cols = 2
for i in range(cols):
self.grid_columnconfigure(i, weight=1)
rows = 2
for i in range(rows):
self.grid_rowconfigure(i, weight=1)
for i, c in enumerate(['nw', 'ne', 'sw', 'se']):
self.__dict__[f'widgets_{c}'] = Cell(self, i%cols, i//cols)
self.widgets_nw['background'] = 'red'
if __name__ == '__main__':
root = App(background="white", highlightbackground="black", highlightthickness=1)
root.geometry('640x680+300+300')
root.title('not Can is Should Example')
root.mainloop()

QWidget not deleted with parent window

Using the below code, the __del__ method of my Preview widget never gets called. If I uncomment the "del window" line, it does. Why?
#!/usr/bin/env python
from PyQt4 import QtGui
class Preview(QtGui.QWidget):
def __init__(self, parent):
QtGui.QWidget.__init__(self, parent)
def __del__(self):
print("Deleting Preview")
class PreviewWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.widget = Preview(self)
self.setCentralWidget(self.widget)
def __del__(self):
print("Deleting PreviewWindow")
if __name__ == "__main__":
app = QtGui.QApplication(["Dimension Preview"])
window = PreviewWindow()
window.show()
app.exec()
# del window
If a QObject subclass has a parent, then Qt will delete it when the parent is deleted. On the other hand, if a QObject subclass has no parent, it will (eventually) be deleted by python.
Hopefully this example will make things somewhat clearer:
from PyQt4 import QtGui
class Widget(QtGui.QWidget):
def __init__(self, parent):
QtGui.QWidget.__init__(self, parent)
self.destroyed.connect(self.handleDestroyed)
def __del__(self):
print ('__del__:', self)
def handleDestroyed(self, source):
print ('destroyed:', source)
class Foo(Widget):
def __init__(self, parent):
Widget.__init__(self, parent)
class Bar(Widget):
def __init__(self, parent):
Widget.__init__(self, parent)
class Window(Widget):
def __init__(self, parent=None):
Widget.__init__(self, parent)
self.foo = Foo(self)
self.bar = Bar(None)
if __name__ == "__main__":
app = QtGui.QApplication([__file__, '-widgetcount'])
window = Window()
window.show()
app.exec_()
Which outputs:
__del__: <__main__.Window object at 0x88f514c>
destroyed: <__main__.Foo object at 0x88f5194>
__del__: <__main__.Bar object at 0x88f51dc>
Widgets left: 0 Max widgets: 4
EDIT
On second thoughts, it appears that there may be a bug (or at least a difference in behaviour) with some versions of PyQt4.
As a possible workaround, it seems that creating two python names for the main widget and then explicitly deleting each of them may help to ensure that both the C++ and python sides of the object get destroyed.
If the following line is added to the above script:
tmp = window; del tmp, window
Then the output becomes:
__del__: <__main__.Window object at 0x8d3a14c>
__del__: <__main__.Foo object at 0x8d3a194>
__del__: <__main__.Bar object at 0x8d3a1dc>
Widgets left: 0 Max widgets: 4

Categories

Resources