PyQt5 - drawPixmap on QMainWindow with toolbar (can't fit to window) - python

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_())

Related

My custom widget not react to my paintEvent on other sessions

Im trying to develop a program which have many of my custom widget. in my widget i have a crosshair mouse pointer and when i move it in one of my widgets, all of them must sense it and the crosshair must react on every single widget.
I have a self.update() on the end of the paintEnent function.
How can i force the other widgets on my app to react it?
paintEvent is not a simple code like this and as i add every functions on this part, it make a very high CPU usage. How can i manage it?
import sys
from PyQt5.QtWidgets import QApplication, QDialog, QListWidget,
QComboBox, QVBoxLayout, QPushButton, QLabel, QMainWindow, QWidget,
QHBoxLayout, QVBoxLayout, QSizePolicy
from PyQt5.QtCore import Qt, QSize, QRect
from PyQt5.QtGui import QPalette, QColor, QPen, QPixmap, QPainter,
QBrush
class Boom(QWidget):
xPos=-1.0
def __init__(self,bgColor,xSpace=1,ySpace=1):
super().__init__()
self.bgColor=bgColor
self.x = -1
self.y = -1
self.setSizePolicy(QSizePolicy.MinimumExpanding,QSizePolicy.MinimumExpanding)
self.setMouseTracking(True)
layout = QVBoxLayout()
self.setLayout(layout)
def mouseMoveEvent(self, event):
global xPos
self.x = event.x()
self.y = event.y()
xPos=self.x/self.width()
self.update()
def paintEvent(self, e):
painter = QPainter(self)
font = painter.font()
font.setFamily('Times')
font.setPointSize(8)
painter.setFont(font)
brush = QBrush()
brush.setColor(QColor(self.bgColor))
brush.setStyle(Qt.SolidPattern)
pen = QPen()
pen.setWidth(1)
pen.setColor(QColor('black'))
painter.setPen(pen)
rect = QRect(0, 0, painter.device().width(), painter.device().height())
painter.fillRect(rect, brush)
pen.setColor(QColor('blue'))
painter.setPen(pen)
painter.drawLine(self.x, 0, self.x,painter.device().height()) #V
painter.drawLine(0, self.y, painter.device().width(),self.y) #H
self.update()
painter.end()
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle("Graph")
MainPanelLayout = QHBoxLayout()
MainPanelLayout.setContentsMargins(1,1,1,1)
MainPanelLayout.setSpacing(1)
B1=Boom('pink',0)
B2=Boom('gray',1)
MainPanelLayout.addWidget(B1)
MainPanelLayout.addWidget(B2)
widget = QWidget()
widget.setLayout(MainPanelLayout)
self.setCentralWidget(widget)
if __name__ == "__main__":
app = QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
# mainWindow.showMaximized()
app.exec_()
Iv found a way!
I used signal and slots to communicate between instances
May it works for others too :)
import sys
from PyQt5.QtWidgets import QApplication, QDialog, QListWidget,QComboBox, QVBoxLayout, QPushButton, QLabel, QMainWindow,QWidget, QHBoxLayout, QVBoxLayout, QSizePolicy
from PyQt5.QtCore import Qt, QSize, QRect, QObject, pyqtSignal
from PyQt5.QtGui import QPalette, QColor, QPen, QPixmap, QPainter,QBrush
import FxMainForm
class BoomCommunicate(QObject):
signal = pyqtSignal()
class Boom(QWidget):
xPos=-1
def __init__(self,bgColor,nChannel=-1,xSpace=1,ySpace=1):
super().__init__()
self.bgColor=bgColor
self.xSpace=xSpace
self.ySpace=ySpace
self.x = -1
self.y = -1
self.nChannel=nChannel
self.setSizePolicy(QSizePolicy.MinimumExpanding,QSizePolicy.MinimumExpanding)
self.setMouseTracking(True)
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.communicate = BoomCommunicate()
self.communicate.signal.connect(self.trigger_refresh)
def mouseMoveEvent(self, event):
self.x = event.x()
self.y = event.y()
if self.nChannel==0:
Boom.xPos=self.x/self.width()
self.communicate.signal.emit()
def paintEvent(self, e):
painter = QPainter(self)
font = painter.font()
font.setFamily('Times')
font.setPointSize(8)
painter.setFont(font)
brush = QBrush()
brush.setColor(QColor(self.bgColor))
brush.setStyle(Qt.SolidPattern)
pen = QPen()
pen.setWidth(1)
pen.setColor(QColor('black'))
painter.setPen(pen)
## Border
rect = QRect(0, 0, painter.device().width(), painter.device().height())
painter.fillRect(rect, brush)
pen.setColor(QColor('blue'))
painter.setPen(pen)
# self.Drawings(painter,pen,brush)
if self.nChannel==0:
painter.setPen(QPen(Qt.red, 1, Qt.SolidLine))
painter.drawLine(self.x, self.ySpace, self.x,painter.device().height()-self.ySpace-1) ##V
painter.drawLine(self.xSpace, self.y, painter.device().width()-self.ySpace-1,self.y) ##H
if not FxMainForm.studyItem==None:
painter.setPen(QPen(Qt.black, 1, Qt.SolidLine))
painter.drawText(5, 15,FxMainForm.studyItem[0]+' ('+FxMainForm.studyItem[1]+') ')
Boom.xPos=self.x/self.width()
else:
painter.setPen(QPen(Qt.red, 1, Qt.SolidLine))
painter.drawLine(int(Boom.xPos*painter.device().width()), self.ySpace,int(Boom.xPos*painter.device().width()),painter.device().height()-self.ySpace-1)
painter.end()
def trigger_refresh(self):
self.update()
def sizeHint(self):
return QSize(100, 100)
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle("Graph-Boom")
self.MainPanelLayout = QHBoxLayout()
self.MainPanelLayout.setContentsMargins(1,1,1,1)
self.MainPanelLayout.setSpacing(1)
self.B1=Boom('pink',0)
self.B2=Boom('gray',1)
self.MainPanelLayout.addWidget(self.B1)
self.MainPanelLayout.addWidget(self.B2)
self.B1.communicate.signal.connect(self.B2.update)
self.widget = QWidget()
self.widget.setLayout(self.MainPanelLayout)
self.setCentralWidget(self.widget)
if __name__ == "__main__":
app = QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
# mainWindow.showMaximized()
app.exec_()

Pyqt5 QLabel with image at top and text at bottom

I am trying to create a PyQt5 - QLabel with both image and text. I would like to have a text at the bottom of the image. Below is a part of the code
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Window(QWidget):
def __init__(self, *args, **kwargs):
QWidget.__init__(self, *args, **kwargs)
l4=QLabel()
l4.setText('delete')
l4.setAlignment(Qt.AlignBottom)
pixmap = QPixmap("/home/moh/Documents/My_GUI/Icons/Delete.png")
l4.setPixmap(pixmap)
l4.setAlignment(Qt.AlignTop)
self.layout = QGridLayout()
self.layout.addWidget(l4, 0, 0)
self.setLayout(self.layout)
self.show()
app = QApplication(sys.argv)
win = Window()
sys.exit(app.exec_())
You have to use 2 QLabel in a QVBoxLayout:
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QApplication, QLabel, QVBoxLayout, QWidget
class Window(QWidget):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
pixmap_label = QLabel(
pixmap=QPixmap("/home/moh/Documents/My_GUI/Icons/Delete.png")
)
text_label = QLabel(text="delete")
lay = QVBoxLayout(self)
lay.addWidget(pixmap_label, alignment=Qt.AlignCenter)
lay.addWidget(text_label, alignment=Qt.AlignCenter)
if __name__ == "__main__":
app = QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())
If you want to use a circle Qlabel image, use this code:
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap, QPainterPath, QPainter
from PyQt5.QtWidgets import QApplication, QLabel, QVBoxLayout, QWidget
class Label(QLabel):
def __init__(self, *args, antialiasing=True, **kwargs):
super(Label, self).__init__(*args, **kwargs)
self.Antialiasing = antialiasing
self.setMaximumSize(90, 90)
self.setMinimumSize(90, 90)
self.radius = 45
self.target = QPixmap(self.size())
self.target.fill(Qt.transparent)
p = QPixmap("Image.jpg").scaled(
90, 90, Qt.KeepAspectRatioByExpanding, Qt.SmoothTransformation)
painter = QPainter(self.target)
if self.Antialiasing:
painter.setRenderHint(QPainter.Antialiasing, True)
painter.setRenderHint(QPainter.HighQualityAntialiasing, True)
painter.setRenderHint(QPainter.SmoothPixmapTransform, True)
path = QPainterPath()
path.addRoundedRect(
0, 0, self.width(), self.height(), self.radius, self.radius)
painter.setClipPath(path)
painter.drawPixmap(0, 0, p)
self.setPixmap(self.target)
class Window(QWidget):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
pixmap_label = Label()
text_label = QLabel(text="delete")
lay = QVBoxLayout(self)
lay.addWidget(pixmap_label, alignment=Qt.AlignCenter)
lay.addWidget(text_label, alignment=Qt.AlignCenter)
if __name__ == "__main__":
app = QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())

How to show new QMainWindow in every loop in PyQT5?

I'm trying to write a Python program using PyQt5 that will display a window in each iteration of the for loop. I would like to close after incrementing and displaying the next window. However, I do not know how to stop the loop every iteration and at the moment I am getting 6 windows at once.
main.py
import sys
from PyQt5.QtWidgets import (QLineEdit, QVBoxLayout, QMainWindow,
QWidget, QDesktopWidget, QApplication, QPushButton, QLabel,
QComboBox, QFileDialog, QRadioButton)
from PyQt5.QtCore import pyqtSlot, QByteArray
from alert import Window2
from test import test
class SG(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.resize(300, 150)
self.setWindowTitle('TEST')
self.resultsGen = QPushButton('TEST', self)
self.resultsGen.clicked.connect(lambda: self.on_click())
self.show()
#pyqtSlot()
def on_click(self):
test(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
sg = SG()
sys.exit(app.exec_())
alert.py
from PyQt5.QtWidgets import (QLineEdit, QVBoxLayout, QMainWindow,
QWidget, QDesktopWidget, QApplication, QPushButton, QLabel,
QComboBox, QFileDialog, QRadioButton)
from PyQt5.QtCore import pyqtSlot, QByteArray
from PyQt5.QtGui import QPixmap
from PyQt5 import QtGui, QtCore
class Window2(QMainWindow):
def __init__(self):
super().__init__()
self.initPopup()
def initPopup(self):
self.resize(500, 500)
self.setWindowTitle("Window22222")
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
lay = QVBoxLayout(self.central_widget)
label = QLabel(self)
pixmap = QPixmap('cropped/8.png')
label.setPixmap(pixmap)
self.resize(pixmap.width(), pixmap.height())
lay.addWidget(label)
self.textbox = QLineEdit(self)
self.textbox.move(20, 20)
self.textbox.resize(280, 40)
# Create a button in the window
self.button = QPushButton('Show text', self)
self.button.move(20, 80)
# connect button to function on_click
self.button.clicked.connect(lambda: self.on_clickX())
self.show()
#pyqtSlot()
def on_clickX(self):
textboxValue = self.textbox.text()
print(textboxValue)
self.textbox.setText("")
self.hide()
test.py
from alert import Window2
def test(self):
for x in range(6):
w = Window2()
As soon as you run the for cycle, all the code of the initialization will be executed, which includes the show() call you used at the end of initPopup().
A simple solution is to create a new signal that is emitted whenever you hide a window, and connect that signal to a function that creates a new one until it reaches the maximum number.
main.py:
import sys
from PyQt5.QtWidgets import QWidget, QApplication, QPushButton
from alert import Window2
class SG(QWidget):
def __init__(self):
super().__init__()
self.initUI()
self.alerts = []
def initUI(self):
self.resize(300, 150)
self.setWindowTitle('TEST')
self.resultsGen = QPushButton('TEST', self)
self.resultsGen.clicked.connect(self.nextAlert)
self.show()
def nextAlert(self):
if len(self.alerts) >= 6:
return
alert = Window2()
self.alerts.append(alert)
alert.setWindowTitle('Window {}'.format(len(self.alerts)))
alert.closed.connect(self.nextAlert)
alert.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
sg = SG()
sys.exit(app.exec_())
alert.py:
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Window2(QMainWindow):
closed = pyqtSignal()
def __init__(self):
super().__init__()
self.initPopup()
def initPopup(self):
self.resize(500, 500)
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
lay = QVBoxLayout(self.central_widget)
label = QLabel(self)
pixmap = QPixmap('cropped/8.png')
label.setPixmap(pixmap)
self.resize(pixmap.width(), pixmap.height())
lay.addWidget(label)
self.textbox = QLineEdit(self)
lay.addWidget(self.textbox)
# Create a button in the window
self.button = QPushButton('Show text', self)
lay.addWidget(self.button)
# connect button to function on_click
self.button.clicked.connect(lambda: self.on_clickX())
self.show()
#pyqtSlot()
def on_clickX(self):
textboxValue = self.textbox.text()
print(textboxValue)
self.textbox.setText("")
self.hide()
self.closed.emit()
Just note that with this very simplified example the user might click on the button of the "SG" widget even if an "alert" window is visibile. You might prefer to use a QDialog instead of a QMainWindow and make the main widget a parent of that dialog.
main.py:
class SG(QWidget):
# ...
def nextAlert(self):
if len(self.alerts) >= 6:
return
alert = Window2(self)
# ...
alert.py:
class Window2(QDialog):
closed = pyqtSignal()
def __init__(self, parent):
super().__init__()
self.initPopup()
def initPopup(self):
self.resize(500, 500)
# a QDialog doesn't need a central widget
lay = QVBoxLayout(self)
# ...
Also, if an alert window is closed using the "X" button the new one will not be shown automatically. To avoid that, you can implement the "closeEvent" and ignore the event, so that the user will not be able to close the window until the button is clicked. As QDialogs can close themself when pressing the escape key, I'm also ignoring that situation.
alert.py:
class Window2(QMainWindow):
# ...
def closeEvent(self, event):
event.ignore()
def keyPressEvent(self, event):
if event.key() != Qt.Key_Escape:
super().keyPressEvent(event)

How to set window and it's graphicScene transparent(using slider) and leave only QPushButton visible

I want my window and it's QGraphicsScene to be transparent which is controlled by QSlider.
I tried looking for some answers here and there, but it's mainly setting background color to 0 :
self.setStyleSheet("background-color:rgba(0, 0, 0, 0);")
or like that :
self.setWindowFlags(Qt.FramelessWindowHint)
self.setAttribute(Qt.WA_TranslucentBackground)
Which does it job, but I would like to make slider which will control level of transparency and I don't see how can I do it with commands above.
Can somebody please give me some advise how to do it ? Thank you
I will attach my test code here below(I want to be able to control transparency of everything , but do not touch slider and button):
from PySide2.QtGui import QBrush, QColor
from PySide2.QtCore import QSize, Qt
from PySide2.QtWidgets import QDialog, QVBoxLayout, QGraphicsView, QGraphicsScene, QFrame, QSizePolicy, QApplication, QSlider, QPushButton
class MainWindow(QDialog):
def __init__(self):
QDialog.__init__(self)
self.mainLayout = QVBoxLayout()
self.graphicsWidget = MainGraphicsWidget()
self.window = 'transp_test'
self.title = 'transparent UI'
self.size = (1000, 650)
self.create()
def create(self, **kwargs):
self.setWindowTitle(self.title)
self.resize(QSize(*self.size))
self.setLayout(self.mainLayout)
self.mainLayout.addWidget(self.graphicsWidget)
class MainGraphicsWidget(QGraphicsView):
def __init__(self, parent=None):
super(MainGraphicsWidget, self).__init__(parent)
self._scene = QGraphicsScene(backgroundBrush = Qt.gray)
self.setScene(self._scene)
self.transpSlider = QSlider()
self.transpSlider.setRange(0,100)
self.mainButton = QPushButton('I want it to be "Test" button')
self._scene.addWidget(self.mainButton)
self._scene.addWidget(self.transpSlider)
self.transpSlider.move(300, 100)
self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
self.setResizeAnchor(QGraphicsView.AnchorUnderMouse)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setBackgroundBrush(QBrush(QColor(30, 30, 30)))
self.setFrameShape(QFrame.NoFrame)
self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = MainWindow()
window.setGeometry(600, 300, 600, 600)
window.show()
sys.exit(app.exec_())
Here is one way.
class MainWindow(QDialog):
def __init__(self):
QDialog.__init__(self)
# these two lines are needed to get a transparent background in windows
self.setWindowFlags(Qt.FramelessWindowHint)
self.setAttribute(Qt.WA_TranslucentBackground)
# rest of class definition unchanged
class MainGraphicsWidget(QGraphicsView):
def __init__(self, parent=None):
super(MainGraphicsWidget, self).__init__(parent)
# set transparent background color for the widget itself
self.setStyleSheet("background-color: #00000000")
self._scene = QGraphicsScene()
self.setScene(self._scene)
# create of slider and connect to slot for changing opacity.
self.transpSlider = QSlider()
self.transpSlider.setStyleSheet('background-color: #00000000')
self.transpSlider.setRange(0,255)
self.transpSlider.valueChanged.connect(self.set_opacity)
self.transpSlider.setValue(255)
# rest of __init__ unchanged
def set_opacity(self, value):
brush = self.backgroundBrush()
color = brush.color()
color.setAlpha(value)
brush.setColor(color)
self.setBackgroundBrush(color)
Note that I've changed the range of the slider to 0-255 to make changing the opacity from fully opaque to fully transparent easier.
Try it:
#from PySide2.QtGui import QBrush, QColor
#from PySide2.QtCore import QSize, Qt
#from PySide2.QtWidgets import QDialog, QVBoxLayout, QGraphicsView, QGraphicsScene, QFrame, QSizePolicy, QApplication, QSlider, QPushButton
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtGui import QBrush, QColor
from PyQt5.QtCore import QSize, Qt
from PyQt5.QtWidgets import (QDialog, QVBoxLayout, QGraphicsView, QGraphicsScene,
QFrame, QSizePolicy, QApplication, QSlider, QPushButton)
class MainGraphicsWidget(QGraphicsView):
def __init__(self, parent=None):
super(MainGraphicsWidget, self).__init__(parent)
self._scene = QGraphicsScene()
self.setScene(self._scene)
self.transpSlider = QtWidgets.QSlider(
QtCore.Qt.Horizontal,
minimum=10,
maximum=100,
value=100,
valueChanged=self.onValueChanged,
)
self.mainButton = QPushButton('I want it to be "Test" button \n QUIT')
self.mainButton.resize(150, 150)
self.mainButton.clicked.connect(parent.close)
self._scene.addWidget(self.mainButton)
self._scene.addWidget(self.transpSlider)
self.transpSlider.move(300, 100)
self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
self.setResizeAnchor(QGraphicsView.AnchorUnderMouse)
c = QColor(220, 30, 30)
c.setAlphaF(1)
self.setBackgroundBrush(QBrush(c))
self.setFrameShape(QFrame.NoFrame)
self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
#QtCore.pyqtSlot(int)
def onValueChanged(self, value):
c = QColor(220, 30, 30)
c.setAlphaF(value * 0.01)
self.setBackgroundBrush(QBrush(c))
window.setWindowOpacity(value * 0.03)
self.setStyleSheet("MainGraphicsWidget {{background-color: rgba(0, 215, 55, {});}}".format(value))
class MainWindow(QDialog):
def __init__(self):
super().__init__()
self.setAttribute(Qt.WA_NoSystemBackground, False)
self.setStyleSheet("MainWindow {background-color: rgba(0, 215, 55, 70);}")
self.graphicsWidget = MainGraphicsWidget(self)
self.window = 'transp_test'
self.title = 'transparent UI'
self.size = (1000, 650)
self.setWindowTitle(self.title)
self.resize(QSize(*self.size))
self.mainLayout = QVBoxLayout()
self.setLayout(self.mainLayout)
self.mainLayout.addWidget(self.graphicsWidget)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = MainWindow()
window.setGeometry(600, 100, 600, 600)
window.show()
sys.exit(app.exec_())

Adding custom widgets to a QScrollArea in pyqt5 does not make scrollbar appear

The example shown below adds a very simple custom pyqt5 widget to a QScrollArea. When i move the custom widget "off" the area of the scroll area I would expect that scrollbars should appear. Obviously this is not the case.
#!/usr/bin/python3
from PyQt5.QtWidgets import QMainWindow, QWidget, QApplication, QScrollArea
from PyQt5.QtCore import QObject
from PyQt5.QtGui import QPainter, QColor, QPen
import sys
class ExampleWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent=parent)
def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
self.drawWidget(qp)
qp.end()
def drawWidget(self, qp):
qp.setPen(QColor(255, 0, 0))
qp.setBrush(QColor(255, 0, 0))
qp.drawRect(0, 0, 100, 100)
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.setGeometry(300, 300, 300, 200)
self.scrollArea = QScrollArea(self)
self.setCentralWidget(self.scrollArea)
self.widget = ExampleWidget(self.scrollArea)
self.widget.setGeometry(250, 150, 100, 100)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
How can I make the scrollbars appear once a widget is moved so it's not visible completely anymore?
In the code that samples ExampleWidget is a child of QScrollArea: self.widget = ExampleWidget(self.scrollArea), that does not imply that the widget is handled with the properties of the QScrollArea, the QScrollArea has a viewport() that is the background widget and the QScrollArea only shows a part of it. So if you want a widget to be inside you have to use the setWidget() method. On the other hand that viewport() has the size of the content and how it calculates that size ?, by default it uses the sizeHint() of the widget, and in your case it does not have it so it will not show what you want.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class ExampleWidget(QtWidgets.QWidget):
def paintEvent(self, e):
qp = QtGui.QPainter(self)
self.drawWidget(qp)
def drawWidget(self, qp):
qp.setPen(QtGui.QColor(255, 0, 0))
qp.setBrush(QtGui.QColor(255, 0, 0))
qp.drawRect(0, 0, 100, 100)
def sizeHint(self):
return QtCore.QSize(500, 500)
class Example(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.scrollArea = QtWidgets.QScrollArea()
self.setCentralWidget(self.scrollArea)
self.widget = ExampleWidget()
self.scrollArea.setWidget(self.widget)
self.show()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

Categories