Can't remove margins from QVBoxLayout - python

I have set up an image button with some text, but the image does not align with the text due to some extra margins. How can I get rid of these margins? I have tried setting setContentsMargins(0,0,0,0) and setSpacing(0) on various components but it doesn't seem to affect the correct margins.
Here is a demo:
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class ImageButton(QWidget):
def __init__(self, img_location):
QWidget.__init__(self)
self.img_location = img_location
self.button = QToolButton(self)
self.button.clicked.connect(self.handleButton)
self.button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
self.button.setIcon(QIcon(img_location))
self.button.setIconSize(QSize(300,400))
layout = QVBoxLayout(self)
layout.addWidget(self.button)
def handleButton(self):
print(self.img_location)
app = QApplication([])
window = QMainWindow()
window.resize(800,600)
label_title = QLabel("bob asdfjak f ajksf asljf ajdslf aldskj ksf kslfhadjks lfhiu sofhjaklfsiuod fahklfhadisufaksufhdsuifhosa fasdf afsda")
label_title.setStyleSheet('background-color: yellow')
label_title.setAlignment(Qt.AlignCenter)
label_title.adjustSize()
label_title.setWordWrap(True)
imgbtn = ImageButton("a.png")
imgbtn.setStyleSheet('background-color: green')
layout_box = QVBoxLayout()
layout_box.setContentsMargins(0,0,0,0)
layout_box.setSpacing(0)
layout_box.addWidget(imgbtn, 0, Qt.AlignTop)
layout_box.addWidget(label_title, 0, Qt.AlignTop)
layout_box.setAlignment(Qt.AlignCenter)
layout_box.setSpacing(0)
content = QWidget()
content.setStyleSheet('background-color: blue')
content.setFixedWidth(300)
content.setFixedHeight(400)
content.setLayout(layout_box)
window.setCentralWidget(content)
window.show()
app.exec_()
The Yellow region marks the text label, the Green region marks the imagebutton, and the Blue region marks the space I'm trying to get rid of. See how the yellow region expands to the size of the blue, with the end result that the text doesn't align to the imagebutton.
How can I get rid of this blue region?

That margin is that of the QVBoxLayout that you use to place the QToolButton inside ImageButton, so the solution is to set it to 0 that margin:
# ...
class ImageButton(QWidget):
def __init__(self, img_location):
super().__init__(self)
# ...
layout = QVBoxLayout(self)
layout.addWidget(self.button)
layout.setContentsMargins(0, 0, 0, 0)
# ...

Related

PyQt5 Example of Using `QSizePolicy` to Shrink a Widget

I am trying to stop a widget from expanding by setting its size policy but things are not working.
The following code runs:
from PyQt5.QtWidgets import*
import pyqtgraph as pg
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.layout = QHBoxLayout()
self.left_widget = pg.GraphicsLayoutWidget()
self.layout.addWidget(self.left_widget)
self.right_widget = RightWidget()
#self.right_widget.groupbox.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
self.layout.addWidget(self.right_widget)
self.widget = QWidget()
self.widget.setLayout(self.layout)
self.setCentralWidget(self.widget)
class RightWidget(QWidget):
def __init__(self):
super().__init__()
self.layout = QVBoxLayout()
self.groupbox = QGroupBox()
self.groupbox.setTitle("some title")
#self.groupbox.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
self.groupboxlayout = QVBoxLayout()
self.button1 = QPushButton ("1")
self.groupboxlayout.addWidget(self.button1)
self.button2 = QPushButton ("2")
self.groupboxlayout.addWidget(self.button2)
self.button3 = QPushButton ("3")
self.groupboxlayout.addWidget(self.button3)
self.groupbox.setLayout(self.groupboxlayout)
self.layout.addWidget(self.groupbox)
self.button4 = QPushButton ("4")
self.layout.addWidget(self.button4)
self.button5 = QPushButton ("5")
self.layout.addWidget(self.button5)
self.setLayout(self.layout)
if __name__ == '__main__':
import sys
system_app = QApplication(sys.argv)
main = MainWindow()
main.show()
system_app.exec()
It gives:
The specific choice of widgets should not matter. The point is that, there is a large widget on the left and there are smaller widgets on the right that is not large enough to fill the column. I want to modify the above code to shrink the widgets on the right hand side. That is:
In words, I want the widgets to shrink to top and bottom of the page in a way taking minimum space (and hence leaving the middle empty).
I attempted to use QSizePolicy to achieve the desired result. The commented lines seem to have no impact on the page at all. I don't know what went wrong.

QPaintEvent event rect for scrollable widget

I have a QPaintEvent override for a custom widget that has a fixed size set. This fixed size can change per instance but in this simple example, ive set it. however the PaintEvent doesn't take it into account so when the users scrolls to the right the rectangle shouldn't paint rounded corners since the widget extends past the visible viewport. How do i fix this?
Full widget painted correctly...
When i resize dialog and scroll right, you'll see rounded corners appear on the left side... when it should NOT.
They should look like this...
Code
import os
import sys
from PySide2 import QtGui, QtWidgets, QtCore, QtSvg
class Card(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Card, self).__init__(parent=parent)
self.label = QtWidgets.QLabel('Help This Paint Event Is Broken')
self.label.setFixedHeight(40)
self.label.setFixedWidth(300)
self.mainLayout = QtWidgets.QVBoxLayout(self)
self.mainLayout.addWidget(self.label)
# overrides
def paintEvent(self, event):
painter = QtGui.QPainter()
painter.begin(self)
painter.setOpacity(1.0)
painter.setRenderHints(QtGui.QPainter.Antialiasing)
painter.setPen(QtGui.QColor(0, 0, 0, 128))
painter.setPen(QtCore.Qt.NoPen)
painter.setBrush(QtGui.QColor('#F44336'))
painter.drawRoundedRect(event.rect(), 12, 12)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.end()
class ListViewExample(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ListViewExample, self).__init__(parent)
self.resize(200,200)
self.listView = QtWidgets.QListWidget()
self.listView.setSpacing(10)
self.listView.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
self.listView.verticalScrollBar().setSingleStep(10)
# layout
self.mainLayout = QtWidgets.QVBoxLayout()
self.mainLayout.setContentsMargins(0,0,0,0)
self.mainLayout.addWidget(self.listView)
self.setLayout(self.mainLayout)
for x in range(50):
wgt = Card()
self.appendItem(wgt)
def appendItem(self, widget):
lwi = QtWidgets.QListWidgetItem()
lwi.setSizeHint(widget.sizeHint())
self.listView.addItem(lwi)
self.listView.setItemWidget(lwi, widget)
################################################################################
# Widgets
################################################################################
def unitTest_CardDelegate():
app = QtWidgets.QApplication(sys.argv)
window = ListViewExample()
window.show()
app.exec_()
if __name__ == '__main__':
pass
unitTest_CardDelegate()
QPaintEvent::rect() returns the visible rectangle, not the rectangle of the widget itself, so you observe this behavior. The solution is:
painter.drawRoundedRect(self.rect(), 12, 12)

Pyqt margin padding setting invalid in parent-children widget [duplicate]

I have set up an image button with some text, but the image does not align with the text due to some extra margins. How can I get rid of these margins? I have tried setting setContentsMargins(0,0,0,0) and setSpacing(0) on various components but it doesn't seem to affect the correct margins.
Here is a demo:
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class ImageButton(QWidget):
def __init__(self, img_location):
QWidget.__init__(self)
self.img_location = img_location
self.button = QToolButton(self)
self.button.clicked.connect(self.handleButton)
self.button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
self.button.setIcon(QIcon(img_location))
self.button.setIconSize(QSize(300,400))
layout = QVBoxLayout(self)
layout.addWidget(self.button)
def handleButton(self):
print(self.img_location)
app = QApplication([])
window = QMainWindow()
window.resize(800,600)
label_title = QLabel("bob asdfjak f ajksf asljf ajdslf aldskj ksf kslfhadjks lfhiu sofhjaklfsiuod fahklfhadisufaksufhdsuifhosa fasdf afsda")
label_title.setStyleSheet('background-color: yellow')
label_title.setAlignment(Qt.AlignCenter)
label_title.adjustSize()
label_title.setWordWrap(True)
imgbtn = ImageButton("a.png")
imgbtn.setStyleSheet('background-color: green')
layout_box = QVBoxLayout()
layout_box.setContentsMargins(0,0,0,0)
layout_box.setSpacing(0)
layout_box.addWidget(imgbtn, 0, Qt.AlignTop)
layout_box.addWidget(label_title, 0, Qt.AlignTop)
layout_box.setAlignment(Qt.AlignCenter)
layout_box.setSpacing(0)
content = QWidget()
content.setStyleSheet('background-color: blue')
content.setFixedWidth(300)
content.setFixedHeight(400)
content.setLayout(layout_box)
window.setCentralWidget(content)
window.show()
app.exec_()
The Yellow region marks the text label, the Green region marks the imagebutton, and the Blue region marks the space I'm trying to get rid of. See how the yellow region expands to the size of the blue, with the end result that the text doesn't align to the imagebutton.
How can I get rid of this blue region?
That margin is that of the QVBoxLayout that you use to place the QToolButton inside ImageButton, so the solution is to set it to 0 that margin:
# ...
class ImageButton(QWidget):
def __init__(self, img_location):
super().__init__(self)
# ...
layout = QVBoxLayout(self)
layout.addWidget(self.button)
layout.setContentsMargins(0, 0, 0, 0)
# ...

How can I show overlapping QWidgets with Pyqt5?

I have a toplevel widget with a layout set and 2 other widgets added to that layout, when I color them all I only see the toplevel widget color but Id like to see the children widgets on top. This is what I have attempted but it just displays a blue QWidget, I am expecting red and green widgets one on top of the other
def set_color(widget, color):
p = widget.palette()
p.setColor(widget.backgroundRole(), color)
widget.setPalette(p)
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget,QVBoxLayout
app = QApplication([])
win = QWidget()
win.show()
win.resize(1920,1080)
vlayout = QVBoxLayout()
win.setLayout(vlayout)
set_color(win, Qt.blue)
mod_group = QWidget()
mod_layout = QHBoxLayout()
mod_group.setLayout(mod_layout)
vlayout.addWidget(mod_group)
set_color(mod_group, Qt.red)
mod_group.show()
audio_group = QWidget()
audio_layout = QHBoxLayout()
vlayout.addWidget(audio_group)
audio_group.setLayout(audio_layout)
set_color(audio_group, Qt.green)
audio_group.show()
The widgets are visible but the background color you use is the same as the parent widget, so that they are applied correctly you must enable the autoFillBackground property:
mod_group.setAutoFillBackground(True)
audio_group.setAutoFillBackground(True)

How to make QTabWidget look transparent?

I want to make a simple GUI desktop application using python.
I've made a simple window with a background image, and I added a tab-widget on the right corner. It worked properly. But the tab-bar and tab contents area are white.
What I want is that the tab-widget's background shows it's parent window's background image (which means it's transparent). But I don't know how to do it.
Here is my working environment, code and screen shot:
Working environment:
Windows 7
Python 3.4
PyQt5 5.5
Source code:
# coding: utf-8
# There are some unnecessary module.
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QTabWidget, QWidget, QLabel, QHBoxLayout, QVBoxLayout, QGridLayout
from PyQt5.QtGui import QPixmap, QPalette, QBrush, QColor
from PyQt5.QtCore import Qt
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
tab1 = QWidget()
tab2 = QWidget()
vbox1 = self.makeTab1()
vbox2 = self.makeTab2()
tab1.setLayout(vbox1)
tab2.setLayout(vbox2)
tabs = QTabWidget()
tabs.addTab(tab1, "firstTab")
tabs.addTab(tab2, "secondTab")
picLabel = QLabel(self)
picFile = 'background_img.jpg'
pixmap = QPixmap(picFile)
palette = QPalette()
palette.setBrush(QPalette.Background, QBrush(pixmap))
hboxEX = QHBoxLayout()
hboxEX.addStretch(2)
hboxEX.addWidget(tabs)
hboxEX.setStretchFactor(tabs, 1)
vboxEX = QVBoxLayout()
vboxEX.addStretch(1)
vboxEX.addLayout(hboxEX)
vboxEX.setStretchFactor(hboxEX, 1)
self.setLayout(vboxEX)
self.setPalette(palette)
self.resize(pixmap.width(), pixmap.height())
self.show()
def makeTab1(self):
lbl1 = QLabel(self)
lbl2 = QLabel(self)
lbl3 = QLabel(self)
lbl1.setText("Google")
lbl2.setText("WikiPedia")
lbl3.setText("StackOverflow")
lbl1.setOpenExternalLinks(True)
lbl2.setOpenExternalLinks(True)
lbl3.setOpenExternalLinks(True)
vbox1 = QVBoxLayout()
vbox1.addWidget(lbl1)
vbox1.addWidget(lbl2)
vbox1.addWidget(lbl3)
return vbox1
def makeTab2(self):
lbl4 = QLabel(self)
lbl5 = QLabel(self)
lbl6 = QLabel(self)
lbl4.setText("Python")
lbl5.setText("CentOS")
lbl6.setText("MariaDB")
lbl4.setOpenExternalLinks(True)
lbl5.setOpenExternalLinks(True)
lbl6.setOpenExternalLinks(True)
vbox2 = QVBoxLayout()
vbox2.addWidget(lbl4)
vbox2.addWidget(lbl5)
vbox2.addWidget(lbl6)
return vbox2
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Screen shot:
What I tried:
I added these codes and it changed the tab's color. But it didn't make the tab area look transparent:
tabPalette = QPalette()
tabPalette.setColor(QPalette.Background, QColor("cyan"))
tab1.setAutoFillBackground(True)
tab1.setPalette(tabPalette)
I think it's a Windows problem. You might want to try to switch your application to a different style.
See this page of PyQt reference http://pyqt.sourceforge.net/Docs/PyQt4/qstyle.html
some sample code:
def changeStyle(self, styleName):
QtGui.QApplication.setStyle(QtGui.QStyleFactory.create(styleName))
self.changePalette()
call it with:
changeStyle("plastique")

Categories

Resources