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