pyqt: How to let the QLabel occupy the whole window - python

I put three label in a window, however, the three labels only occupy small part of the window. Here is my code:
from PyQt5.QtWidgets import *
import sys
class ThreeDMPRWindow(QMainWindow):
def __init__(self, image=None):
super(ThreeDMPRWindow, self).__init__()
self.resize(800, 600)
widget = QWidget()
self.setCentralWidget(widget)
layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
widget.setLayout(layout)
allLayout = QHBoxLayout()
layout1 = QVBoxLayout()
label1 = QLabel('label 1')
label1.setStyleSheet("background: rgb(255,0,0)")
layout1.addWidget(label1)
layout2 = QVBoxLayout()
label2 = QLabel('label 2')
label2.setStyleSheet("background: rgb(255,0,0)")
layout2.addWidget(label2)
layout3 = QVBoxLayout()
label3 = QLabel('label 3')
label3.setStyleSheet("background: rgb(255,0,0)")
layout3.addWidget(label3)
qlayout = QGridLayout()
qlayout.addLayout(layout1, 0, 0, 2, 1)
qlayout.addLayout(layout2, 0, 1, 1, 1)
qlayout.addLayout(layout3, 1, 1, 1, 1)
allLayout.addLayout(qlayout)
allLayout.addLayout(QVBoxLayout())
layout.addLayout(allLayout)
app = QApplication(sys.argv)
window = ThreeDMPRWindow()
window.show()
app.exec_()
If we annotate the code: allLayout.addLayout(QVBoxLayout()), the three labels would occupy the whole window. I don't know why this code makes such difference. But I can't remove the code allLayout.addLayout(QVBoxLayout()), because I need the new layout for some other widgets.

If you want to have a space where you can add other widgets then you must use QWidget instead of QVBoxLayout, and in that QWidget add the QVBoxLayout:
# ...
allLayout.addLayout(qlayout)
empty_widget = QWidget()
empty_widget.setContentsMargins(0, 0, 0, 0)
lay = QVBoxLayout(empty_widget)
allLayout.addWidget(empty_widget)
layout.addLayout(allLayout)
# ...
Output:

Related

PQYT Make QGridLayout scrollable

I was wondering if it is possible to add a QScrollArea to a QGridLayout? Below is my attempt however, it always fails with the error.
TypeError: setWidget(self, QWidget): argument 1 has unexpected type 'QGridLayout'
Is this method only possible for combo and list boxes? I am basically passing QPixmap images into a QGridLayout which needs to be scrolled. Any help much appreciated thank you.
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class PicClip(QWidget):
def __init__(self):
super().__init__()
# Load image
self.im = QPixmap("1.jpg")
self.im1 = QPixmap("1.jpg")
# Label 1
self.label = QLabel()
self.label.setPixmap(self.im)
# Label 2
self.label1 = QLabel()
self.label1.setPixmap(self.im1)
# Make Grid
self.grid = QGridLayout()
# Create widgets to grid
self.grid.addWidget(self.label, 0, 1, alignment=Qt.AlignCenter)
self.grid.addWidget(self.label1, 1, 1, alignment=Qt.AlignCenter)
# Set layout of Grid
self.setLayout(self.grid)
# Scroll
scroll = QScrollArea()
scroll.setWidget(self.grid)
scroll.setWidgetResizable(True)
# Show
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = PicClip()
sys.exit(app.exec_())
self.grid is layout and you are trying to add layout using setWidget function. setWidget function only gets QWidget
simple trick is to add wrapper QWidget and set self.grid as its layout
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class PicClip(QMainWindow): # I modified this line to show window properly
def __init__(self):
super().__init__()
# Load image
self.im = QPixmap("1.jpg")
self.im1 = QPixmap("1.jpg")
# Label 1
self.label = QLabel()
self.label.setPixmap(self.im)
# Label 2
self.label1 = QLabel()
self.label1.setPixmap(self.im1)
# Make Grid
self.grid = QGridLayout()
# Create widgets to grid
self.grid.addWidget(self.label, 0, 1, alignment=Qt.AlignCenter)
self.grid.addWidget(self.label1, 1, 1, alignment=Qt.AlignCenter)
# Set layout of Grid
self.setLayout(self.grid)
# Scroll
scroll = QScrollArea()
# add wrapper widget and set its layout
wrapper_widget = QWidget()
wrapper_widget.setLayout(self.grid)
scroll.setWidget(wrapper_widget)
scroll.setWidgetResizable(True)
# Show
self.setCentralWidget(scroll) # I modified this line to show window properly
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = PicClip()
sys.exit(app.exec_())

How to modify/clear/delete a QWidget from a QGridLayout ? - Python, PyQt

I wish to have a QGridLayout containing some informations that can be dynamicaaly changed. However, as it is, it will only superimpose the different informations on top of the previous one instead of replacing it. Surprisingly I couldn't find a method to remove or clean or such a widget from a grid. So what, can't it be dynamically changed ?...
Here is an example of code :
import sys
from PyQt5.QtWidgets import (
QApplication,
QGridLayout,
QPushButton,
QWidget,
QLabel
)
class Window(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("QGridLayout Example")
# Create a QGridLayout instance
self.buttonA = QPushButton("A")
self.buttonB = QPushButton("B")
self.layout = QGridLayout()
# Add widgets to the layout
self.layout.addWidget(self.buttonA, 0, 1)
self.layout.addWidget(self.buttonB, 0, 2)
self.layout.addWidget(QPushButton("C"), 1, 0)
self.layout.addWidget(QPushButton("D"), 1, 1)
self.layout.addWidget(QPushButton("E"), 1, 2)
self.layout.addWidget(QPushButton("F"), 2, 0)
self.layout.addWidget(QPushButton("G"), 2, 1)
self.layout.addWidget(QPushButton("H"), 2, 2)
# Set the layout on the application's window
self.setLayout(self.layout)
self.buttonA.clicked.connect(self.change_label)
self.buttonB.clicked.connect(self.change_label2)
def change_label(self):
self.label = QLabel("Hello")
self.layout.addWidget(self.label, 0, 0)
def change_label2(self):
self.label = QLabel("Bonjour")
self.layout.addWidget(self.label, 0, 0)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
When one clicks on button A, I want to have displayed in box (0,0) "Hello". Then if one clicks on button B, I want to replace the text "Hello" with "Bonjour". However I can only have one text on top of the other which is obviously hardly readable then.
Can someone help me ?
Just use this code:
import sys
from PyQt5.QtWidgets import (
QApplication,
QGridLayout,
QPushButton,
QWidget,
QLabel
)
class Window(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("QGridLayout Example")
# Create a QGridLayout instance
self.label = QLabel("Show text here")
self.buttonA = QPushButton("A")
self.buttonB = QPushButton("B")
self.layout = QGridLayout()
# Add widgets to the layout
self.layout.addWidget(self.label, 0, 0)
self.layout.addWidget(self.buttonA, 0, 1)
self.layout.addWidget(self.buttonB, 0, 2)
self.layout.addWidget(QPushButton("C"), 1, 0)
self.layout.addWidget(QPushButton("D"), 1, 1)
self.layout.addWidget(QPushButton("E"), 1, 2)
self.layout.addWidget(QPushButton("F"), 2, 0)
self.layout.addWidget(QPushButton("G"), 2, 1)
self.layout.addWidget(QPushButton("H"), 2, 2)
# Set the layout on the application's window
self.setLayout(self.layout)
self.buttonA.clicked.connect(self.change_label)
self.buttonB.clicked.connect(self.change_label2)
def change_label(self):
self.label.setText("Hello")
def change_label2(self):
self.label.setText("Bonjour")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())

How to create checkable ability to Qpushbuttons like QRadioButtons in pyqt5

How to add checkable ability to buttons when clicking on one of them had the checked mode and the other buttons are unchecked.
That is, one button can be checked at a time.
from PyQt5.QtWidgets import *
import sys
class Window(QWidget):
def __init__(self):
QWidget.__init__(self)
layout = QGridLayout()
self.setLayout(layout)
btn1 = QPushButton()
btn1.setChecked(True)
btn1.setStyleSheet("background-color: rgba(255, 0, 0, 0.61);")
layout.addWidget(btn1, 0, 0)
btn2 = QPushButton()
btn2.setStyleSheet("background-color: rgb(0, 255, 34);")
layout.addWidget(btn2, 0, 1)
btn3 = QPushButton()
btn3.setStyleSheet("background-color: rgb(49, 49, 49);")
layout.addWidget(btn3, 0, 2)
app = QApplication(sys.argv)
screen = Window()
screen.show()
sys.exit(app.exec_())

how to let the layout showed in the bottom

The window would have two layouts: A, the main layout to show some images; B, the qlabel to show some status. When the window is started, A would be empty. A would show some images after some operations.
My question is: how to let B show in the bottom? The current code is:
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class TimeLine(QMainWindow):
def __init__(self):
super(TimeLine, self).__init__()
widget = QWidget()
self.setCentralWidget(widget)
layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
widget.setLayout(layout)
statusLabel = QLabel('status bar')
statusLabel.setStyleSheet("background-color:blue")
statusLabel.setMaximumHeight(20)
layout.addWidget(statusLabel)
layout.setSpacing(0)
app = QApplication(sys.argv)
window = TimeLine()
window.show()
app.exec_()
And the result is:
The blue label shows in the middle, and I want it to be show in the bottom.
Then, I add a stretch. The layout B would show in the bottom, however, the layout A would also be squeezed. The code is:
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class TimeLine(QMainWindow):
def __init__(self):
super(TimeLine, self).__init__()
widget = QWidget()
self.setCentralWidget(widget)
layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
widget.setLayout(layout)
mainLabel = QLabel()
mainLabel.setStyleSheet("background-color:yellow")
statusLabel = QLabel()
statusLabel.setStyleSheet("background-color:blue")
statusLabel.setMaximumHeight(20)
layout.addWidget(mainLabel)
layout.addStretch()
layout.addWidget(statusLabel)
layout.setSpacing(0)
app = QApplication(sys.argv)
window = TimeLine()
window.show()
app.exec_()
And the result is:
The yellow label is the main label, the gray color represents the back ground. I want the yellow label to occupy all the window except from the blue label.
Thus, what I want is:
when there is no other label, I hope the blue label show in the bottom, like:
where there is another label (yellow label), I hope the yellow label occupy all the space except from the blue label, like:
I saw your task like this:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class TimeLine(QMainWindow):
def __init__(self):
super(TimeLine, self).__init__()
widget = QWidget()
self.setCentralWidget(widget)
mainLabel = QLabel("This is a label.", alignment = Qt.AlignCenter)
mainLabel.setStyleSheet("background-color:yellow")
layout = QVBoxLayout(widget)
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(mainLabel)
self.statusBar().setStyleSheet("background-color:blue; color: #fff")
self.statusBar().showMessage('Hello {} !'.format('status bar'))
if __name__ == "__main__":
app = QApplication(sys.argv)
window = TimeLine()
window.show()
sys.exit(app.exec_())
If I understand your question correctly, you want the blue label to be aligned with the bottom edge of the main window at all times. One way to get what you want to to set the alignment of the label to Qt.AlignBottom when adding it to the layout. You also need to adjust the stretch factors of the two labels to make sure the yellow label takes up all the space above the blue label when it's present, i.e.
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys
class TimeLine(QMainWindow):
def __init__(self):
super(TimeLine, self).__init__()
widget = QWidget()
self.setCentralWidget(widget)
layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
widget.setLayout(layout)
mainLabel = QLabel()
mainLabel.setStyleSheet("background-color:yellow")
statusLabel = QLabel('status bar')
statusLabel.setStyleSheet("background-color:blue")
statusLabel.setMaximumHeight(20)
layout.addWidget(mainLabel, stretch = 1)
layout.addWidget(statusLabel, stretch = 0, alignment = Qt.AlignBottom)
layout.setSpacing(0)
app = QApplication(sys.argv)
window = TimeLine()
window.show()
app.exec_()
Both labels:
Blue label only:

Why does one of my QtWidgets not appear?

My GLWidget (inherited from QtOpenGL.QGLWidget) does not appear on screen, while it should be visible at the right of the other widgets. However, when I switch from an horizontal layout:
layout_final = Qtgui.QHBoxLayout()
to a vertical one:
layout_final = Qtgui.QVBoxLayout()
my GL widget does appear under the other widgets, but I want it to be on the right of the other widgets.
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
# create layout
layout_before_final = QtGui.QVBoxLayout()
layout_final = QtGui.QHBoxLayout()
layout = QtGui.QGridLayout()
layout1 = QtGui.QGridLayout()
self.groupBox = QtGui.QGroupBox('Set HDF5 file')
self.groupBox1 = QtGui.QGroupBox('Current HDF5 file')
# instance widgets
# first box
self.setH5Button = QtGui.QPushButton('set H5')
self.currentH5LineEdit = QtGui.QLineEdit('')
layout.addWidget(self.setH5Button, 0,0)
layout.addWidget(self.currentH5LineEdit, 0, 1)
self.groupBox.setLayout(layout)
# second box
self.channelsLabel = QtGui.QLabel('Channel')
self.channelsComboBox = QtGui.QComboBox()
self.levelsLabel = QtGui.QLabel('Level')
self.levelsComboBox = QtGui.QComboBox()
layout1.addWidget(self.channelsLabel, 0, 0, 1, 1)
layout1.addWidget(self.channelsComboBox, 0, 1, 1, 1)
layout1.addWidget(self.levelsLabel, 1, 0, 1, 1)
layout1.addWidget(self.levelsComboBox, 1, 1, 1, 1)
self.groupBox1.setLayout(layout1)
# create QWidget to gather the two previous boxes
self.widget = QtGui.QWidget()
layout_before_final.addWidget(self.groupBox)
layout_before_final.addWidget(self.groupBox1)
self.widget.setLayout(layout_before_final)
# GL widget
self.widgetGL = MyWidget()
# create a final widget to add the GL widget
self.finalWidget = QtGui.QWidget()
layout_final.addWidget(self.widgetGL)
layout_final.addWidget(self.widget)
self.finalWidget.setLayout(layout_final)
self.setCentralWidget(self.finalWidget)
self.setWindowTitle('PyPractis')
self.resize(640, 480)
def main():
import sys
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I'm not sure why it's happening, but it appears to be caused by the GL widget preferentially collapsing horizontally (giving up it's space to the other elements). You can easily override this behaviour however, by specifying the stretch priority when adding the element:
layout_final.addWidget(self.widgetGL, stretch=1)
This results in the following layout:

Categories