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:
Related
I am trying to create a scroll area with a vertical layout using pyqt5, and I am putting inside some labels. I know that even if it is a vertical layout it is supposed to scroll horizontally if the text does not fit. But no matter what I try it does not let me scroll.
This is the code I am using:
class window(QMainWindow):
def __init__(self):
super(window, self).__init__()
self.setGeometry(300, 300, 803, 520)
self.init_ui()
def init_ui(self):
self.teacher_box = QScrollArea(self)
self.teacher_box.setGeometry(360, 10, 420, 181)
self.teacher_box.setWidgetResizable(True)
self.teacher_box.setObjectName("teacher_box")
self.teacher_box_widget = QWidget()
self.teacher_box_widget.setGeometry(QtCore.QRect(0, 0, 420, 181))
self.teacher_box_widget.setObjectName("teacher_box_widget")
self.verticalLayout = QVBoxLayout(self.teacher_box_widget)
self.verticalLayout.setObjectName("verticalLayout")
self.teacher_box.setWidget(self.teacher_box_widget)
self.teacher_label = QtWidgets.QLabel(self.teacher_box_widget)
self.teacher_label.setText("This is a new text label that i created using pyqt5's qscrollarea and now the label is going to get outside the boundaries")
self.teacher_label.adjustSize()
self.teacher_label.move(10, 10)
if __name__ == "__main__":
app = QApplication(sys.argv)
win = window()
win.show()
sys.exit(app.exec_())
Here is how it should look:
Here is how it looks:
I hope my question is clear
Since many questions wonder how to use a QScrollArea that many widgets have, I will take the license to explain the various forms in detail and use them as a canonical answer for future readers.
QScrollArea only allows placing a container widget so the other widgets must be placed as children of the container widget.
And to place the widgets as children of another there are 2 possibilities:
1. Use a QLayout:
QLayouts allow you to automate the geometry of the widgets based on the QSizePolicy, strecth, sizeHint, etc. So in that case it's simple: Just set the widgetResizable property to True.
import sys
from PyQt5 import QtWidgets
class Window(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
scroll_area = QtWidgets.QScrollArea(central_widget)
scroll_area.setGeometry(360, 10, 420, 180)
scroll_area.setWidgetResizable(True)
container = QtWidgets.QWidget()
scroll_area.setWidget(container)
# Set widgets via layout
lay = QtWidgets.QVBoxLayout(container)
lay.setContentsMargins(10, 10, 0, 0)
for letter in "ABCDE":
text = letter * 100
label = QtWidgets.QLabel(text)
lay.addWidget(label)
lay.addStretch()
self.setGeometry(300, 300, 803, 520)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())
2. Set the widgets directly without layouts:
In this case you must calculate the minimum geometry that contains the internal widgets and set the size in the container, also you must set the widgetResizable property to False:
import sys
from PyQt5 import QtCore, QtWidgets
class Window(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
scroll_area = QtWidgets.QScrollArea(central_widget)
scroll_area.setGeometry(360, 10, 420, 180)
scroll_area.setWidgetResizable(False)
container = QtWidgets.QWidget()
scroll_area.setWidget(container)
# calculate geometry
geometry = QtCore.QRect(10, 10, 0, 0)
for letter in "ABCDE":
text = letter * 100
label = QtWidgets.QLabel(text, container)
label.adjustSize()
label.move(geometry.bottomLeft())
geometry |= label.geometry()
geometry.setTopLeft(QtCore.QPoint(0, 0))
container.resize(geometry.size())
self.setGeometry(300, 300, 803, 520)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())
I am trying to create a scroll area with a vertical layout using pyqt5, and I am putting inside some labels. I know that even if it is a vertical layout it is supposed to scroll horizontally if the text does not fit. But no matter what I try it does not let me scroll.
This is the code I am using:
class window(QMainWindow):
def __init__(self):
super(window, self).__init__()
self.setGeometry(300, 300, 803, 520)
self.init_ui()
def init_ui(self):
self.teacher_box = QScrollArea(self)
self.teacher_box.setGeometry(360, 10, 420, 181)
self.teacher_box.setWidgetResizable(True)
self.teacher_box.setObjectName("teacher_box")
self.teacher_box_widget = QWidget()
self.teacher_box_widget.setGeometry(QtCore.QRect(0, 0, 420, 181))
self.teacher_box_widget.setObjectName("teacher_box_widget")
self.verticalLayout = QVBoxLayout(self.teacher_box_widget)
self.verticalLayout.setObjectName("verticalLayout")
self.teacher_box.setWidget(self.teacher_box_widget)
self.teacher_label = QtWidgets.QLabel(self.teacher_box_widget)
self.teacher_label.setText("This is a new text label that i created using pyqt5's qscrollarea and now the label is going to get outside the boundaries")
self.teacher_label.adjustSize()
self.teacher_label.move(10, 10)
if __name__ == "__main__":
app = QApplication(sys.argv)
win = window()
win.show()
sys.exit(app.exec_())
Here is how it should look:
Here is how it looks:
I hope my question is clear
Since many questions wonder how to use a QScrollArea that many widgets have, I will take the license to explain the various forms in detail and use them as a canonical answer for future readers.
QScrollArea only allows placing a container widget so the other widgets must be placed as children of the container widget.
And to place the widgets as children of another there are 2 possibilities:
1. Use a QLayout:
QLayouts allow you to automate the geometry of the widgets based on the QSizePolicy, strecth, sizeHint, etc. So in that case it's simple: Just set the widgetResizable property to True.
import sys
from PyQt5 import QtWidgets
class Window(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
scroll_area = QtWidgets.QScrollArea(central_widget)
scroll_area.setGeometry(360, 10, 420, 180)
scroll_area.setWidgetResizable(True)
container = QtWidgets.QWidget()
scroll_area.setWidget(container)
# Set widgets via layout
lay = QtWidgets.QVBoxLayout(container)
lay.setContentsMargins(10, 10, 0, 0)
for letter in "ABCDE":
text = letter * 100
label = QtWidgets.QLabel(text)
lay.addWidget(label)
lay.addStretch()
self.setGeometry(300, 300, 803, 520)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())
2. Set the widgets directly without layouts:
In this case you must calculate the minimum geometry that contains the internal widgets and set the size in the container, also you must set the widgetResizable property to False:
import sys
from PyQt5 import QtCore, QtWidgets
class Window(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
scroll_area = QtWidgets.QScrollArea(central_widget)
scroll_area.setGeometry(360, 10, 420, 180)
scroll_area.setWidgetResizable(False)
container = QtWidgets.QWidget()
scroll_area.setWidget(container)
# calculate geometry
geometry = QtCore.QRect(10, 10, 0, 0)
for letter in "ABCDE":
text = letter * 100
label = QtWidgets.QLabel(text, container)
label.adjustSize()
label.move(geometry.bottomLeft())
geometry |= label.geometry()
geometry.setTopLeft(QtCore.QPoint(0, 0))
container.resize(geometry.size())
self.setGeometry(300, 300, 803, 520)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())
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_())
I am trying to create a scroll area with a vertical layout using pyqt5, and I am putting inside some labels. I know that even if it is a vertical layout it is supposed to scroll horizontally if the text does not fit. But no matter what I try it does not let me scroll.
This is the code I am using:
class window(QMainWindow):
def __init__(self):
super(window, self).__init__()
self.setGeometry(300, 300, 803, 520)
self.init_ui()
def init_ui(self):
self.teacher_box = QScrollArea(self)
self.teacher_box.setGeometry(360, 10, 420, 181)
self.teacher_box.setWidgetResizable(True)
self.teacher_box.setObjectName("teacher_box")
self.teacher_box_widget = QWidget()
self.teacher_box_widget.setGeometry(QtCore.QRect(0, 0, 420, 181))
self.teacher_box_widget.setObjectName("teacher_box_widget")
self.verticalLayout = QVBoxLayout(self.teacher_box_widget)
self.verticalLayout.setObjectName("verticalLayout")
self.teacher_box.setWidget(self.teacher_box_widget)
self.teacher_label = QtWidgets.QLabel(self.teacher_box_widget)
self.teacher_label.setText("This is a new text label that i created using pyqt5's qscrollarea and now the label is going to get outside the boundaries")
self.teacher_label.adjustSize()
self.teacher_label.move(10, 10)
if __name__ == "__main__":
app = QApplication(sys.argv)
win = window()
win.show()
sys.exit(app.exec_())
Here is how it should look:
Here is how it looks:
I hope my question is clear
Since many questions wonder how to use a QScrollArea that many widgets have, I will take the license to explain the various forms in detail and use them as a canonical answer for future readers.
QScrollArea only allows placing a container widget so the other widgets must be placed as children of the container widget.
And to place the widgets as children of another there are 2 possibilities:
1. Use a QLayout:
QLayouts allow you to automate the geometry of the widgets based on the QSizePolicy, strecth, sizeHint, etc. So in that case it's simple: Just set the widgetResizable property to True.
import sys
from PyQt5 import QtWidgets
class Window(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
scroll_area = QtWidgets.QScrollArea(central_widget)
scroll_area.setGeometry(360, 10, 420, 180)
scroll_area.setWidgetResizable(True)
container = QtWidgets.QWidget()
scroll_area.setWidget(container)
# Set widgets via layout
lay = QtWidgets.QVBoxLayout(container)
lay.setContentsMargins(10, 10, 0, 0)
for letter in "ABCDE":
text = letter * 100
label = QtWidgets.QLabel(text)
lay.addWidget(label)
lay.addStretch()
self.setGeometry(300, 300, 803, 520)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())
2. Set the widgets directly without layouts:
In this case you must calculate the minimum geometry that contains the internal widgets and set the size in the container, also you must set the widgetResizable property to False:
import sys
from PyQt5 import QtCore, QtWidgets
class Window(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
scroll_area = QtWidgets.QScrollArea(central_widget)
scroll_area.setGeometry(360, 10, 420, 180)
scroll_area.setWidgetResizable(False)
container = QtWidgets.QWidget()
scroll_area.setWidget(container)
# calculate geometry
geometry = QtCore.QRect(10, 10, 0, 0)
for letter in "ABCDE":
text = letter * 100
label = QtWidgets.QLabel(text, container)
label.adjustSize()
label.move(geometry.bottomLeft())
geometry |= label.geometry()
geometry.setTopLeft(QtCore.QPoint(0, 0))
container.resize(geometry.size())
self.setGeometry(300, 300, 803, 520)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())
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: