Show questions tagged with python3 and What do you want to do <: Create a main window with two buttons: Start and Stop I was able to create と and は by referring to various sites, but Currently, when you press the stop button, the video on the USB camera remains unchanged, and the following error message appears:
②: Press the start button to display the video of the connected USB camera in the main window
③: Press the stop button to erase the USB camera image displayed in で (remain the main window) What's troubling you
in processing の.
I'm in trouble because I can't erase the USB camera image.Exception in thread -8:
Traceback (most recent call last):
File "C:\Users\usr\Anaconda3\lib\threading.py", line 916, in_bootstrap_inner self.run()
File "C:\Users\usr\Anaconda3\lib\threading.py", line 864, in run
self._target(*self._args, **self._kwargs)
TypeError: destroy() missing 1 required positional argument: 'panel'
Code
import cv2
from PIL import Image
from PIL import ImageTk
import threading
import tkinter as tk
def button1_clicked():
thread=threading.Thread(target=videoLoop,args=())
thread.start()
def button2_clicked():
thread=threading.Thread(target=destroy,args=())
thread.start()
def destroy (panel):
panel.destroy()
def videoLoop (mirror=False):
No = 0
cap=cv2.VideoCapture(No)
cap.set (cv2.CAP_PROP_FRAME_WIDTH,800)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT,600)
while True:
ret, to_draw=cap.read()
if mirror is True:
to_draw = to_draw [:,::-1]
image=cv2.cvtColor(to_draw, cv2.COLOR_BGR2RGB)
image=Image.fromarray(image)
image=ImageTk.PhotoImage(image)
panel=tk.Label(image=image)
panel.image=image
panel.place(x=50,y=50)
return panel
root=tk.Tk()
root.geometry("1920x1080+0+0")
button1=tk.Button(root, text="start", bg="#ffff", font=(",50), command=button1_clicked)
button1.place (x=1000, y=100, width=400, height=250)
button2=tk.Button(root, text="stop", bg="#ffff", font=(",50), command=button2_clicked)
button2.place (x=1000, y=360, width=400, height=250)
root.mainloop()
I don't have anything to change to the camera image itself, so I will write the answer only by looking at the error situation above.
The error is a function called destroy()
requesting the argument panel
, but the value of the argument panel
does not contain anything.
def destroy(panel):
panel.destroy()
As specified in , panel
is set as the argument for the destroy
function.When you use this function, you must include some value in the panel
.
The variable panel
can be found in many parts of the code you provided, but the meaning of this code is
def button2_clicked():
thread=threading.Thread(target=destroy,args=())
thread.start()
Yes, if you look at the Thread
argument, you can see that the destroy
function moves without the args
=() argument.
As previously mentioned, running without arguments at least results in an error.
It may be a snake's foot, but
def button1_clicked():
thread=threading.Thread(target=videoLoop,args=())
thread.start()
The reason why this button 1 doesn't get an error is
def videoLoop (mirror=False):
This is because the value of the argument is initially set.Therefore, if you use it without arguments, the value of mirror
will naturally be False
.
It seems that True
is also handled below, but this will always be False
.
So why don't you first consider putting a proper value in the argument of the destroy
function?
add
I'd like to read your comments and look at the overall code and add something that I'm curious about.Please refer to it.
As you can see in the form panel.destroy()
, the argument panel
is the Label
type of Tkinter
and it appears to be true from the return value of the videooop
function.
Then you have to accept this return value, panel
, and insert it as an argument with destroy(panel)
, but to get the return value, use something_variable=videooop()
and put the something_variable
type into
At this time, you can see that the name has changed from panel
to something_variable
.
For example,
def something_func():
return "a"
b = "b"
b=something_func()
print(b)
"a"
So to put it simply, this "a" is just the Label
type of Tkinter
.
Instead of something_variable
, you can name it yourself.
However, destroy(panel)
is utilized (local) in the button2_clicked()
function, so it seems a little far to get the arguments to that location.
It is recommended that you look at the overall code and redesign the relationship between code and code a little more, but if you try to force it through,
def button2_clicked(panel):
# Undefined error if empty argument of button2_clicked
thread=threading.Thread(target=destroy,args=(panel))
thread.start()
In such a way, the value is passed to an internal function as button2_clicked(panel)
.
Then, inevitably,
button2=tk.Button(root, text="stop", bg="#ffff", font=(",50), command=button2_clicked(panel))#Here!
button2.place (x=1000, y=360, width=400, height=250)
In this way, you will have to include arguments here as well.
The videooloop
function is the first function that runs button1_clicked
, so even if you return the panel
as a return value, you have to think about where to receive it and how to insert it as an argument.
Also, as for the while
loop, the conditional expression is always True
, and there is no process to get out of the loop, so even if you insert a value into the panel
variable, the panel
will never return as a return value.
At first, I suggested that you include panel
as an argument, but I think you should reconsider the positional relationship of the code a little more.
Do I really have to pass the panel
as an argument?
while
What is intended within the loop?When do I have to stop the loop and return the panel
as the return value?
Do you really need threading
?
There may be more just because of the concern.I don't understand everything and make suggestions, but I don't think it's out of the question in general.I was just curious about the code.Perhaps you want to get pixel-like information from a video and convert it as image data in pillow and label it as a variable called panel
to change the screen.Is the looping process to keep the image updated?If you press button 2, the screen itself will disappear.
It may not be true, but I recommend that you think carefully about whether what you really want to do is expressed as a code.Of course, it is also useful to review the basics of Tkinter
, and to repeat the experiment with detailed and simple code.If you look back at the code many times and ruminate the processing in your head or write it down on paper, you may be able to code it better.You may be able to do something similar using a different method.(For example, instead of destroy()
, I think it's better to simply use lower()
to make it invisible.Then, it might be a good idea to check and use the method that is suitable for the current process.
If there is anything else, I will update it.Sorry for the long delay.
© 2024 OneMinuteCode. All rights reserved.