Create a transparent drawing window on top of all applications
Step 1: Introduction
In our modern time, more and more people are faced with the need to create applications or scripts that run on top of other applications without interrupting the user’s work. One interesting example is the creation of a transparent drawing window that allows users to take notes, comments or draw on top of any active window without switching to other applications. I write code that finds and circles certain objects right at work.
In this article, we will look at how to create a transparent drawing window in Python using the PyQt5 library. We will learn how to create a window, adjust its transparency and display it on top of all windows on the desktop, while maintaining functionality and usability for users.
To create a transparent window, we will use the powerful tools provided by the PyQt5 library.
Step 2: Installing the Required Libraries
To create a transparent window, we will use the PyQt5 library, which provides powerful tools for creating a GUI based on Qt.
To install the libraries, you can use the pip command:
pip install PyQt5
or
pip install pyqt5-tools
Step 3: Import the required modules
Once the libraries are installed, we can import them into our code:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtGui import QPainter, QBrush, QColor, QPen
from PyQt5.QtCore import Qt, QTimer, QRect
import random
Step 4: Defining the DrawingWindow Class
To create a transparent window, we define a DrawingWindow class that inherits from the QMainWindow class. The class constructor sets the necessary window parameters, such as title, geometry, and flags. It also initializes the QPainter object to draw on the window.
class DrawingWindow(QMainWindow):
def __init__(self, coordinates):
super().__init__()
# Устанавливаем заголовок окна
self.setWindowTitle("Прозрачное окно для рисования")
# Устанавливаем геометрию окна, чтобы оно занимало весь экран
self.setGeometry(0, 0, QApplication.desktop().screenGeometry().width(),
QApplication.desktop().screenGeometry().height())
# Устанавливаем флаги, чтобы окно было без рамки и оставалось поверх других окон
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowSt
aysOnTopHint)
# Создаем объект QPainter для рисования на окне
self.painter = QPainter()
self.painter.setRenderHint(QPainter.Antialiasing)
# Устанавливаем начальный цвет пера (красный) и ширину пера (4 пикселя)
self.pen_color = QColor(255, 0, 0)
self.pen_width = 4
# Сохраняем переданные координаты прямоугольников для рисования
self.coordinates = coordinates
# Создаем таймер для обновления окна
self.draw_timer = QTimer()
# Запускаем таймер и устанавливаем интервал обновления окна (10 миллисекунд)
self.draw_timer.start(10)
Step 5: Update and Display the Window
In the paintEvent function, the window is updated on each paintEvent event. We use the QPainter object to draw on the window. First the transparent background is drawn, then the rectangles are drawn using the coordinates from the self.coordinates variable.
def paintEvent(self, event):
self.painter.begin(self)
# Устанавливаем прозрачный фон
self.painter.setPen(Qt.NoPen)
self.painter.setBrush(QBrush(Qt.transparent))
self.painter.drawRect(QRect(0, 0, self.width(), self.height()))
# Устанавливаем цвет пера и его ширину
self.painter.setPen(QPen(QColor(self.pen_color), self.pen_width))
self.painter.setBrush(QBrush(Qt.transparent))
# Рисуем прямоугольники, используя переданные координаты
for coord in self.coordinates:
x, y, width, height = coord
self.painter.drawRect(x, y, width, height)
self.painter.end()
# Обновляем координаты
self.update_coord()
# Планируем перерисовку через 1 секунду
QTimer.singleShot(1000, self.update)
Step 6: Update Coordinates
The coordinates of the rectangles are updated by calling the update_coord() method, which receives the new coordinates using the R.run() function from the ScreenCapture module. If the new coordinates are presented as a list, then they are stored in the self.coordinates variable. Otherwise, the new coordinates are converted to a list and saved.
def update_coord(self):
self.coordinates = [(random.randrange(0, 1000), random.randrange(0, 1000), random.randrange(0, 1000)), (random.randrange(0, 1000), random.randrange(0, 1000), random.randrange(0, 1000))]
Step 7: Launching the Application
At startup, the initial coordinates of the s_coordinates rectangles are determined. Then an instance of the Recognizer class is created and a DrawingWindow window is created, passing in the s_coordinates coordinates. The window is then displayed using the show() method.
if __name__ == "__main__":
# Начальные координаты прямоугольников
s_coordinates = [(524, 474, 84, 64), (524, 367, 84, 47)]
app = QApplication(sys.argv)
# Создаем экземпляр класса Recognizer
# Создаем экземпляр класса DrawingWindow с передачей координат
window = DrawingWindow(s_coordinates)
# Отображаем окно
window.show()
# Запускаем цикл обработки событий приложения и выходим, когда цикл завершится
sys.exit(app.exec_())
Now you know how to create a transparent drawing window on top of all applications using the PyQt5 Python library. This can be useful when creating applications or scripts that require user interaction without interrupting their work. If you have any additional questions, feel free to ask them.
The result of the work
As you can see, the quads are perfectly displayed on top of Pycharm and at the same time do not interfere with working with it. In general, this case is part of a project that you can follow here
PUMOVETZ/The-Fool-Game (github.com)
Here is the complete code
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtGui import QPainter, QBrush, QColor, QPen
from PyQt5.QtCore import Qt, QTimer, QRect
import random
class DrawingWindow(QMainWindow):
def __init__(self, coordinates):
super().__init__()
self.setWindowTitle("Transparent Drawing Window")
self.setGeometry(0, 0, QApplication.desktop().screenGeometry().width(),
QApplication.desktop().screenGeometry().height())
self.setAttribute(Qt.WA_TranslucentBackground, True)
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
self.painter = QPainter()
self.painter.setRenderHint(QPainter.Antialiasing)
self.pen_color = QColor(255, 0, 0) # Set the initial pen color to red
self.pen_width = 4 # Set the initial pen width to 4
self.coordinates = coordinates # Store the coordinates for drawing rectangles
self.draw_timer = QTimer()
self.draw_timer.start(10) # Update the window every 10 milliseconds
def paintEvent(self, event):
self.painter.begin(self)
self.painter.setPen(Qt.NoPen)
self.painter.setBrush(QBrush(Qt.transparent))
self.painter.drawRect(QRect(0, 0, self.width(), self.height())) # Draw a transparent background
self.painter.setPen(QPen(QColor(self.pen_color), self.pen_width))
self.painter.setBrush(QBrush(Qt.transparent))
for coord in self.coordinates:
x, y, width, height = coord
self.painter.drawRect(x, y, width, height) # Draw rectangles using the provided coordinates
self.painter.end()
self.update_coord() # Update the coordinates
QTimer.singleShot(1000, self.update) # Schedule a repaint after 1 second
def update_coord(self, coords=0):
if coords != 0:
pass
else:
self.coordinates = [
(random.randrange(0, 500), random.randrange(0, 500), random.randrange(0, 500), random.randrange(0, 500))]
if __name__ == "__main__":
coordinates = [(524, 474, 818-524, 689-474), (524, 367, 818-524, 473-367)]
app = QApplication(sys.argv)
window = DrawingWindow(coordinates) # Create an instance of the DrawingWindow class with the given coordinates
window.show() # Display the window
sys.exit(app.exec_()) # Start the application event loop and exit when it's finished