I'm trying to put a QProgressBar below a QPushButton and align them on the center of a QVBoxLayout, but for some reason the button stays left aligned when the progress bar is present and center aligned if it is not.
I tried setting the alignment of all parent widgets and layouts to Qt.AlignCenter, but the progress bar keeps making the button go to the left.
connect_box = QVBoxLayout()
connect_box.setAlignment(Qt.AlignCenter)
connect_button = QPushButton('Connect')
connect_button.setFixedSize(120, 30)
connect_progress = QProgressBar()
connect_progress.setRange(0, 10000)
connect_progress.setValue(0)
connect_box.addWidget(connect_button)
connect_box.addWidget(connect_progress)
connect_box.setContentsMargins(0, 20, 0, 0)
I expect the button to stay center aligned when the progress bar is added.
Try it:
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class MyWidget(QWidget):
def __init__(self):
super().__init__()
connect_button = QPushButton('Connect')
connect_button.setFixedSize(120, 30)
connect_progress = QProgressBar()
connect_progress.setRange(0, 10000)
connect_progress.setValue(0)
connect_box = QVBoxLayout(self)
connect_box.setAlignment(Qt.AlignCenter)
connect_box.addWidget(connect_button, alignment=Qt.AlignCenter) # < ----
connect_box.addWidget(connect_progress)
connect_box.setContentsMargins(0, 20, 0, 0)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWidget()
w.show()
sys.exit(app.exec_())
Related
good day, I wonder if someone could tell me why I end up with the following lines around the edge of my GUI.
The skeleton code is below which replicates the problem. I've tried adding stylesheets and QT alignment but to no avail. I think the issue could be with the QScrollArea(). I would love any help as this one has me stumped. Thank you
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.main_window()
def main_window(self):
self.setGeometry(0, 0, 500, 500)
self.grid = QGridLayout()
vbox = QVBoxLayout()
wrapper_widget = QWidget()
wrapper_widget.setLayout(self.grid)
# Bars
scroll = QScrollArea()
scroll.setWidget(wrapper_widget)
master_widget = QWidget()
vbox.addWidget(scroll)
master_widget.setLayout(vbox)
self.setCentralWidget(master_widget)
# Show
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec())
I've a list of rectangle make in this way:
import sys
from PyQt5.QtCore import Qt, QRect, QRectF
from PyQt5.QtGui import *
from PyQt5.QtWidgets import ( QGridLayout, QWidget, QApplication, QGraphicsScene,
QGraphicsView, QGraphicsProxyWidget, QGraphicsRectItem
)
class WidRect(QWidget):
def __init__(self, mIntMeasureId,mStrLabel=None):
super().__init__()
self.aIntMeasureId=mIntMeasureId
self.aStrLabel=mStrLabel
#self.setWidget(QLabel(mStrLabel))
def mousePressEvent(self, QMouseEvent):
if QMouseEvent.button() == Qt.LeftButton:
print("Left Button Clicked on measure "+ str(self.aIntMeasureId))
elif QMouseEvent.button() == Qt.RightButton:
#do what you want here
print("Right Button Clicked on measure "+ str(self.aIntMeasureId))
class MeasureGrid(QWidget):
#grid = None
#scene = None
def __init__(self, geometry, parent=None):
super(MeasureGrid, self).__init__(parent=parent)
#super().onclick.connec(self.click)
self.aLayMeasureGrid = QGridLayout(self)
self.aGsMeasureScene = QGraphicsScene(self)
self.aGsMeasureScene .setSceneRect(geometry.x(), geometry.y(), geometry.width(), geometry.height())
self.aGsMeasureScene .setBackgroundBrush(Qt.white)
self.aGvMeasureView = QGraphicsView()
self.aGvMeasureView.setScene(self.aGsMeasureScene )
self.aLayMeasureGrid.addWidget(self.aGvMeasureView)
for i in range(1,5):
rect = QRectF(100*i, 20, 80, 140)
self.addRect(rect,i)
def addRect(self, mRecMeasureBox,mIntMeasureNum):
#label = QLabel("World")
#label.setAlignment(Qt.AlignCenter | Qt.AlignCenter)
wrRectBox = WidRect(mIntMeasureNum,"Meas #" + str(mIntMeasureNum))
### CREA IL PROXY ###
gpqProxMeasure = QGraphicsProxyWidget()
gpqProxMeasure.setWidget(wrRectBox)
gpqProxMeasure.setGeometry(mRecMeasureBox)
self.aGsMeasureScene.addItem(gpqProxMeasure)
### CREA L'OGGETTO GENITORE ###
griMeasure = QGraphicsRectItem(mRecMeasureBox)
#rectangle.setFlag(QGraphicsItem.ItemIsMovable, True)
self.aGsMeasureScene.addItem(griMeasure)
gpqProxMeasure.setParentItem(griMeasure)
if __name__ == "__main__":
app = QApplication(sys.argv)
mgMeasureList = MeasureGrid(QRect(10, 10, 550, 280))
mgMeasureList.show()
app.exec_()
I would like to add:
a text into every rectangle
an icon into every rectangle
change the icon with another if I click with right button.
I try to add a QLabel but I cannot add a widget to a widget.
Can you tell me where is my error?
I create the rectangle using a proxy object because in the final version of the application they will be from 100 to 300 objects.
I have a QPushButton that has a QIcon set. I would like to grayscale the icon's colors until it is hovered over or selected, without writing 2 separate image files for each icon. If use QPushButton.setDisabled(True) the icon's colors do in fact turn to grayscale, so I would like this same behavior being controlled through a enterEvent. Is this at all possible?
Yes, you can do exactly what you described. Enable the button in the enterEvent and disable it in the leaveEvent if it's not checked.
import sys
from PySide2.QtWidgets import *
from PySide2.QtCore import *
from PySide2.QtGui import *
class Button(QPushButton):
def __init__(self):
super().__init__()
self.setCheckable(True)
self.setDisabled(True)
self.setIcon(QIcon('icon.png'))
self.setIconSize(QSize(100, 100))
def enterEvent(self, event):
self.setEnabled(True)
def leaveEvent(self, event):
if not self.isChecked():
self.setDisabled(True)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = QWidget()
grid = QGridLayout(w)
grid.addWidget(Button(), 0, 0, Qt.AlignCenter)
w.show()
sys.exit(app.exec_())
I used a green check mark for the icon image. Result:
You also don't need to subclass QPushButton, this will work too.
btn = QPushButton()
btn.setCheckable(True)
btn.setIcon(QIcon('icon.png'))
btn.setIconSize(QSize(100, 100))
btn.setDisabled(True)
btn.enterEvent = lambda _: btn.setEnabled(True)
btn.leaveEvent = lambda _: btn.setEnabled(btn.isChecked())
I've seen a number of replies on SO regarding this matter but not specifically to QMenu and QToolButton. Would appreciate some pointers on aligning the popup widget to the right side of the button. Here's a basic code I'm working off..
import sys
from PyQt5.QtWidgets import *
class test(QWidget):
def __init__(self):
super().__init__()
self.resize(200, 100)
layout = QHBoxLayout(self)
label = QLabel('Testing QToolButton Popup')
toolbutton = QToolButton()
toolbutton.setPopupMode(QToolButton.InstantPopup)
widget = QWidget()
widgetLayout = QHBoxLayout(widget)
widgetLabel = QLabel('Popup Text')
widgetSpinbox = QSpinBox()
widgetLayout.addWidget(widgetLabel)
widgetLayout.addWidget(widgetSpinbox)
widgetAction = QWidgetAction(toolbutton)
widgetAction.setDefaultWidget(widget)
widgetMenu = QMenu(toolbutton)
widgetMenu.addAction(widgetAction)
toolbutton.setMenu(widgetMenu)
layout.addWidget(label)
layout.addWidget(toolbutton)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = test()
win.show()
sys.exit(app.exec_())
The outcome looks like this:
The Qt developer thought the default position was correct, so if you want to modify the alignment you must move the QMenu as I show below:
import sys
from PyQt5.QtCore import QPoint
from PyQt5.QtWidgets import (
QApplication,
QHBoxLayout,
QLabel,
QMenu,
QSpinBox,
QToolButton,
QWidgetAction,
QWidget,
)
class Menu(QMenu):
def showEvent(self, event):
if self.isVisible():
button = self.parentWidget()
if button is not None:
pos = button.mapToGlobal(button.rect().bottomRight())
self.move(pos - self.rect().topRight())
super().showEvent(event)
class Test(QWidget):
def __init__(self):
super().__init__()
self.resize(200, 100)
layout = QHBoxLayout(self)
label = QLabel("Testing QToolButton Popup")
toolbutton = QToolButton(popupMode=QToolButton.InstantPopup)
widgetLabel = QLabel("Popup Text")
widgetSpinbox = QSpinBox()
widget = QWidget()
widgetLayout = QHBoxLayout(widget)
widgetLayout.addWidget(widgetLabel)
widgetLayout.addWidget(widgetSpinbox)
widgetAction = QWidgetAction(toolbutton)
widgetAction.setDefaultWidget(widget)
widgetMenu = Menu(toolbutton)
widgetMenu.addAction(widgetAction)
toolbutton.setMenu(widgetMenu)
layout.addWidget(label)
layout.addWidget(toolbutton)
if __name__ == "__main__":
app = QApplication(sys.argv)
win = Test()
win.show()
sys.exit(app.exec_())
I am trying to make a QLabel appear over a QGridLayout, but I cannot figure how to do it.
This is a sample code:
from PyQt5.QtWidgets import QWidget, QApplication, QGridLayout, QFrame, QLabel
import sys
class Foo(QWidget):
def __init__(self):
super().__init__()
grid_layout = QGridLayout()
rect1 = QLabel('RECT1')
rect1.setStyleSheet("color: green;")
grid_layout.addWidget(rect1, 0, 1)
rect2 = QLabel('RECT2')
rect2.setStyleSheet("color: blue;")
grid_layout.addWidget(rect2, 0, 2)
self.setLayout(grid_layout)
self.show()
app = QApplication(sys.argv)
foo = Foo()
sys.exit(app.exec_())
which produces the following output:
For instance, I want to create another QLabel in red, and display it over them, in the center of the image:
red_label = QLabel('red')
red_labe.setStyleSheet("font-size:20pt; color: red;");
Something like this:
How can I achieve that?
A possible solution is to make red_label son of the QWidget for it you must pass the self parameter when the object is created. In addition to this the QLabel must change size when the window does, emulating the layout task for it will create a signal that will be emited in the resizeEvent event:
import sys
from PyQt5 import QtCore, QtWidgets
class Foo(QtWidgets.QWidget):
sizeChanged = QtCore.pyqtSignal(QtCore.QSize)
def __init__(self):
super().__init__()
grid_layout = QtWidgets.QGridLayout(self)
rect1 = QtWidgets.QLabel("RECT1")
rect1.setStyleSheet("color: green;")
grid_layout.addWidget(rect1, 0, 1)
rect2 = QtWidgets.QLabel("RECT2")
rect2.setStyleSheet("color: blue;")
grid_layout.addWidget(rect2, 0, 2)
red_label = QtWidgets.QLabel("red", self)
red_label.setAlignment(QtCore.Qt.AlignCenter)
red_label.setStyleSheet("font-size: 20pt; color: red;")
self.sizeChanged.connect(red_label.resize)
def resizeEvent(self, event):
self.sizeChanged.emit(event.size())
super().resizeEvent(event)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
foo = Foo()
foo.show()
sys.exit(app.exec_())
This may be a little less elegant of a solution, but it does keep the red labeled centered as the window is resized.
class Foo(QWidget):
def __init__(self):
super().__init__()
grid_layout = QGridLayout()
rect1 = QLabel('RECT1')
rect1.setStyleSheet("color: green;")
grid_layout.addWidget(rect1, 0, 0)
rect2 = QLabel('RECT2')
rect2.setStyleSheet("color: blue;")
grid_layout.addWidget(rect2, 0, 2)
grid_layout_two = QGridLayout()
blank_label = QLabel()
red_label = QLabel('red')
red_label.setStyleSheet("font-size:20pt; color: red;")
grid_layout_two.addWidget(blank_label, 0, 0)
grid_layout_two.addWidget(red_label, 0, 1)
grid_layout_two.addWidget(blank_label, 0, 2)
grid_layout_three = QGridLayout()
grid_layout_three.addItem(grid_layout, 0, 0)
grid_layout_three.addItem(grid_layout_two, 0, 0)
self.setLayout(grid_layout_three)
self.show()
app = QApplication(sys.argv)
foo = Foo()
sys.exit(app.exec_())
Basically making three grid layouts, positioning the elements so that the red label is in the center of the other two labels but in a grid layout that is in front of the other labels layout.