How to make Qlabel not filling BoxLayout - python

I have QWidget, which contains QVBoxLayout and QLabel. Indeed when I put Qlabel inside QVBoxLayout it fill the QVBoxLayout. How to make QLabel ignore QVBoxLayout.
How to make the red border only around 'Text Label' ?
I've tried using setStyleSheet, setGeometry, but it didn't work. And I think using maximumsize is not the good option.
Thank you

A simple solution is to use QSizePolicy so that instead of expanding, it contracts to the minimum:
from PyQt5 import QtCore, QtWidgets
class Label(QtWidgets.QLabel):
def __init__(self, *args, **kwargs):
super(Label, self).__init__(*args, **kwargs)
self.setAlignment(QtCore.Qt.AlignCenter)
self.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
lbl = Label("TextLabel")
lbl.setStyleSheet('''background: red;''')
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(lbl, alignment=QtCore.Qt.AlignCenter)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())

Try it:
import sys
from PyQt5.QtWidgets import *
class Widget(QWidget):
def __init__(self):
super().__init__()
label = QLabel("TextLabel")
layout = QGridLayout(self)
layout.addWidget(label)
CSS = """
QLabel {
font-family: Ubuntu-Regular;
font-size: 12px;
qproperty-alignment: AlignCenter;
color: blue;
border: 3px solid red;
border-radius: 4px;
min-height: 40px;
max-height: 40px;
min-width: 48px;
max-width: 100px;
background: yellow;
}
"""
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyleSheet(CSS)
ex = Widget()
ex.show()
app.exec_()

Related

Hover Effect for Two or More Widgets at a same time?

How to make a Hover effect for Two or More QLabels at a time? For Example, In my code, I need to hover effect for Lbl1 and Lbl2 at a time. ( Either Mouse enter into a QLabel 1 or QLabel 2, both QLabels will take a Hover Effect)
from PyQt5 import QtWidgets
class Hover_Multiple(QtWidgets.QWidget):
def __init__(self):
super(). __init__()
self.setWindowTitle("Hover Effects")
self.lbl1 = QtWidgets.QLabel("Python")
self.lbl1.setFixedSize(100,50)
self.lbl1.setStyleSheet(mystyle())
self.lbl2 = QtWidgets.QLabel("PyQt5")
self.lbl2.setStyleSheet(mystyle())
self.lbl2.setFixedSize(100,50)
self.hbox = QtWidgets.QHBoxLayout()
self.hbox.addStretch()
self.hbox.addWidget(self.lbl1)
self.hbox.addWidget(self.lbl2)
self.hbox.addStretch()
self.hbox.setSpacing(0)
self.hbox.setContentsMargins(0,0,0,0)
self.setLayout(self.hbox)
def mystyle():
return"""
QLabel
{
background-color:lightgreen;
min-height : 25%; min-width : 40%;
border:0px solid;border-color:red;
text-align:centre ;font-size :10pt; font-family:Trebuchet MS; color:Black; padding : 2px;
}
QLabel::hover
{
background-color: red;
color :white;
}
"""
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
mainwindow = Hover_Multiple()
mainwindow.show()
sys.exit(app.exec_())
A possible solution is to use a qproperty that serves as a flag to change the painting, and that qproperty must be changed in the widgets when some widget is triggered by the QEvent::HoverEnter and QEvent::HoverLeave events and that can be done using an eventfilter.
from PyQt5 import QtCore, QtWidgets
class HoverHelper(QtCore.QObject):
def __init__(self, parent=None):
super().__init__(parent)
self._widgets = []
#property
def widgets(self):
return self._widgets
def add_widget(self, widget):
if not isinstance(widget, QtWidgets.QWidget):
raise TypeError(f"{widget} must be QWidget object")
widget.installEventFilter(self)
widget.setAttribute(QtCore.Qt.WA_Hover)
self.widgets.append(widget)
def eventFilter(self, obj, event):
if obj in self.widgets:
if event.type() == QtCore.QEvent.HoverEnter:
self.change_property(True)
elif event.type() == QtCore.QEvent.HoverLeave:
self.change_property(False)
return super().eventFilter(obj, event)
def change_property(self, hovered):
for widget in self.widgets:
widget.setProperty("hovered", hovered)
widget.style().polish(widget)
class Hover_Multiple(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Hover Effects")
self.setStyleSheet(style_sheet())
self.lbl1 = QtWidgets.QLabel("Python")
self.lbl1.setFixedSize(100, 50)
self.lbl2 = QtWidgets.QLabel("PyQt5")
self.lbl2.setFixedSize(100, 50)
lay = QtWidgets.QHBoxLayout(self)
lay.addStretch()
lay.addWidget(self.lbl1)
lay.addWidget(self.lbl2)
lay.addStretch()
lay.setSpacing(0)
lay.setContentsMargins(0, 0, 0, 0)
helper = HoverHelper(self)
helper.add_widget(self.lbl1)
helper.add_widget(self.lbl2)
def style_sheet():
return """
QLabel{
background-color: lightgreen;
min-height: 25%;
min-width: 40%;
border: 0px solid;
border-color: red;
text-align: center;
font-size: 10pt;
font-family: Trebuchet MS;
color: black;
padding: 2px;
}
QLabel[hovered="true"]{
background-color: red;
color: white;
}
"""
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
mainwindow = Hover_Multiple()
mainwindow.show()
sys.exit(app.exec_())

How to add styles to widgets inside custom Qwidget

I am having a Custom widget that contains a QLabel and a custom label(MessageLabel). I would like to know how I can add css styles to the QLabel inside the custom widget.
Here is my code.
from PyQt5 import QtWidgets, QtCore
import sys
_style = """
#MessageLabel{
background-color: rgba(196, 195, 192, 100);
color: white;
padding: 10px;
border-radius: 5px 5px 30px 5px;
selection-color: black;
selection-background-color: white;
}
#MessageDisplayWidget #InfoLabel{
color: red;
background-color: blue;
}
"""
class MessageLabel(QtWidgets.QLabel):
def __init__(self, *args, **kwargs):
super(MessageLabel, self).__init__(*args, **kwargs)
self.setObjectName("MessageLabel")
font = self.font()
font.setPointSize(12)
self.setFont(font)
self.setMinimumWidth(100)
self.setText("Hello World")
class MessageDisplayWidget(QtWidgets.QWidget):
def __init__(self):
super(MessageDisplayWidget, self).__init__()
self.message_box_frame = QtWidgets.QFrame()
self.vBoxLayout = QtWidgets.QVBoxLayout(self.message_box_frame)
self.vBoxLayout.setSpacing(0)
self.setLayout(self.vBoxLayout)
self.message_lbl_layout = QtWidgets.QVBoxLayout()
self.more_options_layout = QtWidgets.QHBoxLayout()
self.more_options_layout.setContentsMargins(0, 0, 0, 0)
self.vBoxLayout.addLayout(self.message_lbl_layout, 1)
self.vBoxLayout.addLayout(self.more_options_layout, 0)
self.message_text = MessageLabel() # this is a custom label
self.info_label = QtWidgets.QLabel("time") # this is the label I want to change
self.info_label.setObjectName("InfoLabel")
self.info_label.setFixedHeight(30)
self.message_lbl_layout.addWidget(self.message_text)
self.more_options_layout.addWidget(self.info_label)
self.more_options_layout.setStretch(0, 1)
self.more_options_layout.setAlignment(self.info_label, QtCore.Qt.AlignRight)
self.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
win = MessageDisplayWidget()
win.setStyleSheet(_style)
win.show()
sys.exit(app.exec_())
"""
QVboxlayout
|
- QVboxLayout(Message), QVboxLayout(MoreOptions)
| |
MessageLabel InfoLabel
"""
As shown in the above image I would like to add css style to time label

QSlider Handle Size PyQt5 [duplicate]

This question already has an answer here:
How to change QSlider handle width using stylesheet
(1 answer)
Closed 2 years ago.
I'm trying to increase the width of the Qslider handle to make it more user friendly on small screens, but I've only found ways of doing this in C++.
I have tried to implement this in python using the following code, only for it to change the colour of the slider:
self.Zoom.setStyleSheet("""
QSlider::handle:horizontal {
height: 80px;
}
""")
Any advice on how to use QWidget.setStyleSheet() correctly.
A possible solution is to use a QProxyStyle:
from PyQt5 import QtCore, QtWidgets
class SliderProxyStyle(QtWidgets.QProxyStyle):
def pixelMetric(self, metric, option, widget):
if metric == QtWidgets.QStyle.PM_SliderThickness:
return 40
elif metric == QtWidgets.QStyle.PM_SliderLength:
return 40
return super().pixelMetric(metric, option, widget)
class TestWindow(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
style = SliderProxyStyle(self.slider.style())
self.slider.setStyle(style)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.slider)
lay.addStretch()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle("fusion")
w = TestWindow()
w.show()
app.exec_()
Before
After
A possible solution is to use a QSS:
from PyQt5 import QtCore, QtWidgets
class TestWindow(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
self.slider.setMinimumHeight(70)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.slider)
lay.addStretch()
QSS = """
/* QSlider -------------------------------------- */
QSlider::groove:horizontal {
border-radius: 1px;
height: 3px;
margin: 0px;
background-color: rgb(52, 59, 72);
}
QSlider::groove:horizontal:hover {
background-color: rgb(55, 62, 76);
}
QSlider::handle:horizontal {
background-color: rgb(85, 170, 255);
border: none;
height: 40px;
width: 40px;
margin: -20px 0;
border-radius: 20px;
padding: -20px 0px;
}
QSlider::handle:horizontal:hover {
background-color: rgb(155, 180, 255);
}
QSlider::handle:horizontal:pressed {
background-color: rgb(65, 255, 195);
}
"""
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle("fusion")
app.setStyleSheet(QSS)
w = TestWindow()
w.show()
sys.exit(app.exec_())

pyqt4 widget appear outside the layout

I want the effect in the picture. The qlabel is in the layout, and the font is centered. Below is the code I wrote, which is different from what I want. First, qlabel is outside the layout, and second, the font is not centered.
import sys
from PyQt4.QtCore import Qt
from PyQt4.QtGui import QLabel, QApplication, QWidget, QVBoxLayout, QStyleOption, QPainter, QStyle
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
self.setGeometry(100, 100, 500, 500)
vbox = QVBoxLayout()
self.setLayout(vbox)
a = QLabel('aaa')
b = QLabel('bbb')
vbox.addWidget(a)
vbox.addWidget(a, alignment=Qt.AlignHCenter | Qt.AlignTop)
vbox.addWidget(b, alignment=Qt.AlignHCenter | Qt.AlignBottom)
self.setStyleSheet("""
Example{
border-width: 1px;
border-style: solid;
border-color: red;
min-width:500px;
max-width:500px;
min-height:500px;
max-height:500px;
padding:1px 1px 1px 1px;
margin-bottom:30px;
}
QLabel{
min-width:500px;
max-width:500px;
min-height:50px;
max-height:50px;
margin:0px;
padding:0px;
background-color:#cdcdcd;
text-align: center center;
}
""")
self.show()
def paintEvent(self, event):
super(Example, self).paintEvent(event)
opt = QStyleOption()
opt.initFrom(self)
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
self.style().drawPrimitive(QStyle.PE_Widget, opt, painter, self)
def main():
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
The logic of the layouts is to handle the geometry of the elements but you are also handling the geometry with the stylesheet, causing the problem you observe. On the other hand, the QLabel does not have the text-align property but you have to use qproperty-alignment: AlignCenter;.
To avoid this it is better to avoid managing the geometry with stylesheet but with the methods of the class, considering the solution is:
import sys
from PyQt4.QtCore import Qt
from PyQt4.QtGui import (
QLabel,
QApplication,
QWidget,
QVBoxLayout,
QStyleOption,
QPainter,
QStyle,
)
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
self.setGeometry(100, 100, 500, 500)
self.label_a = QLabel("aaa")
self.label_b = QLabel("bbb")
self.label_a.setFixedHeight(50)
self.label_b.setFixedHeight(50)
vbox = QVBoxLayout(self)
vbox.setContentsMargins(1, 1, 1, 1)
vbox.addWidget(self.label_a)
vbox.addWidget(QWidget(), stretch=1)
vbox.addWidget(self.label_b)
self.setFixedSize(500, 500)
self.setStyleSheet(
"""
Example{
border-width: 1px;
border-style: solid;
border-color: red;
padding:1px 1px 1px 1px;
}
QLabel{
margin:0px;
padding:0px;
background-color:#cdcdcd;
qproperty-alignment: AlignCenter;
}
"""
)
def paintEvent(self, event):
super(Example, self).paintEvent(event)
opt = QStyleOption()
opt.initFrom(self)
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
self.style().drawPrimitive(QStyle.PE_Widget, opt, painter, self)
def main():
app = QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()

Changing widget's highlight color in PyQt5

I've figured out how to change the background color of PyQt5 widgets using setStyleSheet() but I cannot find how to change their highlight color. I am 100% sure this option should be available as in tkinter.
from PyQt5.QtWidgets import QWidget, QApplication, QPushButton
import sys
class Example(QWidget):
def __init__(self):
super().__init__()
self.create_widgets()
def create_widgets(self):
b1 = QPushButton(parent=self, text='Button')
color_1 = 'red'
color_2 = 'blue'
b1.setStyleSheet('QWidget {background-color: %s}' % color_1)
#b1.setStyleSheet('QWidget {highlight-color: %s}' % color_2) does not work
b1.resize(150,50)
b1.move(100,100)
self.setGeometry(300,200, 400, 400)
self.show()
if __name__ == '__main__':
app = QApplication([])
ex = Example()
sys.exit(app.exec_())
Any help is greatly appreciated!
To customize QPushButton you can use the following style sheet:
import sys
from PyQt5.QtWidgets import QWidget, QApplication, QPushButton
class Example(QWidget):
def __init__(self):
super().__init__()
self.create_widgets()
def create_widgets(self):
b1 = QPushButton(parent=self, text='Button')
b1.setGeometry(150,150, 100, 100)
style = '''
QWidget {
background-color: coral;
}
QPushButton {
background-color: #006325;
font-size: 20px;
color: white;
min-width: 100px;
max-width: 100px;
min-height: 100px;
max-height: 100px;
border-radius: 50px;
border-width: 1px;
border-color: #ae32a0;
border-style: solid;
}
QPushButton:hover {
background-color: #328930;
color: yellow;
}
QPushButton:pressed {
background-color: #80c342;
color: red;
}
'''
if __name__ == '__main__':
app = QApplication([])
app.setStyleSheet(style) # <---
ex = Example()
ex.setGeometry(300,200, 400, 400)
ex.setWindowTitle("QPushButton - style sheet")
ex.show()
sys.exit(app.exec_())

Categories