簡體   English   中英

類型錯誤:get() 缺少 1 個必需的位置參數:'self'/Tkinter 回調中的異常

[英]TypeError: get() missing 1 required positional argument: 'self' / Exception in Tkinter callback

所以我一直在做這個項目,由於某種原因,這個錯誤不斷彈出:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1892, in __call__
    return self.func(*args)
  File "D:\KPI\minesweeper\main.py", line 198, in login_verify
    username_1 = username_verify.get()
TypeError: get() missing 1 required positional argument: 'self'

起初我嘗試將 combine.pack 和 grid 合並到一個 class 中,但出現了錯誤,所以我將其從 class 中刪除。 然后我嘗試將this.pack這段代碼添加到新的class中,但還是有問題。 TBO,這段代碼有點來自不同代碼的不同元素,所以我可能只是感到困惑。

這是一個代碼:

from random import shuffle
from tkinter import *
from tkinter.messagebox import showinfo
import os

colors = {
    0: 'white',
    1: 'blue',
    2: 'green',
    3: 'red',
    4: 'purple',
    5: 'maroon',
    6: 'turquoise',
    7: 'black',
    8: 'gray',
}


class Autherisation:
    def __init__(self, master):
        self.screen = screen


def delete2():
    screen3.destroy()


def delete3():
    screen4.destroy()


def delete4():
    screen5.destroy()

def login_sucess():
    global screen3
    screen3 = Toplevel(screen)
    screen3.title('Sucess')
    screen3.geometry('150x100')
    Label(screen3, text='Login sucess').pack()
    Button(screen3, text='OK', command=delete2).pack()


def password_not_recognised():
    global screen4
    screen4 = Toplevel(screen)
    screen4.title('Sucess')
    screen4.geometry('150x100')
    Label(screen4, text='Password not recognised').pack()
    Button(screen4, text='OK', command=delete3).pack()


def user_not_found():
    global screen5
    screen5 = Toplevel(screen)
    screen5.title('Sucess')
    screen5.geometry('150x100')
    Label(screen5, text='User not found').pack()
    Button(screen5, text='OK', command=delete4).pack()


def register_user():
    username_info = username_.get()
    password_info = password_.get()

    file = open(username_info, "w")
    file.write(username_info + '\n')
    file.write(password_info)
    file.close()

    username_entry.delete(0, END)
    password_entry.delete(0, END)

    Label(screen_1, text='Registration successful!', fg='green', font=('calibri', 11)).pack()


def login_verify():
    username_1 = username_verify.get()
    password_1 = password_verify.get()
    username_entry1.delete(0, END)
    password_entry1.delete(0, END)

    list_of_files = os.listdir()
    if username_1 in list_of_files:
        file1 = open(username_1, 'r')
        verify = file1.read().splitlines()
        if password_1 in verify:
            login_sucess()
        else:
            password_not_recognised()
    else:
        user_not_found()


def register():
    global screen_1
    screen_1 = Toplevel(screen)
    screen_1.title("Register")
    screen_1.geometry('300x250')

    global username_
    global password_
    global username_entry
    global password_entry
    username_ = StringVar()
    password_ = StringVar()

    Label(screen_1, text='Please enter details below').pack()
    Label(screen_1, text='').pack()
    Label(screen_1, text='Username * ').pack()
    username_entry = Entry(screen_1, textvariable=username_)
    username_entry.pack()
    Label(screen_1, text='Password * ').pack()
    password_entry = Entry(screen_1, textvariable=password_)
    password_entry.pack()
    Button(screen_1, text='Register', width=10, height=1, command=register_user).pack()


def login():
    global screen_2
    screen_2 = Toplevel(screen)
    screen_2.title("Login")
    screen_2.geometry('300x250')
    Label(screen_2, text='Please enter details below to login').pack()
    Label(screen_2, text='').pack()

    global username_verify
    global password_verify

    username_verify = StringVar
    password_verify = StringVar
    global username_entry1
    global password_entry1
    Label(screen_2, text='Username * ').pack()
    username_entry1 = Entry(screen_2, textvariable=username_verify)
    username_entry1.pack()
    Label(screen_2, text='').pack()
    Label(screen_2, text='Password * ').pack()
    password_entry1 = Entry(screen_2, textvariable=password_verify)
    password_entry1.pack()
    Label(screen_2, text='').pack()
    Button(screen_2, text='Login', width=10, height=1, command=login_verify).pack()


def login_screen():
    global screen
    screen = Tk()
    screen.geometry("300x250")
    screen.title("Minesweeper")
    Label(text='MineSweeper', bg='grey', width='300', height='2', font=("calibri", 13)).pack()
    Label(text='').pack()
    Button(text='Login', height='2', width='30', command=login).pack()
    Label(text='').pack()
    Button(text="Register", height='2', width='30', command=register).pack()

    screen.mainloop()


login_screen()


class MyButton(tk.Button):

    def __init__(self, master, x, y, number=0, *args, **kwargs):
        super(MyButton, self).__init__(master, width=3, font='Calibri 15 bold', *args, **kwargs)
        self.x = x
        self.y = y
        self.number = number
        self.is_mine = False
        self.count_bomb = 0
        self.is_open = False

    def __repr__(self):
        return f'MyButton{self.x} {self.y} {self.number} {self.is_mine}'


class MineSweeper:
    window = tk.Tk()
    window.title("MineSweeper")
    row_ = 16
    columns_ = 16
    mines = 60
    IS_GAME_OVER = False
    IS_FIRST_CLICK = True

    def __init__(self):
        self.buttons = []

        for i in range(MineSweeper.row_ + 2):
            temp = []
            for j in range(MineSweeper.columns_ + 2):
                btn = MyButton(MineSweeper.window, x=i, y=j)
                btn.config(command=lambda button=btn: self.click(button))
                btn.bind('<Button-3>', self.right_click)
                btn.bind('<Double-Button-1>', self.double_button_click)
                temp.append(btn)
            self.buttons.append(temp)

    def right_click(self, event):
        if MineSweeper.IS_GAME_OVER:
            return
        cur_btn = event.widget
        if cur_btn['state'] == 'normal':
            cur_btn['state'] = 'disabled'
            cur_btn['text'] = '🚩'
            cur_btn['disabledforeground'] = 'red'
        elif cur_btn['state'] == '🚩':
            cur_btn['text'] = ''
            cur_btn['state'] = 'normal'

    def double_button_click(self, event):
        if MineSweeper.IS_GAME_OVER:
            return
        cur_btn = event.widget
        if cur_btn['state'] == 'normal':
            cur_btn['state'] = 'disabled'
            cur_btn['text'] = '?'
            cur_btn['disabledforeground'] = 'red'
        elif cur_btn['state'] == '?':
            cur_btn['text'] = ''
            cur_btn['state'] = 'normal'

    def click(self, clicked_button: MyButton):

        if MineSweeper.IS_GAME_OVER:
            return

        if MineSweeper.IS_FIRST_CLICK:
            self.insert_mines(clicked_button.number)
            self.count_mines_in_buttons()
            self.print_buttons()
            MineSweeper.IS_FIRST_CLICK = False

        print(clicked_button)
        if clicked_button.is_mine:
            clicked_button.config(text="*", background='red', disabledforeground='black')
            clicked_button.is_open = True
            MineSweeper.IS_GAME_OVER = True
            showinfo('Game over', 'Вы проиграли!')
            for i in range(1, MineSweeper.row_ + 1):
                for j in range(1, MineSweeper.columns_ + 1):
                    btn = self.buttons[i][j]
                    if btn.is_mine:
                        btn['text'] = '*'
        else:
            color = colors.get(clicked_button.count_bomb, 'black')
            if clicked_button.count_bomb:
                clicked_button.config(text=clicked_button.count_bomb, disabledforeground=color)
                clicked_button.is_open = True
            else:
                self.breadth_first_search(clicked_button)
        clicked_button.config(state='disabled')
        clicked_button.config(relief=tk.SUNKEN)

    def breadth_first_search(self, btn: MyButton):
        queue = [btn]
        while queue:

            cur_bth = queue.pop()
            color = colors.get(cur_bth.count_bomb, 'black')
            if cur_bth.count_bomb:
                cur_bth.config(text=cur_bth.count_bomb, disabledforeground=color)
            else:
                cur_bth.config(text='', disabledforeground=color)
            cur_bth.is_open = True
            cur_bth.config(state='disabled')
            cur_bth.config(relief=tk.SUNKEN)

            if cur_bth.count_bomb == 0:
                x, y = cur_bth.x, cur_bth.y
                for dx in [-1, 0, 1]:
                    for dy in [-1, 0, 1]:
                        # if not abs(dx - dy) == 1:
                        #     continue

                        next_btn = self.buttons[x + dx][y + dy]
                        if not next_btn.is_open and 1 <= next_btn.x <= MineSweeper.row_ and 1 <= next_btn.y <= MineSweeper.columns_ and next_btn not in queue:
                            queue.append(next_btn)

    def reload(self):
        [child.destroy() for child in self.window.winfo_children()]
        self.__init__()
        self.create_widgets()
        MineSweeper.IS_FIRST_CLICK = True
        MineSweeper.IS_GAME_OVER = False

    def create_username_login(self):

        win_log_in = tk.Toplevel(self.window)
        win_log_in.wm_title("Log in/sign in")
        tk.Label(win_log_in, text='Login').grid(row=0, column=0)
        login_entrys = tk.Entry(win_log_in)
        login_entrys.grid(row=0, column=1, padx=20, pady=20)
        tk.Label(win_log_in, text='Password').grid(row=1, column=0)
        password_entrys = tk.Entry(win_log_in)
        password_entrys.grid(row=1, column=1, padx=20, pady=20)
        my_file = open('user.txt', 'w')
        my_file.write('login_entry')
        my_file.write('password_entry')
        # with open("file.text", "r") as file:
        #     data = file.readlines()
        #     for line in data:
        #         word = line.split()
        #         print(word)

    def create_widgets(self):
        menubar = tk.Menu(self.window)
        self.window.config(menu=menubar)

        settings_menu = tk.Menu(menubar, tearoff=0)

        settings_menu.add_command(label='Save')
        settings_menu.add_command(label='Log in', command=self.create_username_login)
        settings_menu.add_command(label='Start over', command=self.reload)
        settings_menu.add_command(label='Finish', command=self.window.destroy)
        menubar.add_cascade(label='File', menu=settings_menu)

        settings_menu = tk.Menu(menubar, tearoff=0)

        settings_menu.add_command(label='Novice')
        settings_menu.add_command(label='Amateur')
        settings_menu.add_command(label='Professional')
        menubar.add_cascade(label='Mode', menu=settings_menu)

        count = 1
        for i in range(1, MineSweeper.row_ + 1):
            for j in range(1, MineSweeper.columns_ + 1):
                btn = self.buttons[i][j]
                btn.number = count
                btn.grid(row=i, column=j, stick='NWES')
                count += 1

        for i in range(1, MineSweeper.row_ + 1):
            tk.Grid.rowconfigure(self.window, i, weight=1)

        for j in range(1, MineSweeper.columns_ + 1):
            tk.Grid.columnconfigure(self.window, i, weight=1)

    def open_all_buttons(self):
        for i in range(MineSweeper.row_ + 2):
            for j in range(MineSweeper.columns_ + 2):
                btn = self.buttons[i][j]
                if btn.is_mine:
                    btn.config(text="*", background='red', disabledforeground='black')
                elif btn.count_bomb in colors:
                    color = colors.get(btn.count_bomb, 'black')
                    btn.config(text=btn.count_bomb, foreground=color)

    def start(self):

        self.create_widgets()
        # self.login_screen()
        # self.open_all_buttons()
        # self.create_username_login()
        MineSweeper.window.mainloop()

    def print_buttons(self):
        for i in range(1, MineSweeper.row_ + 1):
            for j in range(1, MineSweeper.columns_ + 1):
                btn = self.buttons[i][j]
                if btn.is_mine:
                    print("B", end='')
                else:
                    print(btn.count_bomb, end='')
            print()

    def insert_mines(self, number: int):
        index_mines = self.get_mines_places(number)
        print(index_mines)
        for i in range(1, MineSweeper.row_ + 1):
            for j in range(1, MineSweeper.columns_ + 1):
                btn = self.buttons[i][j]
                if btn.number in index_mines:
                    btn.is_mine = True

    def count_mines_in_buttons(self):
        for i in range(1, MineSweeper.row_ + 1):
            for j in range(1, MineSweeper.columns_ + 1):
                btn = self.buttons[i][j]
                count_bomb = 0
                if not btn.is_mine:
                    for row_dx in [-1, 0, 1]:
                        for col_dx in [-1, 0, 1]:
                            neighbour = self.buttons[i + row_dx][j + col_dx]
                            if neighbour.is_mine:
                                count_bomb += 1
                btn.count_bomb = count_bomb

    @staticmethod
    def get_mines_places(exclude_number: int):
        indexes = list(range(1, MineSweeper.columns_ * MineSweeper.row_ + 1))
        print(f" {exclude_number}")
        indexes.remove(exclude_number)
        shuffle(indexes)
        return indexes[:MineSweeper.mines]


game = MineSweeper()
game.start()

快速回答

在第 198 行,您執行username_verify.get() ,這通常很好,假設 username_verify 是tk.StringVar 如果我們向下滾動,我們可以找到 username_verify 的定義如下

global username_verify
username_verify = StringVar

如果查看文檔,可以看到 StringVar 應該像這樣初始化

string_var = tk.StringVar(container, value, name)

您缺少包含構建實際 StrinVar 所需信息的括號。 這意味着您的 username_verify 只是指向 class 的指針,而不是所述 class 的實際實例。

更多技術細節

在創建實例時,python 創建一個self ,其中包含該實例以及該方法的所有唯一值。 class 純粹是方法和屬性名稱的模板。 創建 class 方法時,您會看到始終將self作為第一個參數。 Python 在調用方法時隱式添加 self 以引用調用它的實例。 這個 self 使您可以訪問此實例的唯一值。 (有一些例外,即 class 方法和 static 方法,但為了簡單起見,我不會介紹這些)

在您的代碼中,您沒有創建新實例。 這意味着沒有保留 memory 空間,並且永遠不會分配self 當您調用方法get()時, python 期望self被傳遞。 由於沒有實例,因此缺少此參數並導致您的錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM