PyQt5: Create transparent window with opaque widgets - python

Is it possible to make mainWindow completely transparent while other widgets remains visible?
For example:
I want to make app transparent and make everything else visible (like, mainFrame, close button, minimize button)

As #Felipe mentioned you can use
window.setAttribute(QtCore.Qt.WA_TranslucentBackground)
here is a little example:
import sys
from PyQt5 import QtWidgets, QtCore
app = QtWidgets.QApplication(sys.argv)
# create invisble widget
window = QtWidgets.QWidget()
window.setAttribute(QtCore.Qt.WA_TranslucentBackground)
window.setWindowFlags(QtCore.Qt.FramelessWindowHint)
window.setFixedSize(800, 600)
# add visible child widget, when this widget is transparent it will also be invisible
visible_child = QtWidgets.QWidget(window)
visible_child.setStyleSheet('QWidget{background-color: white}')
visible_child.setObjectName('vc')
visible_child.setFixedSize(800, 600)
layout = QtWidgets.QGridLayout()
# add a close button
close_button = QtWidgets.QPushButton()
close_button.setText('close window')
close_button.clicked.connect(lambda: app.exit(0))
layout.addWidget(close_button)
# add a button that makes the visible child widget transparent
change_size_button = QtWidgets.QPushButton()
change_size_button.setText('change size')
change_size_button.clicked.connect(lambda: visible_child.setStyleSheet('QWidget#vc{background-color: transparent}'))
layout.addWidget(change_size_button)
visible_child.setLayout(layout)
window.show()
app.exec()

Related

Creating QPainter object by passing pixmap via ".pixmap()" causes: "QPaintDevice: Cannot destroy paint device that is being painted"

Ive just recently started to use PyQt6. I am trying to make a custom UI-element so i am (trying) to use QPainter. However even the example code on https://www.pythonguis.com/tutorials/pyqt6-bitmap-graphics/ doesn't work and outputs QPaintDevice: Cannot destroy paint device that is being painted. (I'll paste the code with a few added comments down below)
It seems that when i create an QPainter object by passing it the label's pixmap by using self.label.pixmap() something is happening that is causing the error.
Commenting the two following lines (painter.drawLine(10, 10, 300, 200) and painter.end() does not stop the error from occuring
However, when i pass it the canvas object directly, and then assign the canvas object to label it works. But now i would have to reassign the canvas to label everytime i want to update it.
This is the example code from the website:
import sys
from PyQt6 import QtCore, QtGui, QtWidgets, uic
from PyQt6.QtCore import Qt
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
# create widget containing the pixmap
self.label = QtWidgets.QLabel()
# create the pixmap
canvas = QtGui.QPixmap(400, 300)
# set the pixmap to the label
self.label.setPixmap(canvas)
# i dont really know what this does but it was in the example code
self.setCentralWidget(self.label)
self.draw_something()
def draw_something(self):
# create the painter and tell it what pixmap to draw on
painter = QtGui.QPainter(self.label.pixmap())
# draw a line
painter.drawLine(10, 10, 300, 200)
# end / delete the printer
painter.end()
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
And this is my Version which somewhat works:
import sys
from PyQt6 import QtCore, QtGui, QtWidgets, uic
from PyQt6.QtCore import Qt
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
# create widget containing the pixmap
self.label = QtWidgets.QLabel()
# create the pixmap
self.canvas = QtGui.QPixmap(400, 300)
# this was not in the example code but without it the background is just black and the line therefore not visible
self.canvas.fill(QtGui.QColor("white"))
# i dont really know what this does but it was in the example code
self.setCentralWidget(self.label)
self.draw_something()
# set the pixmap to the label
self.label.setPixmap(self.canvas)
def draw_something(self):
# create the painter and tell it what pixmap to draw on (in this case directly to canvas obj)
painter = QtGui.QPainter(self.canvas)
# draw a line
painter.drawLine(10, 10, 300, 200)
# end / delete the printer
painter.end()
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
So what is causing this problem? May this be a bug or am i missing something here?

PyQt QTextEdit forgetting settings

I've got a PyQt GUI with a QTextEdit in it. I have set a few of the widget settings to play with things like the font size. What I'm seeing is that when I initially type in the field, the settings are applied, but if I delete all text and start typing again, the settings have reset to the default ones. Below is a MWE where I can see this behavior. Just in case it matters, I'm using Python 3.5.1 with PyQt4 4.8.7.
from PyQt4 import QtCore, QtGui
class App(object):
def __init__(self):
self.app = QtGui.QApplication([]) # The main application
self.win = QtGui.QMainWindow() # The main window
self.widget = QtGui.QWidget() # The central widget in the main window
self.grid = QtGui.QVBoxLayout() # The layout manager of the central widget
self.textArea = QtGui.QTextEdit()
self.grid.addWidget(self.textArea)
self.textArea.setMinimumSize(600,300)
self.textArea.setLineWrapMode(QtGui.QTextEdit.NoWrap)
self.textArea.setFontPointSize(12)
self.widget.setLayout(self.grid)
self.win.setCentralWidget(self.widget)
self.win.show()
self.app.exec_()
App()
You can create a new QFont item and then you can use QTextEdit.setFont()
This way it will not reset after all text is deleted.

PyQt5 PushButton not showing

This is the code I am using and the button doesn't show and it only shows a blank window. There is no error in the console.
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import *
import sys
def start():
app = QApplication(sys.argv)
w = QWidget()
w.resize(128,102)
w.move(0, 0)
w.setWindowTitle('Simple')
btn = QtWidgets.QPushButton("Hi")
btn.move(50, 50)
btn.resize(btn.sizeHint())
w.show()
sys.exit(app.exec_())
start()
This is the window it shows
Try passing the parent argument to the constructor. The parent argument causes the button to be owned by Qt, not PyQt. btn = QtWidgets.QPushButton("Hi", w) should work.
Any widget you want to be shown needs to be parented, either directly or indirectly, to the widget you want it to appear in.
The common way to do this is by assigning your widget a layout and adding other widgets or sublayouts to it.
widget = QtWidgets.QWidget()
button = QtWidgets.QPushButton('Hi')
layout = QtWidgets.QVBoxLayout(widget) # Parents layout to widget
layout.addWidget(button)
widget.show()
In this example, widget is indirectly assigned as the parent to button through layout
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import *
import sys
def start():
app = QApplication(sys.argv)
w = QWidget()
w.resize(128,102)
w.move(0, 0)
w.setWindowTitle('Simple')
btn = QtWidgets.QPushButton (w)
btn.move(50, 50)
btn.resize(btn.sizeHint())
btn.setText ('Hi')
w.show()
sys.exit(app.exec_())
start()

PyQt: How can i set stylesheet contents on scaled mode?

I had an application that contained a lot of widgets with stylesheet on them, However, I did not add any layout to interface, It neither had central widget included, But the application was running without any problems.
However, whenever i tried to resize the application (scaling it down) the widgets would not scale, of course.
I had an little research (Because i could not find anything else related to my problem) and i found this on Qt Documentation, stylesheet reference:
"The actual image that is drawn is determined using the same algorithm as QIcon (i.e) the image is never scaled up but always scaled down if necessary."
How can i make stylesheet scale down with window? (If stylesheet has background image on)
For example i have button with stylesheet:
btn = QtGui.QPushButton(self)
btn.move(0, 0)
btn.setObjectName('btn)
btn.setStyleSheet("#btn {background-image: url(':/images/somepicture.png'); border: none; }")
How can i make this button scale down with window, Can i achieve this without layouts? If not how can i do it with layouts? (without it limiting too much)
If you add the button as the central widget to a QMainWindow it should automatically adjust it's size to fit the available space. However, to get the button image to scale, you need to set the image as a border-image stylesheet property (a little strange). A working example for PyQt4:
from PyQt4 import QtGui, QtCore
class MainWindow(QtGui.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
btn = QtGui.QPushButton(self)
btn.setStyleSheet("border-image: url('somepicture.png');") # Scaled
#btn.setStyleSheet("background-image: url('somepicture.png');") # Not scaled
self.setCentralWidget(btn)
self.show()
app = QtGui.QApplication([])
window = MainWindow()
app.exec_()
Note that you don't need to set an id (objectName) to assign the CSS to a specific widget, you can simply pass in the CSS rule via .setStyleSheet().
You cannot set a layout on QMainWindow as it already has a complex layout system to accommodate docking widgets and toolbars. Therefore, if you want to use a layout to add more than one widget to the window, you need to use a container widget to hold it. The following working example demonstrates this:
from PyQt4 import QtGui, QtCore
class MainWindow(QtGui.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
w = QtGui.QWidget() # container widget
l = QtGui.QVBoxLayout() # your layout
w.setLayout(l) # set the layout on your container widget
btn = QtGui.QPushButton(self)
btn.setStyleSheet("border-image: url('somepicture.png');")
label = QtGui.QLabel('Hello!')
l.addWidget(btn) # add your widget to the layout
l.addWidget(label) # add the label to the layout
self.setCentralWidget(w) # add the container widget to the QMainWindow
self.show()
app = QtGui.QApplication([])
window = MainWindow()
app.exec_()
If you want to be able to position widgets absolutely, rather than adding them to a layout (which will control their size/position) you can pass the parent element (relative to which x,y coords are taken) when creating it:
from PyQt4 import QtGui, QtCore
class MainWindow(QtGui.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
w = QtGui.QWidget() # container widget
btn = QtGui.QPushButton(w)
btn.move(100,100)
btn.setStyleSheet("border-image: url('somepicture.png');")
self.setCentralWidget(w) # add the container widget to the QMainWindow
self.show()
app = QtGui.QApplication([])
window = MainWindow()
app.exec_()
But positioning a widget absolutely like this loses you the ability to auto-scale it to fit the parent widget. If you just want some padding/spacing around the element in the window, take a look at .setContentsMargins on the QLayouts, e.g. l.setContentsMargins(50,50,50,50) will put a 50px margin around the button.

Moving from GTK to Qt

I have a small application written in python that I want to move from GTK+ to Qt.
The graphics interface in the GTK version is basically a tab widget (gtk.Notebook) that fills the whole top level window. The tab window grows and shrinks with the top level window and fills it completely.
In GTK the code looks like:
...
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
...
self.notebook = gtk.Notebook()
self.window.add(self.notebook)
...
How to do something similar in Qt? I just can't figure it out! For the GTK code I used no graphics tool, but now I'm trying to use Qt designer.
JW
This is how you would get a basic QTabWidget set up:
from PyQt4.QtCore import (Qt, SIGNAL)
from PyQt4.QtGui import (QApplication, QDialog,
QVBoxLayout, QPushButton, QTabWidget, QWidget, )
class Form(QWidget):
def __init__(self, parent=None):
super(Form, self).__init__(parent)
self.tabauto = QWidget() #set up 'auto' tab
self.tabman = QWidget() #set up 'manual' tab
self.tabs = QTabWidget() #set up tabs widget
self.ButtonM = QPushButton("Manual Button")
self.ButtonA = QPushButton("AUto Button")
layoutO = QVBoxLayout() #set overal layout
layoutA = QVBoxLayout()
layoutA.addWidget(self.ButtonA)
layoutM = QVBoxLayout()
layoutM.addWidget(self.ButtonM)
self.tabman.setLayout(layoutM) #Add manual layout to manual tab
self.tabauto.setLayout(layoutA) #Add automatic layout to automatic tab
self.tabs.addTab(self.tabauto, "Auto") #assign tabs with their layouts to the overall tab widget
self.tabs.addTab(self.tabman, "Manual") #assign tabs with their layouts to the overall tab widget
layoutO.addWidget(self.tabs) #add overall tab widget to overall layout
self.setLayout(layoutO) #make the overall layout visible
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()

Categories

Resources