Tkinter and cv2: "not responding" popup when imshow launched from tk app

John O'Hagan research at johnohagan.com
Sat Mar 18 20:08:54 EDT 2023


On Tue, 2023-03-14 at 21:54 +1100, John O'Hagan wrote:

[...]

> Here is minimal code that demonstrates the problem in the subject
> line:
> 
> import cv2
> from tkinter import *
> 
> images=['a.jpg', 'b.jpg', 'c.jpg'] #change to image paths
> 
> cv2.namedWindow('W', cv2.WND_PROP_FULLSCREEN)
> cv2.setWindowProperty('W', cv2.WND_PROP_FULLSCREEN, 
> cv2.WINDOW_FULLSCREEN)
> counter=[0]
> def show():
>    cv2.imshow('W', cv2.imread(images[counter[0] % len(images)]))
>    cv2.waitKey(1)
>    counter[0] += 1
> 
> root=Tk()
> root.wm_attributes("-topmost", 1)
> Button(root, text=' Show ', command=show).pack()
> mainloop()
> 
> It works up to a point - I can cycle through the images by clicking
> the button - but if I mouse-click on the displayed image (e.g. to use
> the zooming and panning features of cv2), nothing happens, and a few
> seconds later the image greys out and a popup appears saying
> "'Unknown' is not responding" and giving the option of waiting or
> forcing close (but sometimes these options are greyed out too).
> Clicking "wait", if available, closes the popup but it comes back a
> few seconds later. If I then click on the tkinter window titlebar,
> the popup changes to "'Tk' is not responding". Clicking on the button
> still works and after a few clicks the popup closes.
> 
[...]

For anyone interested (and there are a lot of questions about this type
of issue out there), here's the nearest I came to a satisfactory
solution. In the real code I put a method like:

def window_thread():
   cv2.namedWindow('W') #window properties omited
   while 1: # really a flag for clean exit
      cv2.imshow('W', self.image)
      cv2.waitKey(40)

and call this as a thread from __init__. This updates the image every
40 ms regardless of whether it has been changed or not, in the manner
of a video feed. Seems unnecessary, but surprisingly it doesn't seem to
use any significant resources and seems to be the only way to keep both
the tkinter GUI and the cv2 window responsive. What I'd really like is
cv2.wait(until_i_say_so()) - i.e. to wait for a flag that can be set
programatically, but it doesn't seem to be available in cv2.

Thanks to those who replied.

> --
> 
> John
> 
> 



More information about the Python-list mailing list