Pystray с tkinter TypeError: принимает 1 позиционный аргумент, но дано 2

Обычно, когда я кодирую без объектно-ориентированной программы, моя программа tkinter, например:

from pystray import MenuItem as item
import pystray
from PIL import Image
import tkinter as tk

window = tk.Tk()
window.title("Welcome")

def quit_window(icon, item):
    icon.stop()
    window.destroy()

def show_window(icon, item):
    icon.stop()
    window.after(0,window.deiconify)

def withdraw_window():  
    window.withdraw()
    image = Image.open("image.ico")
    menu = (item('Quit', quit_window), item('Show', show_window))
    icon = pystray.Icon("name", image, "title", menu)
    icon.run()

window.protocol('WM_DELETE_WINDOW', withdraw_window)
window.mainloop()

Я не получаю никаких ошибок, все работает. Но когда я кодирую свою программу с такими объектами, как:

from pystray import MenuItem as item
import pystray
from PIL import Image
import tkinter as tk
class Program:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("Welcome")
        self.window.protocol('WM_DELETE_WINDOW', self.withdraw_window)
        self.window.mainloop()

    def quit_window(self):
        self.icon.stop()
        self.window.destroy()

    def show_window(self):
        self.icon.stop()
        self.window.after(0, self.window.deiconify)

    def withdraw_window(self):
        self.window.withdraw()
        image = Image.open("microphone.ico")
        menu = (item('Quit', self.quit_window), item('Show', self.show_window))
        self.icon = pystray.Icon("name", image, "title", menu)
        self.icon.run()

run=Program()

когда я нажимаю на выход. Я получаю следующую ошибку:

An error occurred when calling message handler
Traceback (most recent call last):
  File "D:\PythonInterpreter\Python37-32\lib\site-packages\pystray\_win32.py", line 378, in _dispatcher
    uMsg, lambda w, l: 0)(wParam, lParam) or 0)
  File "D:\PythonInterpreter\Python37-32\lib\site-packages\pystray\_win32.py", line 198, in _on_notify
    descriptors[index - 1](self)
  File "D:\PythonInterpreter\Python37-32\lib\site-packages\pystray\_base.py", line 240, in inner
    callback(self)
  File "D:\PythonInterpreter\Python37-32\lib\site-packages\pystray\_base.py", line 327, in __call__
    return self._action(icon, self)
  File "D:\PythonInterpreter\Python37-32\lib\site-packages\pystray\_base.py", line 421, in wrapper1
    return action(icon)
TypeError: quit_window() takes 1 positional argument but 2 were given

Как я показал в двух приведенных выше примерах, проблема связана с пакетом pystray. Может кто поможет?


person pigman    schedule 18.03.2019    source источник
comment
В вашей исходной программе ваша функция quit_window принимает два аргумента. В вашем классе вы передаете только self в своем методе класса.   -  person Henry Yik    schedule 18.03.2019
comment
Этот ответ оказался недостаточно полезным. Мне больше не нужны параметры во втором коде.   -  person pigman    schedule 18.03.2019
comment
Разве ошибка не была очевидной? quit_window при вызове получает 2 аргумента. Хотя у меня не было установлено pytray, по внешнему виду ('Quit', self.quit_window) кажется, что он передает что-то похожее на event в обратном вызове tkinter.   -  person Henry Yik    schedule 18.03.2019
comment
Хорошо, я решил эту проблему с помощью лямбда-функции. Спасибо.   -  person pigman    schedule 18.03.2019


Ответы (1)


В порядке. Я решил эту проблему. Я делюсь своими кодами, чтобы помогать другим. Просто используйте лямбда-функцию:

from pystray import MenuItem as item
import pystray
from PIL import Image
import tkinter as tk
class Program:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("Welcome")
        self.window.protocol('WM_DELETE_WINDOW', self.withdraw_window)
        self.window.mainloop()

    def quit_window(self):
        self.icon.stop()
        self.window.destroy()

    def show_window(self):
        self.icon.stop()
        self.window.after(0, self.window.deiconify)

    def withdraw_window(self):
        self.window.withdraw()
        image = Image.open("microphone.ico")
        menu = (item('Quit', lambda: self.quit_window()), item('Show', lambda: self.show_window()))
        self.icon = pystray.Icon("name", image, "title", menu)
        self.icon.run()

run=Program()
person pigman    schedule 18.03.2019