Tkinter and cv2: "not responding" popup when imshow launched from tk app
aapost
aapost at idontexist.club
Thu Mar 16 04:21:30 EDT 2023
On 3/15/23 07:37, John O'Hagan wrote:
> On Tue, 2023-03-14 at 16:22 -0400, aapost wrote:
>> On 3/14/23 06:54, John O'Hagan wrote:
>
> [...]
>>>
Read an alternative description of the waitKey behavior
>For example, waitKey(0) will display the window infinitely until any
keypress (it is suitable for image display). waitKey(25) will display a
frame and wait approximately 25 ms for a key press (suitable for
displaying a video frame-by-frame). To remove the window, use
cv::destroyWindow.
I went back to double check and I stand corrected on the "any keypress"
part. Any keypress on the 'keyboard' does break the wait (as I
incorrectly concluded and assumed only ESC did).
It is still slightly ambiguous in explaining that when using 25ms,
keypress or not, the wait breaks at 25ms (or before that if you press a
keyboard key). For my setup the window is stale at that point, no
controls, just a stale frame behind the tkinter window that needs to be
destroyed or reused.
Whether that is the exact behavior on all set-ups isn't clear, the note
further uses the ambiguous phrasing "might".
>Note: This function should be followed by a call to cv::waitKey or
cv::pollKey to perform GUI housekeeping tasks that are necessary to
actually show the given image and make the window respond to mouse and
keyboard events. Otherwise, it won’t display the image and the window
might lock up.
It seems with the several variations, behavior varies between them, like
one comment saying startWindowThread when using c++ and gtk allows you
to not use waitKey (not the case here.. it seems -- changing my language
to not misspeak, lol).
I haven't come across any examples beyond imshow running stand-alone as
in my solution suggestion 2. But waitKey does return a keyvalue for the
keypess to allow extending the functionality, so you can grab it, do
something, and go right back to waiting, I haven't seen any use of this
though.
You can also leave out reference to tkinter all together when using
startWindowThread:
import sys
import cv2
cv2.startWindowThread()
cv2.namedWindow("W", cv2.WND_PROP_FULLSCREEN)
cv2.setWindowProperty("W", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
cv2.imshow("W", cv2.imread(sys.argv[1]))
while(1):
a = cv2.waitKey(0)
if a == 27:#ESC
break
#elif a == something else, do something
cv2.destroyAllWindows()
exit()
But it still blocks if integrated in to the main tkinter thread, and
appears to use tkinter under the hood. And as tkinter is considered
thread-unsafe, the startWindowThread would only be ok when spawned as a
separate process like the subprocess example.
Anyway, apologies for the mistake on the any key part.
More information about the Python-list
mailing list