Python, tkinter how to make the window click-through Linux - python

I have seen the post about how to do it on Windows, but i need a Linux version. Is there any way? (Yes, i Googled before i came here)
What i basically want to do is to open a maximized transparent click through window, to mainly use it as a "dark reader"
here my tiny code :)
from tkinter import *
win = Tk()
win.geometry("%dx%d+0+0" % (win.winfo_screenwidth(), win.winfo_screenheight()))
win.wait_visibility(win)
win.configure(bg="black")
win.wm_attributes("-alpha", 0.5)
win.mainloop()

I forgot to answer my question, after i got the solution. Thanks to Andrew Hernandez, i checked out PyQT5 and with that i could make what i needed. Here the code:
from PyQt5 import QtCore, QtWidgets, QtGui
import sys
DR = QtWidgets.QApplication(sys.argv)
win = QtWidgets.QWidget()
screen = DR.primaryScreen()
size = screen.size()
w = size.width()
h = size.height()
win.resize(w, h)
win.setWindowTitle("Dark Reader")
win.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents, True)
win.setStyleSheet("background-color: black;")
win.setWindowOpacity(0.5)
win.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.FramelessWindowHint)
win.showMaximized()
sys.exit(DR.exec_())

Simplified Explication
#Z3r0ut, Your probably using python 2.x because that is what most Linux distributions use. If you want to run the code, you can simple start with this argument python %FILENAME%.py.
!/usr/bin/python
-*- encoding: utf8 -*-
try:
import Tkinter as tk
from Tkinter import *
except ImportError:
win = Tk()
win.geometry("%dx%d+0+0" % (win.winfo_screenwidth(), win.winfo_screenheight()))
win.wait_visibility(win)
win.configure(bg="black")
win.wm_attributes("-alpha", 0.5)
win.mainloop()
Detailed Explication
These effects depend on your operating system, therefore you can't make Linux re-create these effects like windows 10/11. For example, shader.dll is used for shaders, dynamic.dll is used for screen smoothing, fix.dll is used for styling windows. Every one, can be found on regedit.
It can be made, but you need third-party API's or links for your file. If you're trying to make it, I would recommend you using c/c++ for it!

Related

Combining Tkinter and win32ui makes Python crash on exit

While building a basic app using the winapi with Python 2.7 (I'm on Windows 8.1), I tried to add a small Tkinter gui to the program. The problem is, whenever I close the app window, Python crashes completely (getting crash messages basically).
I have found reports of this issue in several places, but couldn't find a fix or solution. Here are some sources:
http://sourceforge.net/p/pywin32/bugs/443/#8bde
http://www.gossamer-threads.com/lists/python/python/134956 (this one is from 2002!)
It can be reproduced with as much as these 4 lines:
from Tkinter import Tk
import win32ui
root = Tk()
root.mainloop()
And closing the window after running it.
Does anyone know of a solution for this? Any recommendations for a workaround maybe?
A workaround is to invoke the Tkinter-win32UI app with pythonw. Python doesn't crash.
Tested with Python 3.6.3 on Win 10.
Make a button on the Windows and close your program by this button. Here's my script:
from tkinter import *
import win32ui
win = Tk()
frame = Frame(win)
frame.pack(padx = 10, pady = 10)
b1 = Button(frame, text = "Close", command = win.destroy)
b1.pack()
win.mainloop()

ttk OptionMenu does not fit into its bounding box

I am facing a problem creating a Tkinter-application under Windows, using python 2.7. Basically, when I create an OptionMenu, its right corner (where a down button indicates that something happens when you click there) is truncated in the middle.
The following code reproduces the issue:
from Tkinter import Tk, StringVar
from ttk import OptionMenu
root = Tk()
options = list('ABC')
var = StringVar(value='A')
om = OptionMenu(root, var, var.get(), *options)
om.config(width=25)
om.pack()
root.mainloop()
The result looks on my computer like this:
I have played around with the padx and ipadx keywords of the packing layout manager and also tried a grid layout instead. None of them lets me see the down-arrow completely.
I appreciate your helpful comments on this issue.
The same happens to me on Windows 7 but not on XP, both using Python 2.7. I have found a bug report which states is should be fixed in Tk 8.5.8. Updating Tcl/Tk in Python seems to be very complicated though
The fix in question is for one of the script files shipped in the tk library. You could modify your local copy of vistaTheme.tcl to match this. In later versions I think it does actually request the size from the system properly but this should work if you are forced to use an older version of Tk.
You can find the path using:
from Tkinter import Tk
tk = Tk()
tk.eval("set tk_library")
and then edit the /ttk/vistaTheme.tcl file. I've got python3 here and it seems to have come with Tk 8.6.1 so has this fixed already.

python-wnck set focus to window

I'm trying to set focus to a window using python-wnck.
The only docs I could find related to this library are from https://developer.gnome.org/libwnck/stable/WnckWindow.html
Using some code I found on another question here at SO, I was able to search for windows using the window title, but I'm not sure how to get a window to focus. From the above docs I found the function:
wnck_window_activate(WnckWindow *window, guint32 timestamp);
So in python I tried using this function like "window.activate(0)", but this appears to fail, the icon on my taskbar flashed but it doesn't get focus.In the terminal I get the message:
(windowTest.py:17485): Wnck-WARNING: Received a timestamp of 0; window activation may not function properly
So I think I may actually need to put in a valid timestamp but not sure how to get this.
This is the code Im using sofar:
import pygtk
pygtk.require('2.0')
import gtk
import wnck
import re
import sys
screen = wnck.screen_get_default()
while gtk.events_pending():
gtk.main_iteration()
titlePattern = re.compile('.*Geany.*')
windows = screen.get_windows()
for w in windows:
if titlePattern.match(w.get_name()):
print w.get_name()
w.activate(0)
The solution was actually pretty simpleI just needed to "import time" then pass "int(time.time())" into the activate function
Working code:
import pygtk
pygtk.require('2.0')
import gtk
import wnck
import re
import sys
import time
screen = wnck.screen_get_default()
while gtk.events_pending():
gtk.main_iteration()
titlePattern = re.compile('.*Geany.*')
windows = screen.get_windows()
for w in windows:
if titlePattern.match(w.get_name()):
print w.get_name()
w.activate(int(time.time()))
To get away from the Wnck-WARNING, you need to send a valid timestamp with the w.activate() function. The way that I found to do this is to use:
now = gtk.gdk.x11_get_server_time(gtk.gdk.get_default_root_window())
w.activate(now)
There really should be an easier way to do this, or wnck should allow a timestamp of 0 to mean now like most of the gtk libraries use.

PyQt: Qt.Popup widget sometimes loses focus without closing, becomes unclosable

I'm writing a very small application with PyQt. All of my testing has been on Ubuntu/gnome so far.
I want a single "Popup" style window, with no taskbar/panel entry, that will close itself (and the application) the moment it loses focus.
The Qt.Popup flag seems to fit the bill, but I'm having a weird problem. I've noticed that it's possible (pretty easy, in fact) to take focus away from the application as it's starting, leaving a Popup window with no focus -- and it is now impossible to close it, because it cannot lose focus.
Here's a simplified example:
#!/usr/bin/python
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
if __name__ == '__main__':
app = QApplication(sys.argv)
w = QDialog()
w.setWindowFlags(Qt.Popup)
w.exec_()
If you click around a bit within the same moment the program is starting, the QDialog will appear without focus, and will not close itself under any circumstance. Clicking on the popup does not restore focus or allow it to be closed.
I could add a close button to the popup (and I intend to!) but that doesn't fix the broken close-on-lost-focus behavior. Is there something else I should be doing with Qt.Popup windows to prevent this, or is there some way I can work around it?
Using QWidget::raise() seems to help here.
(Also took the liberty and fixed your app event loop)
#!/usr/bin/python
import sys
#import time
from PyQt4.QtCore import *
from PyQt4.QtGui import *
if __name__ == '__main__':
#time.sleep(2)
app = QApplication(sys.argv)
w = QDialog()
w.setWindowFlags(Qt.Popup)
w.setAttribute(Qt.WA_QuitOnClose)
w.show()
w.raise_()
sys.exit(app.exec_())

PyQt4 SIGNAL/SLOT problem when using sub-directories

Thanks in advance for taking the time to read this. Apologies that it is somewhat verbose. But hopefully it fully explains the problem. Stripped code demonstrating the issue is included.
I'm having an issue with PyQt4 SIGNAL/SLOTS. While I can make everything work fine if I am writing in a single file, I can't make things work if I some of the functions I wish to use are moved to sub-directories/classes.
I've looked through the Python Bindings document I can see how this works when using a single file. But what I am trying to do is this:
main.py file in root dir which contains the MainWindow __init__ code.
This file imports a number of widgets. Each widget is stored in its own sub-directory. All sub-directories contain an __init__.py file. These sub-directories are inside of a directory called 'bin', which is itself in the root dir
Some of these widgets need to have SIGNAL/SLOT links between them This is where I fall down.
So the file structure is:
- main.py
- bin/textEditor/__init__.py
- bin/textEditor/plugin.py
- bin/logWindow/__init__.py
- bin/logWindow/plugin.py
The following code shows the problem. This code creates a very basic main window that contains a central QTextEdit() widget and a dockable QTextEdit() widget. All that happens is that when the text in the central widget is changed, the same text is shown in the dockable widget. The example works. But it does so by connecting the signal textChanged() in the bin/textEditor/plugin.py file that creates the central QTextEdit() with a function in main.py. I would like it to do exactly the same thing but connexted to the updateUi function in bin/textEditor/plugin.py
If anyone could shed some light on this, I would be hugely grateful. I'm sure it is simple. But direction to any tutorials that cover this or statements that I am doing it all very wrong are equally appreciated!. Thanks again for your time:
### main.py
import os
import sys
# Import PyQT modules
from PyQt4.QtCore import *
from PyQt4.QtGui import *
# Start the main class
class MainWindow(QMainWindow):
# Initialise
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
# Name and size the main window
self.setWindowTitle("EDITOR/LOG")
self.resize(800, 600)
import bin.logWindow.plugin as logWindow
logWindow.create(self)
import bin.textEditor.plugin as textEditor
textEditor.create(self)
def updateUi(self):
# I can connect to this function from within bin/textEditor/plugin.py (see
# below) but I want to connect to the function located in
# bin/textEditor/plugin.py instead
text = self.editor.toPlainText()
self.logWidget.setText(text)
# Run the app
def main():
app = QApplication(sys.argv)
form = MainWindow()
form.show()
app.exec_()
# Call main
main()
The code inside of the two plugin files is:
### bin/textEditor/plugin.py
# Import PyQT modules
from PyQt4.QtCore import *
from PyQt4.QtGui import *
def create(self):
# Add a dockable widget
self.logDockWidget = QDockWidget("Log", self)
self.logDockWidget.setObjectName("LogDockWidget")
self.logDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea|
Qt.RightDockWidgetArea)
self.logWidget = QTextEdit()
self.logDockWidget.setWidget(self.logWidget)
self.addDockWidget(Qt.LeftDockWidgetArea, self.logDockWidget)
And
### bin/logWindow/plugin.py
Import PyQT modules
from PyQt4.QtCore import *
from PyQt4.QtGui import *
def create(self):
# Create a text editing box
self.editor = QTextEdit()
# Add to main window
self.setCentralWidget(self.editor)
# connect text change to update log window. This is presumably what I need to
# change so that it connects to the function below instead of the on in main.py
self.connect(self.editor, SIGNAL("textChanged()"), self.updateUi)
def updateUi(self):
text = self.editor.toPlainText()
self.logWidget.setText(text)
For starters, is there a reason you're using a very old version of the PyQt release document? The new one is: here
There are a few things you are doing that are a bit unusual. Generally import statements in python are placed at the top of the file (to more easily see dependencies), but I assume you're doing this to support a more generalized import system for plugins in the future.
It seems like the basic problem is you're trying to connect a signal source to a slot in another object, without storing that other object in a particular place. To do this you probably need to either make the connection in main, make a neutral "updateUi" slot that emits it's own special signal that all the plugins are waiting for, or just keep a reference to those subobjects in main and be careful with the initialization order.

Categories