The code below generates a window with a black background. Unfortunately the background is framed by a thin white line.
I've tried to set other background parameters to black, but it didn't work out.
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsScene
class GraphicsWindow(QGraphicsView):
def __init__(self, parent=None):
super(GraphicsWindow, self).__init__(parent)
scene = QGraphicsScene(self)
self.setScene(scene)
self.setBackgroundBrush(Qt.black)
def main():
app = QApplication(sys.argv)
graphics_window = GraphicsWindow()
graphics_window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I wanted to create a window with an entirely black background, but it has a thin white frame.
You have to change the background color of the QGraphicsView as for example with QPalette:
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPalette
from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsScene
class GraphicsWindow(QGraphicsView):
def __init__(self, parent=None):
super(GraphicsWindow, self).__init__(parent)
scene = QGraphicsScene(self)
self.setScene(scene)
self.setBackgroundBrush(Qt.black)
pal = self.palette()
pal.setColor(QPalette.Window, Qt.black)
self.setPalette(pal)
def main():
app = QApplication(sys.argv)
graphics_window = GraphicsWindow()
graphics_window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
You can add css styles inside the init method of your class:
def __init__(self, parent=None):
super(GraphicsWindow, self).__init__(parent)
scene = QGraphicsScene(self)
self.setScene(scene)
self.setBackgroundBrush(Qt.black)
self.setStyleSheet("border:0px")
Related
I have a problem with styles in PyQT5.
I would like to modify something in the "Fusion" style : when the page loses focus, the blue of some widgets becomes white, i would like to keep them blue.
But when i try to edit only the background color for a QprogressBar, the text is no more centered and there are some other changes.
(app.setStyleSheet("QProgressBar::chunk { background-color : blue}"))
I also tried app.my_progress_bar.setStyleSheed("background-color : blue") which seems to keep text centered but i don't know how to do it for "chunk" item.
Here is a little script if you want to test a solution :
import sys
import time
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QWidget, QPushButton, QProgressBar, QVBoxLayout, QApplication
class Thread(QThread):
_signal = pyqtSignal(int)
def __init__(self):
super(Thread, self).__init__()
def __del__(self):
self.wait()
def run(self):
for i in range(100):
time.sleep(0.1)
self._signal.emit(i)
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
self.setWindowTitle('QProgressBar')
self.btn = QPushButton('Click me')
self.btn.clicked.connect(self.btnFunc)
self.pbar = QProgressBar(self)
self.pbar.setValue(0)
self.resize(300, 100)
self.vbox = QVBoxLayout()
self.vbox.addWidget(self.pbar)
self.vbox.addWidget(self.btn)
self.setLayout(self.vbox)
self.show()
def btnFunc(self):
self.thread = Thread()
self.thread._signal.connect(self.signal_accept)
self.thread.start()
self.btn.setEnabled(False)
def signal_accept(self, msg):
self.pbar.setValue(int(msg))
if self.pbar.value() == 99:
self.pbar.setValue(0)
self.btn.setEnabled(True)
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setStyle("Fusion") ##### When the main windows loses focus, the progressbar becomes white instead of blue
ex = Example()
ex.show()
sys.exit(app.exec_())
When the window have the focus :
When the window does not have the focus :
There is no need to use style sheets as long as the color roles of the widget are known.
Specifically, QProgressBar normally uses the Highlight role, which has a different color for the Inactive color group, so you just need to override it.
palette = self.pbar.palette()
palette.setBrush(
palette.Inactive, palette.Highlight, palette.highlight())
self.pbar.setPalette(palette)
Note that the palette is only a reference, it's completely up to the style to decide which group/role use for a widget (or even completely ignore it). If you use another style than Fusion, the above might not work as expected.
use stylesheet for QProgressBar to achieve centered text and QProgressBar::chunk to keep background color even if it loses focus
import sys
import time
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QWidget, QPushButton, QProgressBar, QVBoxLayout, QApplication
class Thread(QThread):
_signal = pyqtSignal(int)
def __init__(self):
super(Thread, self).__init__()
def __del__(self):
self.wait()
def run(self):
for i in range(100):
time.sleep(0.1)
self._signal.emit(i)
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
self.setWindowTitle('QProgressBar')
self.btn = QPushButton('Click me')
self.btn.clicked.connect(self.btnFunc)
self.pbar = QProgressBar(self)
self.pbar.setValue(0)
# setting background color
self.pbar.setStyleSheet(
"QProgressBar"
"{"
"text-align:center;"
"}"
"QProgressBar::chunk"
"{"
"background-color : blue;"
"text-align:center;"
"color : #E0E0E0;"
"border : 1px"
"}"
)
self.resize(300, 100)
self.vbox = QVBoxLayout()
self.vbox.addWidget(self.pbar)
self.vbox.addWidget(self.btn)
self.setLayout(self.vbox)
self.show()
def btnFunc(self):
self.thread = Thread()
self.thread._signal.connect(self.signal_accept)
self.thread.start()
self.btn.setEnabled(False)
def signal_accept(self, msg):
self.pbar.setValue(int(msg))
if self.pbar.value() == 99:
self.pbar.setValue(0)
self.btn.setEnabled(True)
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setStyle("Fusion") ##### When the main windows loses focus, the progressbar becomes white instead of blue
ex = Example()
ex.show()
sys.exit(app.exec_())
I have 2 QGraphicsView and one QWebEngineView widget on the form and I need to * (on the click of the button1)* make a screenshot of the content inside this QWebEngineView with some defined setback from the original QWebEngineView borders and save that screenshot as an image, and at the same time keep it as an object and paste this object to the first QGraphicsView and * (on the click of button2)* insert saved image into the second QGraphicsView.
Edit:
(I'd like to make a screenshot of the area inside the QtWebEngineWidgets and keep this area as an object. and a second problem I need to know how to paste this area in to the QGraphicsView in 2 different ways: (from the file) and display it as an object without saving. 2 QGraphicsView are just for the studying purpose it could be just one QGraphicsView and by hitting on button1 screenshot is making and pasting as an object to the QGraphicsView and by hitting on button2 -screenshot is making (saving as an png and loading to the QGraphicsView))
Here is the code I have:
import sys, os
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QBrush, QPen, QScreen, QPixmap
from PyQt5.QtWidgets import QApplication, QStyleFactory, QMainWindow, QWidget, QVBoxLayout, QLabel
from PyQt5.QtWidgets import QGraphicsScene, QGraphicsView, QGraphicsItem, QPushButton
from pyqtgraph.Qt import QtCore, QtGui
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWidgets import QApplication, QDialog
class Geometry(QGraphicsView):
def __init__(self):
QGraphicsView.__init__(self)
class CentralPanel(QWidget):
def __init__(self):
QWidget.__init__(self)
self.lblCoords = QLabel('MAP SELECTOR (object image): ')
self.lblCoords2 = QLabel('MAP SELECTOR (loaded from file image): ')
self.gvwShapes = Geometry()
self.gvwShapes2 = Geometry()
vbxDsply = QVBoxLayout()
vbxDsply.addWidget(self.lblCoords) # Capture coordinates of drawn line at window 1
vbxDsply.addWidget(self.gvwShapes) # add QGraphicsView #1
vbxDsply.addWidget(self.lblCoords2) # Capture coordinates of drawn line at window 2
vbxDsply.addWidget(self.gvwShapes2) # add QGraphicsView #2
self.webEngineView = QWebEngineView() # Add Google maps web window
self.webEngineView.load(QtCore.QUrl("https://www.google.com/maps/#36.797966,-97.1413048,3464a,35y,0.92h/data=!3m1!1e3"))
vbxDsply.addWidget(self.webEngineView)
self.Button1 = QPushButton('Do screenshot of webEngineView save it and paste it into QGraphicsView2', self) # Button to load image to graphics view
vbxDsply.addWidget(self.Button1)
self.Button1.clicked.connect(self.button_screenshot)
self.Button2 = QPushButton('Do screenshot of webEngineView and paste it into QGraphicsView1 ', self)
vbxDsply.addWidget(self.Button2)
self.Button2.clicked.connect(self.button_load_image)
self.setLayout(vbxDsply)
self.filename = "image.jpg"
def button_screenshot(self):
print('Screenshot is taken and saved as an image, Image loaded and inserted into the gvwShapes QGraphicsView1 ')
app = QApplication(sys.argv)
QScreen.grabWindow(app.primaryScreen(), QApplication.desktop().winId()).save(self.filename, 'png')
def button_load_image(self):
print('Screenshot is taken and inserted into the gvwShapes2 QGraphicsView2')
# pix = QPixmap()
# pix.load(self.filename)
# pix = QPixmap(self.filename)
# item = QGraphicsPixmapItem(pix)
# scene = QGraphicsScence(self)
# scene.addItem(item)
# self.graphicsView.setScene(scene)
scene = QtWidgets.QGraphicsScene(self)
pixmap = QPixmap(self.filename)
item = QtWidgets.QGraphicsPixmapItem(pixmap)
scene.addItem(item)
self.gvwShapes.setScene(scene)
# scene = self.gvwShapes
# self.image = QtGui.QPixmap(self.filename)
# self.gvwShapes.add
# scene.addItem(QtGui.QGraphicsPixmapItem(self.image))
# self.view = self.QGraphicsView
# self.view.setScene(self.image)
# self.view.show()
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setGeometry(200, 50, 700, 900)
self.setWindowTitle('MAP Selector REV01')
self.setStyle(QStyleFactory.create('Cleanlooks'))
self.CenterPane = CentralPanel()
self.setCentralWidget(self.CenterPane)
# Catching exceptions and running a main loop
#
import traceback
def except_hook(exc_type, exc_value, exc_tb):
tb = "".join(traceback.format_exception(exc_type, exc_value, exc_tb))
print("error cached")
print("error message:\n", tb)
if __name__ == "__main__":
MainEventThred = QApplication([])
os.environ["QTWEBENGINE_CHROMIUM_FLAGS"] = "--enable-logging --log-level=3"
sys.excepthook = except_hook
MainApp = MainWindow()
MainApp.show()
MainEventThred.exec()
Crop image in QWebEngineView
If you want to implement the crop of the QWebEngineView screenshot then you must use a QRubberBand that is on the focusProxy () of the QWebEngineView (it is the widget where the web page is rendered and receives the mouse event that is created after displaying the view)
from functools import cached_property
import sys
from PyQt5.QtCore import pyqtSignal, QEvent, QObject, QPoint, QRect, QSize, QUrl
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QApplication, QLabel, QRubberBand
from PyQt5.QtWebEngineWidgets import QWebEngineView
class RubberBandManager(QObject):
pixmap_changed = pyqtSignal(QPixmap, name="pixmapChanged")
def __init__(self, widget):
super().__init__(widget)
self._origin = QPoint()
self._widget = widget
self.widget.installEventFilter(self)
#property
def widget(self):
return self._widget
#cached_property
def rubberband(self):
return QRubberBand(QRubberBand.Rectangle, self.widget)
def eventFilter(self, source, event):
if self.widget is source:
if event.type() == QEvent.MouseButtonPress:
self._origin = event.pos()
self.rubberband.setGeometry(QRect(self._origin, QSize()))
self.rubberband.show()
elif event.type() == QEvent.MouseMove:
self.rubberband.setGeometry(
QRect(self._origin, event.pos()).normalized()
)
elif event.type() == QEvent.MouseButtonRelease:
rect = self.rubberband.geometry()
pixmap = self.widget.grab(rect)
self.pixmap_changed.emit(pixmap)
self.rubberband.hide()
return super().eventFilter(source, event)
if __name__ == "__main__":
app = QApplication(sys.argv)
view = QWebEngineView()
view.load(
QUrl(
"https://www.google.com/maps/#36.797966,-97.1413048,3464a,35y,0.92h/data=!3m1!1e3"
)
)
view.show()
rubberband_manager = RubberBandManager(view.focusProxy())
label = QLabel()
label.hide()
def on_pixmap_changed(pixmap):
label.setPixmap(pixmap)
label.adjustSize()
label.show()
rubberband_manager.pixmap_changed.connect(on_pixmap_changed)
ret = app.exec()
sys.exit(ret)
Show an Image in QGraphicsView
To display an image then you must use a QGraphicsPixmapItem where you load a QPixmap.
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap, QPainter, QPalette
from PyQt5.QtWidgets import (
QApplication,
QGraphicsView,
QGraphicsScene,
QGraphicsPixmapItem,
)
class ImageViewer(QGraphicsView):
def __init__(self, parent=None):
super().__init__(parent)
self.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
self.setAlignment(Qt.AlignCenter)
self.setBackgroundRole(QPalette.Dark)
scene = QGraphicsScene()
self.setScene(scene)
self._pixmap_item = QGraphicsPixmapItem()
scene.addItem(self._pixmap_item)
def load_pixmap(self, pixmap):
self._pixmap_item.setPixmap(pixmap)
self.fitToWindow()
def fitToWindow(self):
self.fitInView(self.sceneRect(), Qt.KeepAspectRatio)
def resizeEvent(self, event):
super().resizeEvent(event)
self.fitToWindow()
if __name__ == "__main__":
app = QApplication(sys.argv)
view = ImageViewer()
view.resize(640, 480)
view.show()
pixmap = QPixmap("image.jpg")
view.load_pixmap(pixmap)
ret = app.exec()
sys.exit(ret)
The previous widget is used to load an image from a file: pixmap = QPixmap("/path/of/image") or use the QPixmap provided by pixmap_changed signal of RubberBandManager.
Set a scene for your QGraphicsViews.
self.gvwShapes = Geometry()
self.gvwShapes2 = Geometry()
self.gvwShapes.setScene(QGraphicsScene())
self.gvwShapes2.setScene(QGraphicsScene())
Use QWidget.grab() to render it into a QPixmap and QGraphicsScene.addPixmap() to add it to the scene. You can specify the area with a QRect.
def button_screenshot(self):
pixmap = self.webEngineView.grab(QRect(180, 100, 300, 280))
pixmap.save(self.filename)
self.gvwShapes2.scene().addPixmap(pixmap)
def button_load_image(self):
self.gvwShapes.scene().addPixmap(QPixmap(self.filename))
I am making an window where i want to have round corners,I know it can be very easy by setting
self.mainframe=QFrame(self)
self.mainframe.setStyleSheet("background:blue;border-radius:25px")
self.setCentralWidget(self.mainframe)
self.setWindowFlags(Qt.FramelessWindowHint)
self.setAttribute(Qt.WA_TranslucentBackground)
It has nicely rounded, I mean corners are smooth(Antialiased).
But I dont want to go with this for a reason.I have a second option that i set a mask using QPainterPath in resizeEvent.
Here is the code
def resizeEvent(self, event):
path = QPainterPath()
print(self.rect())
path.addRoundedRect(QRectF(self.rect()),25, 25,Qt.AbsoluteSize)
reg = QRegion(path.toFillPolygon().toPolygon())
self.setMask(reg)
But its corners are not smooth means Antialiased.
Here is my complete code:
import sys
from PyQt5.QtCore import Qt, QRectF
from PyQt5.QtGui import QPainterPath, QRegion
from PyQt5.QtWidgets import QApplication, QMainWindow, QFrame
class Example(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.resize(600,400)
self.mainframe=QFrame(self)
self.mainframe.setStyleSheet("background:blue;border-radius:25px")
self.setCentralWidget(self.mainframe)
# self.setWindowFlags(Qt.FramelessWindowHint)
# self.setAttribute(Qt.WA_TranslucentBackground)
def resizeEvent(self, event):
path = QPainterPath()
print(self.rect())
path.addRoundedRect(QRectF(self.rect()),25, 25,Qt.AbsoluteSize)
reg = QRegion(path.toFillPolygon().toPolygon())
self.setMask(reg)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Example()
window.show()
sys.exit(app.exec_())
Is There any way to achieve that.I mean to look like 1st one?
I'm trying to create a layout with pyqt5, but i cannot do it. There are so many error. Why i am getting so many errors.
autoFillBackground() takes no arguments, and MainWindow will not assume the palette of it's central widget unless you explicitly set it. Also, this has nothing to do with a layout.
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class Color(QWidget):
def __init__(self, color):
super().__init__()
self.autoFillBackground()
palette = self.palette()
palette.setColor(QPalette.Window, QColor(color))
self.setPalette(palette)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
widget = Color('Blue')
self.setCentralWidget(widget)
self.setPalette(widget.palette())
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
I have a QMainWindow with a toolbar, and I'm having troubles with fitting the QPixmap to the window, such that it won't tackle with the toolbar.
I want to display the picture:
And from the code:
import sys
from PyQt5.QtCore import QRect
from PyQt5.QtWidgets import QAction, QMainWindow, QApplication
from PyQt5.QtGui import QPixmap, QPainter
class Menu(QMainWindow):
def __init__(self):
super().__init__()
newAct = QAction('New', self)
self.toolbar = self.addToolBar('Remove')
self.toolbar.addAction(newAct)
self.image = QPixmap("background.png")
self.setGeometry(100, 30, 500, 300)
self.resize(self.image.width(), self.image.height())
self.show()
def paintEvent(self, event):
painter = QPainter(self)
rect = QRect(0, 0, self.image.width(), self.image.height())
painter.drawPixmap(rect, self.image)
if __name__ == '__main__':
app = QApplication(sys.argv)
mainMenu = Menu()
sys.exit(app.exec_())
I get:
And as you can see, The picture is on the toolbar as well, and I don't want that.
Another try:
import sys
from PyQt5.QtCore import QRect
from PyQt5.QtWidgets import QAction, QMainWindow, QApplication
from PyQt5.QtGui import QPixmap, QPainter
class Menu(QMainWindow):
def __init__(self):
super().__init__()
newAct = QAction('New', self)
self.toolbar = self.addToolBar('Remove')
self.toolbar.addAction(newAct)
self.image = QPixmap("background.png")
self.setGeometry(100, 30, 500, 300)
self.resize(self.image.width(), self.image.height() + self.toolbar.height())
self.show()
def paintEvent(self, event):
painter = QPainter(self)
rect = QRect(0, self.toolbar.height(), self.image.width(), self.image.height() + self.toolbar.height())
painter.drawPixmap(rect, self.image)
if __name__ == '__main__':
app = QApplication(sys.argv)
mainMenu = Menu()
sys.exit(app.exec_())
But I get:
And as you can see, I don't see one of the lines (the blue one).
How can I fix it, so the picture will fit the window excluding the toolbar?
In addition to that, it means I'll have to change all my mouse clicks to move the y-axis. Is there perhaps a way I can set everything such that (x,y)=(0,0) would be at the uppermost left, below the toolbar?
I'm using Python 3.6.5 |Anaconda custom (64-bit) on windows | PyQt version: 5.9.2
Although I can not reproduce the problem, the following solution must work, in it I draw the image in a widget and I set them as centralwidget.
import sys
from PyQt5.QtCore import QRect
from PyQt5.QtWidgets import QAction, QMainWindow, QApplication, QWidget
from PyQt5.QtGui import QPixmap, QPainter
class Widget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.image = QPixmap("background.png")
self.setFixedSize(self.image.size())
def paintEvent(self, event):
painter = QPainter(self)
painter.drawPixmap(self.rect(), self.image)
class Menu(QMainWindow):
def __init__(self):
super().__init__()
newAct = QAction('New', self)
self.toolbar = self.addToolBar('Remove')
self.toolbar.addAction(newAct)
self.setCentralWidget(Widget())
self.setFixedSize(self.sizeHint())
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
mainMenu = Menu()
sys.exit(app.exec_())