I am using VPython to visualize some data from a computer simulation.
I want to make a movie out of the VPython output. Therefore I tried to make screenshots from the vpython output window. I want to capture the output window in fullscreen mode. This way i don't need to crop the window frame. I tried ImageGrab.grab() (see here) and win32gui (see here), but both methods capture the desktop instead of the fullscreen window.
Methods screenshot and _get_windows_bytitle from here
windowtitle = 'sometitlename'
newscene = display(fullscreen=True,title=windowtitle)
newscene.cursor.visible=false
newscene.select()
b = box()
rate(1)
screenshot(_get_windows_bytitle(windowtitle)[0])
Same problem with ImageGrab.grab. Any suggestions?
I couldn't find any solution, so I used the workaround by cropping the window manually.
disp = display(width=1000, height=1040)
displayrect = (int(round(disp.x))+8, int(round(disp.y))+30, int(round(disp.width))-16, int(round(disp.height))-38)
ImageGrab.grab(displayrect)
I am not really happy with that, since it's quite messy to hardcode the window border width/height (I won't use the win32 module for that)
Related
What I want to do is, I want to have have a user click the close "X" button in an OpenCV window and have the program recognize it, and close that window.
It seems that this is not easy, and after four days of going round in circles and finding out how it can be done on a windows machine I am no closer to finding out how to do it on a Raspberry Pi using Python.
I think I need to get the handle of the OpenCV window ( how? ) and then use that to see if the window is still visible ( what call? ) and if it is not, bring proceedings to a halt ( I can do that bit ).
I have tried cvGetWindowHandle("window_name") but I've downloaded the source and GetWindowHandle doesn't seem to be available from python.
The code to capture the left button mouse click event and close a window is fairly simple:
if event == cv2.EVENT_LBUTTONDOWN:
cv2.destroyWindow("window_name")
There is a tutorial on how to use the button click event here which is where I took that code, it provides a full working example in python.
However you are probably running a unix based system on your Rpi and will therefore want to read This answer as you made need a combination of waitKey(1) in order for it to work.
I maybe have a solution but I'm not 100% sure so you'll have to check it yourself:) I assume the OpenCV uses X11 underneath (if no none of this makes sense). With X11 you can:
1) Find X11 window handle for your OpenCV window as described here
2) Use XSelectInput to hook into its event loop somewhat similar to what was done here. I assume you should useStructureNotifyMask as the mask to get the XDestroyWindowEvent event. Run the X11 event loop and as soon as you get the corresponding event you can call the OpenCV destroyWindow function.
This suggestion is based on assumptions and I can't give any guarantees it will work, but as far as I understand if OpenCV isn't built with some other specific window manager this should work. As far as I understand Raspbian was shipped with X11 up to some point and then it switched to Wayland. In case you have an image with Wayland then this probably will not work (and I'm sorry but my Linux skills do not contain a recipe on how to determine which one is used:D).
UPDATE
Actually after more reading I seem to feel that gtkshould be able to handle whatever is being used underneath (X11/Wayland). So if you install gtk development libraries you should also be able to connect to the windows deletion signal like described here. The only question then remains on how to obtain the window handle.
My personal advice - use Qt or some other GUI friendly framework to render the OpenCV images instead of doing it directly with OpenCV. OpenCV is an imaging framework but IMHO highgui is too unusable for anything serious.
all I want to do is to have a user click the close X in an openCV
window
This is how I did it, in a capture loop (RPi stretch, opencv 4.0):
while True:
# do your video capture
# ...
cv.imshow("video frame",frame)
if cv.getWindowProperty('video frame', 1) < 0:
break
getWindowProperty isn't much documented but what it does is, as its name implies, to return the property of a given window. Two of the flags of interest are WND_PROP_FULLSCREEN (or 0) and WND_PROP_AUTOSIZE (or 1). When the window is closed the function returns -1. Use this to immediately break your loop (or close your window if not in a loop).
References:
https://docs.opencv.org/3.1.0/d7/dfc/group__highgui.html#gaaf9504b8f9cf19024d9d44a14e461656
OpenCV Python: How to detect if a window is closed?
Poll with cv2.getWindowImageRect(windowName). It will return (-1, -1, -1, -1) when the user clicks the window close button.
# check if window was closed or image was resized
xPos, yPos, width, height = cv2.getWindowImageRect(windowName)
if xPos == -1: # if user closed window
pass # do whatever you want here if the user clicked CLOSE
I haven't found this documented anywhere; discovered it by accident while handling window resizing. (Tested with OpenCV 4.1.0.)
I have a python script that, when executed, wait's until it gets input from the user. I now want to know if it is posible to keep showing an image fullscreen until the user has given the input? I have searched for a solution but all i can find are tools that window managers to show the picture, but this is not installed. It'll probably only run on Debian.
I'm kind of searching for the same idea as omxplayer, but instead of movies it has to display pictures.
Using pygame is probably the easiest way of displaying an image fullscreen on the Linux framebuffer or on the X Windows root window (i.e. without a window manager).
The answers to the question Frame buffer module of python have all the details on how to achieve this.
I am creating a full-frame (no decorations) window with code like this (in python 3.2 using tkinter):
self.root = Tk()
self.W, self.H = self.root.winfo_screenwidth(), self.root.winfo_screenheight()
self.root.overrideredirect(1) # full screen, no menu or borders
self.root.geometry("%dx%d+0+0" % (self.W, self.H))
When I try to open a file dialog or message box, they appear UNDER the full frame window. I can verify this by calling a withdraw() on the main window before I open one of the dialogs. For example,
file = tkinter.filedialog.askopenfilename(parent=self.root) # UNDER main window
On windows I don't have a problem with this, only on fedora 14 and ubuntu 12.04 have I noticed it. (I haven't tested on Mac). I'm passing a parent to the dialogs but they don't seem to be paying attention. Can someone help me understand what I'm doing wrong? Thanks.
Calling .overrideredirect(1) on a window has a different meanings on Windows and X11. On Windows, it tells the OS to disable drawing of the window border. On X11, it tells the window manager to completely ignore the window. Realistically, it should have the same effect on Windows that it does on X11, but this is not the case.
The reason why calling .overrideredirect(1) causes the window to stay on top is because X11 does not have any control over it (as the displaying of the window is not handled by the window manager). The program window and the window manager are completely independent, so implementing standard window stacking would not make sense.
With only tkinter, there is nothing you can do to prevent this behaviour, because tkinter is not really the source of the problem. There may be a way to use X11 Python bindings to show the window without a frame, but this would result in platform specific code.
You may want to rethink removing the window border. Is there a possible alternative? A fullscreen window including the window border is a fine option. Removing window borders is not a good idea at the best of times due to accessibility reasons (no way to move, minimize, maximize, etc.). Also, personally, as a Linux user, I have my window borders customized with all kinds of features (e.g. window tabbing, shade button), and use them quite frequently. Removing the window border would prevent such features from being used.
What I need is a tkinter window that is transparent,
but with a image displayed on this window is not.
I've seen the
w.attributes('-alpha', 0.1)
thing, but that makes the image transparent as well.
I need just the background of the window transparent,
so that an image on the window that has transparent parts,
will show the Users desktop through these parts.
Are there anyways to do this in Python?
(specs:
Python 2.7.1
Tkinter
PhotoImage
Windows7)
I would suggest another ui library
pretty much a duplicate to Is it possible to create a Tkinter Window with no frame, and no background?
I just learnt that pygame don't support window transparency but according to the last post here wxPython does if that's an option
more links:
draws under windows over desktop(you can adapt I think)
Discussion about various ways to implement
using Ruby or Python, does someone know how to draw on the screen, covering up any other window? Kind of like, press a key, and the program will show current weather or stock quote on the screen (using the whole screen as the canvas), and then press the key again, and everything restores to the same as before? (like Mac OS X's dash board).
You could use the systems dashboard (desktop widgets, or whatever it's called) API. In order to do that you need bindings to it for Python or Ruby.
Alternatively you could use some generic gui toolkit or application framework and just create a frameless window with transparent background. Then you need to be sure that the chosen toolkit supports 'always-on-top' options on your desired platform(s).
If you are on windows you can directly draw to desktop dc(device context) using win32api
e.g. just for fun try this :)
>>> import win32ui
>>> import win32gui
>>> hdc = win32ui.CreateDCFromHandle( win32gui.GetDC( 0 ) )
>>> hdc.DrawText("Wow it works", (100, 100, 200, 200))
>>> hdc.LineTo(500,500)
but that won't be very useful ,as not erasable
best bet would be to use a transparent window or window with a cutout region (atleast on windows that is possible)
or even if you can't draw transparent on some system you can grab the current screen and display it as background of you window that would give a transparent effect
I would recommend PyGame.