I currently face a problem when I want to call a class A method inside a class B method. The code is running fine. However, the problem happen at line 73 in ImageProcessing.py where MainApplication.signup() is asking for parameter. This function is built for returning to the signup page. I am not sure if it is the right way to code like this. Please help me. I would appreciate your kindness.
*This is Display.py
import tkinter as tk
from tkinter import *
from PIL import ImageTk, Image
import os
import ImageProcessing
class MainApplication:
def __init__(self,master): # parent, *args, **kwargs):
self.master = master
self.frame = tk.Frame(self.master)
# Resize image
self.open_image = Image.open('images/log_icon.png')
self.resized_image = self.open_image.resize((170, 170), Image.ANTIALIAS)
# Define image
self.img = ImageTk.PhotoImage(self.resized_image)
self.bg1 = ImageTk.PhotoImage(Image.open('images/darkblue.png'))
self.lock = ImageTk.PhotoImage(Image.open('Icon/lock.ico'))
self.loginBtn = ImageTk.PhotoImage(Image.open('images/login-button.png'))
# Create labels and buttons
self.my_label = Label(master, image=self.bg1)
self.my_label.place(x=0, y=0, relwidth=1, relheight=1)
self.log_head = Label(master, image=self.img, bg="#1f1a30")
self.log_head.place(x=115, y=10)
self.lock_label = Label(master, image=self.lock, bg="#39304d")
self.lock_label.place(x=50, y=200, height=35, width=40)
self.username = Entry(master, font=("arial", 13), bg="#39304d", fg="white", borderwidth=0)
self.username.place(x=90, y=200, width=250, height=35)
self.login_btn = Button(master, image=self.loginBtn, borderwidth=0, bg="#1f1a30", activebackground="#1f1a30", command=self.login)
self.login_btn.place(x=35, y=300)
self.signup_label = Label(master, text="Don't have an account?", bg="#1f1a30", font=("times new roman", 10),
fg="white")
self.signup_label.place(x=110, y=380)
self.signup_btn = Button(master, text="Sign Up", borderwidth=0, bg="#1f1a30", font=("times new roman", 10, "underline"),
fg="#0df6e3", activebackground="#1f1a30", command=self.signup)
self.signup_btn.place(x=240, y=380)
self.forget_btn = Button(master, text="Forgot Your Password?", borderwidth=0, bg="#1f1a30",
font=("times new roman", 10),
fg="#0df6e3", activebackground="#1f1a30")
self.forget_btn.place(x=132, y=410)
def signup(self):
def open(filename):
os.chdir("C:\Python Projects\PyFYP") # file path
os.system('python ' filename) # run the python command on cmd to execute both windows
self.master.destroy()
open("Registration.py")
def login(self):
pass
def main_login():
App = tk.Tk()
App.title("Login")
App.iconbitmap('C:/Python Projects/PyFYP/Icon/snake2.ico')
App.resizable(False, False)
# Put TK Window screen to center
app_width = 390
app_height = 500
screen_width = App.winfo_screenwidth()
screen_height = App.winfo_screenheight()
sys_width = (screen_width / 2) - (app_width / 2)
sys_height = (screen_height / 2) - (app_height / 2)
App.geometry(f'{app_width}x{app_height} {int(sys_width)} {int(sys_height)}')
MainApplication(App)
App.mainloop()
if __name__ == "__main__":
main_login()
*This is ImageProcessing.py
import tkinter as tk
from tkinter import *
from tkinter import ttk, filedialog
from tkinter.filedialog import askopenfile
from PIL import ImageTk, Image
import cv2
import numpy as np
from tkinter import messagebox
import time
import Display
class ProcessImage():
def __init__(self, master): # parent, *args, **kwargs):
self.master = master
self.frame = tk.Frame(self.master)
self.bg = ImageTk.PhotoImage(Image.open('images/neon.png'))
self.Upload_Btn_img = ImageTk.PhotoImage(Image.open('images/upload_btn.png'))
self.proceed_Btn_img = ImageTk.PhotoImage(Image.open('images/proceed_btn.png'))
self.cancel_Btn_img = ImageTk.PhotoImage(Image.open('images/cancel_btn.png'))
self.reset_Btn_img = ImageTk.PhotoImage(Image.open('images/reset_btn.png'))
# Labels and Buttons
self.Img_process_background = tk.Label(master, image=self.bg)
self.Img_process_background.place(x=0, y=0, relwidth=1, relheight=1)
# OpenCV window name
self.windowName = "Selected Image"
# Attributes for setting coordinates
self.coordinate = np.zeros((3, 2), int)
self.counter = 0
self.file_path_name = "" # Uploaded image's file path
# Upload Image label
self.uploadImg_label = Label(master, text="Please upload your preference image here.", bg="#1f1a30", font=("arial", 12, "bold"), fg="white")
self.uploadImg_label.place(x=50, y=50)
self.uploadImg_note = Label(master, text="* Only jpg, jpeg, png, are allowed.", bg="#1f1a30", font=("arial", 8, "bold"), fg="grey")
self.uploadImg_note.place(x=50, y=75)
self.img_resize_note = Label(master, text="* Image will be resize to 900x500.", bg="#1f1a30",font=("arial", 8, "bold"), fg="grey")
self.img_resize_note.place(x=50, y=100)
self.txt_uploadImg = Entry(master, font=("arial", 10), bg="#39304d", fg="white", borderwidth=0)
self.txt_uploadImg.place(x=50, y=125, width=350, height=20)
# Create Buttons
self.upload_btn = tk.Button(master, image=self.Upload_Btn_img, command=self.Browsing, borderwidth=0, bg="#1f1a30",activebackground="#1f1a30")
self.upload_btn.place(x=170, y=175, width=120)
self.reset_Btn = Button(master, command=self.reset_it, image=self.reset_Btn_img, borderwidth=0, bg="#1f1a30",activebackground="#1f1a30")
self.reset_Btn.place(x=80, y=250, width=120)
self.cancel_btn = Button(master, command=self.cancel_it, image=self.cancel_Btn_img, borderwidth=0, bg="#1f1a30",activebackground="#1f1a30")
self.cancel_btn.place(x=260, y=250, width=120)
self.proceed_btn = Button(master, image=self.proceed_Btn_img, borderwidth=0, bg="#1f1a30",activebackground="#1f1a30", command=self.SetCoordinates)
self.proceed_btn.place(x=170, y=400, width=120)
def reset_it(self):
self.counter = 0
self.txt_uploadImg.delete(0, "end")
self.file_path_name = ""
messagebox.showinfo(title="Success", message="Points have been reset")
def cancel_it(self):
# Initialize variables
self.master.destroy()
self.counter = 0
self.file_path_name = ""
MainApplication.signup() # Return to sign up/register page
def SetCoordinates(self):
try:
self.read_img = cv2.imread(self.file_path_name) # read image
self.resized_img = cv2.resize(self.read_img, (900,500))
while True:
cv2.namedWindow(self.windowName)
cv2.imshow(self.windowName, self.resized_img)
cv2.setMouseCallback(self.windowName, self.PassPoints)
cv2.waitKey(1)
if self.counter == 3:
time.sleep(0.5)
messagebox.showinfo(title="Success", message="Points were marked successfully")
cv2.destroyWindow(self.windowName)
break
except:
messagebox.showerror(title="Error message", message="Image not found")
cv2.destroyWindow(self.windowName)
def PassPoints(self, event, x, y, flags, params):
global counter
if event == cv2.EVENT_LBUTTONDOWN:
self.coordinate[self.counter] = x, y
colorsB = self.resized_img[y, x, 0]
colorsG = self.resized_img[y, x, 1]
colorsR = self.resized_img[y, x, 2]
self.counter = 1
print("x= " str(x) " y= " str(y))
print('Red: ' str(colorsR) ' ' 'Green: ' str(colorsG) ' ' 'Blue: ' str(colorsB))
def Browsing(self):
img_file = filedialog.askopenfile(mode='r', filetypes=[('JPEG', '*.jpeg'), ('JPEG', '*.jpg'), ('PNG', '*.png')])
global file_path_name
def setImageNameInput(self, text):
self.txt_uploadImg.delete(0, "end")
self.txt_uploadImg.insert(0, text)
# img_file.name: the .name used to get the file path of the uploaded image
if img_file:
setImageNameInput(self,img_file.name)
self.file_path_name = img_file.name
def main_image_process():
Imageprocess_page = tk.Tk()
Imageprocess_page.title("Image processing")
Imageprocess_page.iconbitmap('C:/Python Projects/PyFYP/Icon/snake2.ico')
Imageprocess_page.resizable(False, False)
app_width = 900
app_height = 500
screen_width = Imageprocess_page.winfo_screenwidth()
screen_height = Imageprocess_page.winfo_screenheight()
sys_width = (screen_width / 2) - (app_width / 2)
sys_height = (screen_height / 2) - (app_height / 2)
Imageprocess_page.geometry(f'{app_width}x{app_height} {int(sys_width)} {int(sys_height)}')
ProcessImage(Imageprocess_page)
Imageprocess_page.mainloop()
if __name__ == "__main__":
main_image_process()
*This is the error TypeError: signup() missing 1 required positional argument: 'self'
CodePudding user response:
You cannot call the method, because it is not a static / class method but instead the method of an instance / object of the class MainApplication.
This means that the cancel_it
method's parameter self
expects an instance of the class MainApplication
to function properly but by calling MainApplication.cancel_it()
it receives the class instead as argument and therefore throws an exception.
You could easily call it, by passing a reference to the Mainapplication-instance to your cancel_it method.
Assuming that:
self.master
in the ProcessImage
classe's __init__
method is a reference to the Main-Application instance, the solution would look like this:
def cancel_it(self):
# Initialize variables
self.master.destroy()
self.counter = 0
self.file_path_name = ""
self.master.signup() # Return to sign up/register page
Otherwise, the method-adjustment might look something like this:
def cancel_it(self, main_application):
# Initialize variables
self.master.destroy()
self.counter = 0
self.file_path_name = ""
main_application.signup() # Return to sign up/register page
with main_application
being the reference to the MainApplication, which would have to passed as argument.
If the latter case should be true - Keep in mind that you will also have to adjust the command
of the button responsible for calling the function, so that it actually passes the argument main_application
.