如何调用 class A 方法 inside class B 方法 in Python

How to call class A method inside class B method in Python

当我想在 class B 方法中调用 class A 方法时,我目前遇到了一个问题。代码 运行 没问题。但是,问题发生在 ImageProcessing.py 中的第 73 行,其中 MainApplication.signup() 要求参数。此函数是为返回注册页面而构建的。我不确定这样编码是否正确。请帮我。我将不胜感激。

*这是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()

*这是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()

*这是错误 TypeError: signup() 缺少 1 个必需的位置参数:'self'

您不能调用该方法,因为它不是静态/class方法,而是实例/对象[=的方法class MainApplication.

的 45=]

这意味着 cancel_it 方法的参数 self 期望 class MainApplication 的实例正常运行,但是通过调用 MainApplication.cancel_it() 它接收class 而不是 作为参数并且 因此抛出异常 .

您可以轻松调用它,只需将 reference 传递给 Mainapplication-instance 给您的 cancel_it方法.

假设:

self.master

ProcessImage classe的__init__方法是对Main-Application实例的引用,解决方案看起来像这样:

  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

否则,method-adjustment 可能看起来像这样:

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

其中 main_application 是对 MainApplication 的引用,它必须作为参数传递。 如果后一种情况应该成立 - 请记住,您还必须调整负责调用该函数的按钮的 command,以便它实际传递参数 main_application.