"Undecorate" Turtle Window - python

For a scientific experiment I wrote a turtle.py, which opens a 800x480 window and draws a slowly growing black dot. The turtle.py is started with C:\Users\kaza>python C:\Users\kaza\Desktop\Python_scripts\turtle.py "black" 900 40 1 20 20 10 0 0 30 10 in the cmd. black and the numbers after the command are parameters of the dot, which regulate parameters of the dot like growing speed, maxsize etc.
If I execute the cmd the window opens and the turtle.py starts to draw. the size of the screen is 800x480, so the window covers the full screen. The only thing that bothers me is the menu bar. By clicking on it and choosing "undecorate" I can make it disappear but I was not able to find a way starting the window undecorated. The turtle.py should start simultaneously on 12 raspberrys and it is impossible to run to each raspberry and undecorate the window.
I already tried to modify the rc.xml of openbox but nothing changed. Is there maybe a command for the cmd, which starts the turtle.py automatically in an undecorated window?

The standard module turtle uses Tk (through the Tkinter module in Python) for its windows. When you want to undecorate Tk windows, you could use the overrideredirect method of the Toplevel class. This was suggested in an answer to a similar question. From the documentation of Tkinter:
If called with a True argument, this method sets the override redirect flag, which removes all window manager decorations from the window, so that it cannot be moved, resized, iconified, or closed. If called with a False argument, window manager decorations are restored and the override redirect flag is cleared. If called with no argument, it returns the current state of the override redirect flag.
Be sure to call the .update_idletasks() method (see Section 26, “Universal widget methods”) before setting this flag. If you call it before entering the main loop, your window will be disabled before it ever appears.
This method may not work on some Unix and MacOS platforms.
Note that the window is still resizable, but just not through the platform's window manager.
The quick and dirty way to access this method would be to say
turtle.Screen().get‌​canvas()._root().over‌​rideredirect(True)
after the window has been created (to avoid the need for the aforementioned .update_idletasks() workaround).
Normally, the _ at the beginning of a name indicates that the member should not be touched. However, according to the documentation of Tkinter, this is the way to get to the root window:
To get at the toplevel window that contains a given widget, you can often just refer to the widget’s master. Of course if the widget has been packed inside of a frame, the master won’t represent a toplevel window. To get at the toplevel window that contains an arbitrary widget, you can call the _root() method. This method begins with an underscore to denote the fact that this function is part of the implementation, and not an interface to Tk functionality.

Related

Why does update_idletasks() interfere with overrideredirect() functionality?

I have a top-level window, whose specific location is set via geometry string. w.overrideredirect(True) is called because the top-level window mustn't have any window manager decorations. The official documentation states:
Be sure to call the .update_idletasks() method (see Section 26,
“Universal widget methods”(p. 97)) before setting this flag.
So that's exactly what I did, but now window manager decorations appear. It works fine if I don't call w.update_idletasks().
Code:
w = tk.Toplevel(self.parent_frame)
w.geometry('48x240+1567+209')
w.update_idletasks()
w.overrideredirect(True)
I'm using Python 3.8.10 with Tk version 8.6.10 on Ubuntu 20.04.3 LTS.
That's not official documentation, and it is wrong. The exact opposite is true: you must set the flag before tkinter has the chance to draw the window on the screen. That means before mainloop is started, and before any calls to update or update_idletasks.
The reasoning is simple: setting the overrideredirect merely sets a flag. When the window is rendered, tkinter will look to see if the flag is set and then draw the window. If the flag is not set, a border is added to the window.
Setting the flag after the window has already been drawn will have no effect since the border will already have been drawn.

Python/PySide: How to make a widget that will stay on top of the main window, but not cover up other widgets?

So I have a script running inside another program (The Foundry's Hiero) and I'm just making a new QWidget object, and calling self.show()
Now, I can set it to self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint), so my window will stay on top of the main window, even if you click on something in the main window.
The problem is, this is a sort of popup window that you configure settings in, and it triggers other QWidget popups. If I set my window to WindowStaysOnTopHint, those subdialogs that my widget triggers end up beneath my widget.
Is there a way in PySide/PyQt to make a window stay on top/keep focus from the main application window in particular, but not everything?
You can use the QApplication.focusChanged signal to raise your widget up when Hiero's main window is selected. Then you would just need to remove the WindowStaysOnTopHint flag.
I'm not familiar with Hiero's API, but I'm guessing you could try something like:
def raiseMyWidget(old, new):
if new == hiero.ui.mainWindow():
myWidget.raise_()
QtWidgets.QApplication.instance().focusChanged.connect(raiseMyWidget)
Hope this helps! You can take advantage of the old parameter or some other means to make sure that your widget isn't raised above the others as well.

Kill only Qt in PyQt

In a PyQt application is it possible to kill only the GUI (Qt) part?
Any Python commands running should be unaffected, only the graphics should disappear.
how about QtGui.QWidget.setVisible(visible)
PySide.QtGui.QWidget. setVisible ( visible )
Parameters: visible – PySide.QtCore.bool
This property holds whether the widget is visible.
Calling setVisible(true) or PySide.QtGui.QWidget.show() sets the widget to visible status if all its parent widgets up to the window are visible. If an ancestor is not visible, the widget won’t become visible until all its ancestors are shown. If its size or position has changed, Qt guarantees that a widget gets move and resize events just before it is shown. If the widget has not been resized yet, Qt will adjust the widget’s size to a useful default using PySide.QtGui.QWidget.adjustSize() .
Calling setVisible(false) or PySide.QtGui.QWidget.hide() hides a widget explicitly. An explicitly hidden widget will never become visible, even if all its ancestors become visible, unless you show it.
A widget receives show and hide events when its visibility status changes. Between a hide and a show event, there is no need to waste CPU cycles preparing or displaying information to the user. A video application, for example, might simply stop generating new frames.
A widget that happens to be obscured by other windows on the screen is considered to be visible. The same applies to iconified windows and windows that exist on another virtual desktop (on platforms that support this concept). A widget receives spontaneous show and hide events when its mapping status is changed by the window system, e.g. a spontaneous hide event when the user minimizes the window, and a spontaneous show event when the window is restored again.
You almost never have to reimplement the PySide.QtGui.QWidget.setVisible() function. If you need to change some settings before a widget is shown, use PySide.QtGui.QWidget.showEvent() instead. If you need to do some delayed initialization use the Polish event delivered to the PySide.QtGui.QWidget.event() function.

How can I make area outside toplevel unclickable?

I want to create a toplevel window in tkinter, and I want the outside area unclickable. So this way, the user cannot click out from the toplevel window, just after it's been destroyed. (And also preventing to be able to create the same window from the root Tk())
Tkinter supports something called a "grab". When you put a grab on a window, all events are funneled through the widget. Even if you click outside the window, the click will register with the window.
There are two types of grabs: local and global. Local means the grab only works for your application -- you can still click on the desktop, for example. A global grab works for the whole computer. These can be very dangerous because you can completely lock up your UI if you don't provide a way to release the grab.
To set a local grab you can call grab_set on any widget, and all events will go to that widget. To set a global graph, call grab_set_global.
A local grab is how tkinter implements modal dialogs -- while the dialog is open it has a local grab so that you must dismiss the dialog before clicking on buttons in the main window.
Danger Will Robinson! if you are working with global grabs, make sure there's a absolutely foolproof way to release the grab. For example, during development you might use after to release the grab after 15 seconds. Or, bind to the escape key. Always, always test with a local grab first. As a rule of thumb, however, you should avoid using a global grab unless absolutely necessary.

How can I get the main window's handle in Python?

In python, I enumerate top-level windows through EnumWindows, and also I enumerate the processes through EnumProcesses.
Then in the python script, I put all the window handles which belongs to the same pid into one list (I did this through GetWindowThreadProcessId).
Later I found out something: there are 3 window handles which belong to notepad.exe, but I only open one text file.
Why?
Besides, I tried to set the text window as the foreground window through SetForegroundWindow, I passed the three window handles to this function, and two work.
How could this be ?
Processes sometimes create invisible windows for their own purposes. You should ignore them (use IsWindowVisible function).
To investigate this kind of things your best friend is Spy++, that comes with several versions of Visual Studio, if you can get it.
According to it, notepad.exe creates three top-level windows:
The visible main window, class name "Notepad", overlapped.
A hidden, disabled, pop-up window, class name "MSCTFIME UI", caption "M".
Another hidden, disabled, pop-up window, class name "IME", caption "Default IME".
The two hidden windows are used internally by notepad to implement the IME (Input Method Editor), the GUI to type complex scripts.
Many programs create top-level hidden windows for a lot of things. For what you intend, you can ignore them all and use only the visible ones.

Categories