TypeError: <lambda>() аргумент после * должен быть итеративным, а не очередью - PullRequest
0 голосов
/ 24 апреля 2019

Я работаю над интерфейсом, где необходимо изменить курсор на занятый курсор при нажатии кнопки. Но код, который я имею, выбрасывает «ошибку типа». Я просто хочу, чтобы код отображал кнопку, которая при нажатии переключается с курсора руки на курсор «занято», а затем возвращается к обычному курсору.

Вот код, который я пробовал до сих пор:

import threading
from threading import Thread
from threading import Event
import queue

sem=threading.Semaphore()

def setup_for_long_running_task(self):
    print("start")
    self.f1.config(cursor="wait")  # Set the cursor to busy
    sem.acquire()

    return_que = queue.Queue(1)
    workThread = Thread(target=lambda q, w_self: \
                        q.put(self.long_running_task()),
                        args=return_que)
    workThread.start()

    self.f1.after(5000,use_results_of_long_running_task(self,workThread,return_que))  # 500ms is half a second
    sem.release()
    print("stop")

def long_running_task(self):

    Event().wait(3.0)  # Simulate long running task

def use_results_of_long_running_task(self, workThread,return_que):
    ThreadRunning = 1
    while ThreadRunning:
        Event().wait(0.1)  # this is set to .1 seconds. Adjust for your process
        ThreadRunning = workThread.is_alive()

    while not return_que.empty():
        return_list = return_que.get()

    self.f1.config(cursor="")  

Сообщение об ошибке:

    TypeError: <lambda>() argument after * must be an iterable, not Queue. 

    Exception in thread Thread-7:
    Traceback (most recent call last):
    File "C:\ProgramData\Anaconda3\lib\threading.py", line 917, in 
    _bootstrap_inner
    self.run()
    File "C:\ProgramData\Anaconda3\lib\threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
    TypeError: <lambda>() argument after * must be an iterable, not Queue

Ответы [ 2 ]

0 голосов
/ 24 апреля 2019

ниже скрипта, который использует угрозу и меняет тип курсора при запуске потока и после его завершения.Он имитирует обратный отсчет с интервалом в 1 секунду.

Я установил родительский курсор, но если вы сохраняете ссылку на другой виджет, например кнопку, вы можете выполнить ту же работу.

Вызов класса MyThread принудительно устанавливает тип курсора как

self.parent.config (cursor = "watch")

и, когда поток заканчивается, self.check= Ложь, мы сбрасываем тип курсора

self.parent.config (cursor = "")

#!/usr/bin/python3
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import threading
import queue
import time

class MyThread(threading.Thread):

    def __init__(self,parent, queue, count):
        threading.Thread.__init__(self)

        self.parent = parent
        self.parent.config(cursor="watch")
        self.queue = queue
        self.check = True
        self.count = count


    def stop(self):
        self.check = False

    def run(self):

        while self.check:

            if self.count <1:
                self.parent.config(cursor="")
                self.check = False
            else:                
                self.count -= 1
                time.sleep(1)
                self.queue.put(self.count)

class Main(ttk.Frame):
    def __init__(self, parent):
        super().__init__()

        self.parent = parent
        self.parent.config(cursor="")

        self.queue = queue.Queue()
        self.my_thread = None

        self.spins = tk.IntVar()
        self.count = tk.IntVar()

        self.spins.set(5)

        self.init_ui()

    def init_ui(self):

        f = ttk.Frame()

        ttk.Label(f, text = "Set count").pack()
        tk.Spinbox(f, from_=2, to=20, textvariable= self.spins).pack()

        ttk.Label(f, text = "Get count").pack()
        ttk.Label(f, textvariable = self.count).pack()

        w = ttk.Frame()

        self.start = ttk.Button(w, text="Start", command=self.start_count).pack()
        ttk.Button(w, text="Stop", command=self.stop_count).pack()
        ttk.Button(w, text="Close", command=self.on_close).pack()

        f.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
        w.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)


    def start_count(self):

        if (threading.active_count()!=0):

            self.my_thread = MyThread(self.parent, self.queue,self.spins.get())
            self.my_thread.start()
            self.on_periodic_call()

    def stop_count(self):
        if self.my_thread is not None:
            if(threading.active_count()!=1):
                self.my_thread.stop()


    def on_periodic_call(self):

        self.on_check_queue()
        if self.my_thread.is_alive():
            self.after(1, self.on_periodic_call)
        else:
            pass

    def on_check_queue(self):
        while self.queue.qsize():
            try:
                self.count.set(self.queue.get(0))
            except queue.Empty:
                pass                    

    def on_close(self):
        if self.my_thread is not None:
            if(threading.active_count()!=1):
                self.my_thread.stop()

        self.parent.on_exit()

class App(tk.Tk):
    """Start here"""

    def __init__(self):
        super().__init__()

        self.protocol("WM_DELETE_WINDOW", self.on_exit)

        self.set_style()
        self.set_title()

        Main(self)

    def set_style(self):
        self.style = ttk.Style()
        #('winnative', 'clam', 'alt', 'default', 'classic', 'vista', 'xpnative')
        self.style.theme_use("clam")


    def set_title(self):
        s = "{0}".format('Simple App')
        self.title(s)

    def on_exit(self):
        """Close all"""
        if messagebox.askokcancel("Simple App", "Do you want to quit?", parent=self):
            self.destroy()               

if __name__ == '__main__':
    app = App()
    app.mainloop()
0 голосов
/ 24 апреля 2019

Для потока требуется args как кортеж или список (итерируемые объекты), даже если у вас есть только один аргумент

 args=(return_que,)

Ваш lambda ожидает два аргумента lambda q, w_self:, но у вас есть только один элемент в args

 args=(return_que, ???)

но я не знаю, что вы хотите использовать как w_self.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...