Aligning QGridLayout rows in QScrollArea - python-3.x

I am trying to create a lot of rows in a PyQt5 grid widget, but they try to expand as much as they can. How can I set a fixed cell height? They are represented like this:
But I would like them to stick at the top, ordered like this:
Code:
name = QtWidgets.QLabel()
name.setText(str(ui.nombre.toPlainText()) + "({}, {}, {})".format(do, cota, alejamiento))
borrar = QtWidgets.QPushButton()
borrar.setText("X")
borrar.clicked.connect(self.borrar)
ui.elementos.addWidget(name, self.num_elementos, 0, 1, 1)
ui.elementos.addWidget(borrar, self.num_elementos, 1, 1, 1)
self.num_elementos += 1
self.update()
print(self.puntos)
And the elementos widget is created in other class:
self.scroll = QtWidgets.QScrollArea(self.gridLayoutWidget_2)
self.scroll_widget = QtWidgets.QWidget()
self.scroll_widget.resize(200, 700)
self.elementos = QtWidgets.QGridLayout()
self.scroll_widget.setLayout(self.elementos)
self.scroll.setWidget(self.scroll_widget)
self.Punto.addWidget(self.scroll, 4, 0, 1, 3)

You need to add a stretchable space beneath the rows of widgets, so that it pushes them all up to the top. One way to do this is to put another widget inside the scroll-widget, and then use a vertical layout to add the spacer. It will also help if you make the scroll-widget resizable, otherwise the rows will start to get squashed if too many are added.
Below is a demo that implements all that. Hopefully it should be clear how you can adapt this to work with your own code:
import sys
from PyQt5 import QtCore, QtWidgets
class Window(QtWidgets.QWidget):
def __init__(self):
super(Window, self).__init__()
self.scroll = QtWidgets.QScrollArea()
self.scroll.setWidgetResizable(True)
self.scroll_widget = QtWidgets.QWidget()
self.scroll_widget.setMaximumWidth(200)
self.elementos_widget = QtWidgets.QWidget()
vbox = QtWidgets.QVBoxLayout(self.scroll_widget)
vbox.setContentsMargins(0, 0, 0, 0)
vbox.addWidget(self.elementos_widget)
vbox.addStretch()
self.elementos = QtWidgets.QGridLayout()
self.elementos_widget.setLayout(self.elementos)
self.scroll.setWidget(self.scroll_widget)
self.button = QtWidgets.QPushButton('Add')
self.button.clicked.connect(self.crear_punto)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.scroll)
layout.addWidget(self.button)
def crear_punto(self):
num_elementos = self.elementos.rowCount()
name = QtWidgets.QLabel()
name.setText('FOO %s' % num_elementos)
borrar = QtWidgets.QPushButton()
borrar.setText('X')
self.elementos.addWidget(name, num_elementos, 0)
self.elementos.addWidget(borrar, num_elementos, 1)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 100, 300, 500)
window.show()
sys.exit(app.exec_())

Related

PyQt5 fix Qlabel position

i am new to PyQt5 and I try to create a window with grid layout for buttons. But I want to add two labels at top left and bottom right corner of the window.
from PyQt5 import QtWidgets
from PyQt5 import QtCore
import sys
class PrettyWidget(QtWidgets.QWidget):
def __init__(self):
super(PrettyWidget, self).__init__()
self.initUI()
def initUI(self):
self.setGeometry(600,300, 1000, 600)
self.setWindowTitle('Program v1.0')
# Grid Layout
grid = QtWidgets.QGridLayout()
self.setLayout(grid)
self.lbl1 = QtWidgets.QLabel(self)
self.lbl1.setText('Author Information and Copy Right')
self.lbl1.adjustSize()
self.lbl1.move(588, 0)
# Label indicator
self.lbl2 = QtWidgets.QLabel(self)
self.lbl2.setText('Click import to start...')
self.lbl2.adjustSize()
self.lbl2.move(0, 0)
# Import data Button
btn1 = QtWidgets.QPushButton('Select Data', self)
btn1.resize(btn1.sizeHint())
btn1.clicked.connect(self.getData)
grid.addWidget(btn1, 0, 0)
# Import names Button
btn2 = QtWidgets.QPushButton('Select Names', self)
btn2.resize(btn2.sizeHint())
btn2.clicked.connect(self.getNames)
grid.addWidget(btn2, 0, 1)
# Run Button
btn3 = QtWidgets.QPushButton('Run', self)
btn3.resize(btn3.sizeHint())
btn3.clicked.connect(self.Run)
grid.addWidget(btn3, 1, 0)
# Save Button
btn4 = QtWidgets.QPushButton('Save',self)
btn4.resize(btn4.sizeHint())
btn4.clicked.connect(self.Save)
grid.addWidget(btn4, 1, 1)
self.show()
def getData(self):
self.lbl2.setText('Data selected!')
self.lbl2.adjustSize()
def getNames(self):
self.lbl2.setText('Names selected!')
self.lbl2.adjustSize()
def Run(self):
self.lbl2.setText('Done!')
self.lbl2.adjustSize()
def Save(self):
self.lbl2.setText('Saved!')
self.lbl2.adjustSize()
def main():
app = QtWidgets.QApplication(sys.argv)
w = PrettyWidget()
app.exec_()
if __name__ == '__main__':
main()
As you can see I use absolute position for two labels now. So when I maximize or change the window size, the label stays at the same position. How do I stick lbl1 at bottom right and lbl at top left as always?
Paste the labels into the layout.
Set the stretch factor of row row to stretch .
import sys
from PyQt5 import QtWidgets
from PyQt5 import QtCore
class PrettyWidget(QtWidgets.QWidget):
def __init__(self):
super(PrettyWidget, self).__init__()
self.initUI()
def initUI(self):
self.setGeometry(300,100, 1000, 600)
self.setWindowTitle('Program v1.0')
# Grid Layout
grid = QtWidgets.QGridLayout()
self.setLayout(grid)
self.lbl1 = QtWidgets.QLabel(self, alignment=QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
self.lbl1.setText('Author Information and Copy Right')
self.lbl1.adjustSize()
grid.addWidget(self.lbl1, 0, 0)
grid.setRowStretch(1, 1) # <---- Sets the stretch factor of row row to stretch .
# Label indicator
self.lbl2 = QtWidgets.QLabel(self, alignment=QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
self.lbl2.setText('Click import to start...')
self.lbl2.adjustSize()
grid.addWidget(self.lbl2, 5, 1)
# Import data Button
btn1 = QtWidgets.QPushButton('Select Data', self)
btn1.resize(btn1.sizeHint())
btn1.clicked.connect(self.getData)
grid.addWidget(btn1, 2, 0)
# Import names Button
btn2 = QtWidgets.QPushButton('Select Names', self)
btn2.resize(btn2.sizeHint())
btn2.clicked.connect(self.getNames)
grid.addWidget(btn2, 2, 1)
# Run Button
btn3 = QtWidgets.QPushButton('Run', self)
btn3.resize(btn3.sizeHint())
btn3.clicked.connect(self.Run)
grid.addWidget(btn3, 3, 0)
# Save Button
btn4 = QtWidgets.QPushButton('Save',self)
btn4.resize(btn4.sizeHint())
btn4.clicked.connect(self.Save)
grid.addWidget(btn4, 3, 1)
grid.setRowStretch(4, 1) # <---- Sets the stretch factor of row row to stretch .
self.show()
def getData(self):
self.lbl2.setText('Data selected!')
self.lbl2.adjustSize()
def getNames(self):
self.lbl2.setText('Names selected!')
self.lbl2.adjustSize()
def Run(self):
self.lbl2.setText('Done!')
self.lbl2.adjustSize()
def Save(self):
self.lbl2.setText('Saved!')
self.lbl2.adjustSize()
def main():
app = QtWidgets.QApplication(sys.argv)
w = PrettyWidget()
app.exec_()
if __name__ == '__main__':
main()

how to copy the text from text edit into a string variable?

i am trying to copy the text I enter into the text edit and store it into a string variable.
I have written the following code but it shows 'python has stopped working'
from PyQt5 import QtGui,QtWidgets,QtCore
import sys
class GUI(QtWidgets.QWidget):
def __init__(self):
super(GUI,self).__init__()
self.initUI()
def initUI(self):
review = QtWidgets.QLabel('Review')
reviewEdit = QtWidgets.QTextEdit()
grid = QtWidgets.QGridLayout()
grid.addWidget(review, 3, 0)
grid.addWidget(reviewEdit, 3, 1, 5, 1)
self.setLayout(grid)
self.setGeometry(300,300,350,300)
self.setWindowTitle('Sentiment Analysis')
button = QtWidgets.QPushButton("OK")
grid.addWidget(button)
button.clicked.connect(self.copyText)
self.show()
def copyText(self):
reviewEdit.setText("text")
print(text)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
GUI = GUI()
sys.exit(app.exec_())
The program stops working because of a NameError in the copyText() method. The reviewEdit variable doesn't exit in that scope, so you can't reference it.
The way to fix this is to make all the child widgets attributes of the main class - then you can access them later using self:
class GUI(QtWidgets.QWidget):
def __init__(self):
super(GUI,self).__init__()
self.initUI()
def initUI(self):
self.review = QtWidgets.QLabel('Review')
self.reviewEdit = QtWidgets.QTextEdit()
grid = QtWidgets.QGridLayout()
grid.addWidget(self.review, 3, 0)
grid.addWidget(self.reviewEdit, 3, 1, 5, 1)
self.setLayout(grid)
self.setGeometry(300,300,350,300)
self.setWindowTitle('Sentiment Analysis')
self.button = QtWidgets.QPushButton("OK")
grid.addWidget(self.button)
self.button.clicked.connect(self.copyText)
self.show()
def copyText(self):
# self.reviewEdit.setText("text")
text = self.reviewEdit.toPlainText()
print(text)
First, you should make reviewEdit a member of GUI class. Like this:
self.reviewEdit = QtGui.QTextEdit()
next, in addBold(self), you get the text like this:
text = str(self.reviewEdit.toPlainText())

wx python image refresh on Windows

I have an application that involves displaying multiple images. This works as I would expect on linux, but on Windows there is an annoying flash as the images are painted. This is best seen as a little square in the top left-hand corner of the screen where a flash of colour appears. Am I not approaching this requirement in the right way? Or is there some fix I should be applying to overcome the Windows effect? Or is it just my version on Windows (I only have one to test it: Windows 7 Ultimate)?
I have tried Freeze and Thaw in refresh_sizer_cell but it didn't behave as I expected
import wx
class ImageSizer(wx.Frame):
BACKGROUND_COLOUR = (246, 244, 242)
def __init__(self, parent, title):
super(ImageSizer, self).__init__(parent, title=title)
self.main_sizer = wx.GridBagSizer()
self.SetSizer(self.main_sizer)
cmd_reset = wx.Button(self, label='Reset')
cmd_reset.Bind(wx.EVT_BUTTON, self.on_cmd_reset_click)
cmd_cancel = wx.Button(self, label='Cancel')
cmd_cancel.Bind(wx.EVT_BUTTON, self.on_cmd_cancel_click)
self.main_sizer.Add((400, 0), pos=(0, 0), span=(1, 2)) # dummy to position Available
self.main_sizer.Add((0, 100), pos=(1, 0), span=(1, 1)) # dummy to position Buttons
self.main_sizer.Add(cmd_reset, pos=(2, 2), flag=wx.LEFT | wx.TOP, border=10)
self.main_sizer.Add(cmd_cancel, pos=(2, 3), flag=wx.RIGHT | wx.BOTTOM | wx.TOP | wx.ALIGN_RIGHT, border=10)
self.SetBackgroundColour(self.BACKGROUND_COLOUR)
self.shape_types = {'available': 0, 'selected': 1}
self.available_shapes = []
self.selected_shapes = []
self.initialise()
self.Center()
self.Fit()
self.Show()
def initialise(self):
self.available_shapes = ['square', 'circle', 'triangle', 'cross']
self.selected_shapes = []
self.display_images()
def display_images(self):
available_sizer = ShapeSizer(self, self.available_shapes, self.shape_types['available'])
self.refresh_sizer_cell(self.main_sizer, available_sizer, (1, 2), (1, 3))
selected_sizer = ShapeSizer(self, self.selected_shapes, self.shape_types['selected'])
self.refresh_sizer_cell(self.main_sizer, selected_sizer, (1, 1), (2, 1))
self.Layout()
#staticmethod
def refresh_sizer_cell(sizer, item, pos, span, flag=wx.ALL, border=10):
old_item = sizer.FindItemAtPosition(pos)
if old_item is not None and old_item.IsWindow():
old_item.GetWindow().Hide()
sizer.Detach(old_item.GetWindow())
sizer.Add(item, pos=pos, span=span, flag=flag, border=border)
def on_available_shape_double_click(self, event):
shape = event.GetEventObject().GetName()
self.available_shapes.remove(shape)
self.selected_shapes.append(shape)
self.display_images()
def on_selected_shape_double_click(self, event):
shape = event.GetEventObject().GetName()
self.selected_shapes.remove(shape)
self.available_shapes.append(shape)
self.display_images()
def on_cmd_reset_click(self, event):
self.initialise()
def on_cmd_cancel_click(self, event):
self.Destroy()
class ShapeSizer(wx.Panel):
def __init__(self, parent, shapes, shape_type):
wx.Panel.__init__(self, parent, id = wx.ID_ANY)
if shape_type == parent.shape_types['available']:
size = 40
action = parent.on_available_shape_double_click
else:
size = 80
action = parent.on_selected_shape_double_click
panel_sizer = wx.BoxSizer(wx.HORIZONTAL)
shapes.sort()
for shape in shapes:
bitmap = wx.Bitmap(shape + '.png', wx.BITMAP_TYPE_PNG)
bitmap = self.scale_bitmap(bitmap, size, size)
img = wx.StaticBitmap(self, wx.ID_ANY, bitmap, name=shape)
img.Bind(wx.EVT_LEFT_DCLICK, action)
panel_sizer.Add(img, flag=wx.RIGHT, border=10)
self.SetSizer(panel_sizer)
#staticmethod
def scale_bitmap(bitmap, width, height):
image = wx.ImageFromBitmap(bitmap)
image = image.Scale(width, height, wx.IMAGE_QUALITY_HIGH)
result = wx.BitmapFromImage(image)
return result
if __name__ == '__main__':
app = wx.App()
ImageSizer(None, title='Image Sizer')
app.MainLoop()
Here are the images:
Every time you double click on a shape your program is creating new instances of the panels and their wx.StaticBitmap widgets, it is these new instances you are seeing as they are initially created with a small default size and then they are repositioned by the next layout. Instead you should reorganize things so you only create the set of panels once, and as the state of the shape selections changes you can have the existing panels update themselves. That will greatly reduce the flicker visible to the user.

How to add TextEdit, Labels and Buttons that move when Window Size is moved using PyQt?

I am new to PyQt, but for the past days I was trying to create a GUI which has labels, TextEdit and buttons which move when the Window size is moved (minimized or enlarged), I tried doing it so but the Buttons get stuck in the top left corner while the labels and TextEdit completely don't show up on the form, Please do help . Here is a snippet of my codes
import sys
from PyQt4 import QtGui, QtCore
class Window(QtGui.QMainWindow, QtGui.QWidget):
` def __init__(self):
super(Window, self).__init__()
self.setGeometry(50, 50, 500, 300)
self.setWindowTitle("PTE")
self.setWindowIcon(QtGui.QIcon('.png'))
self.center()
# Adding Menu to the GUI
quitAction = QtGui.QAction(QtGui.QIcon('exit.png'), "&Quit", self)
quitAction.setShortcut("Ctrl+Q")
quitAction.setStatusTip('Exit Application')
quitAction.triggered.connect(self.close_application)
undoAction = QtGui.QAction(QtGui.QIcon('undo.png'), "&Undo", self)
undoAction.setShortcut("Ctrl+Z")
undoAction.triggered.connect(self.close_application)
aboutAction = QtGui.QAction("&About PTE...", self)
self.statusBar()
#Actual Main Menu with options
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu('&File')
fileMenu.addAction(quitAction)
fileMenu = mainMenu.addMenu('&Edit')
fileMenu.addAction(undoAction)
fileMenu = mainMenu.addMenu('&Help')
fileMenu.addAction(aboutAction)
self.home()
#Centering Window on the screen
def center(self):
gui = self.frameGeometry()
cp = QtGui.QDesktopWidget().availableGeometry().center()
gui.moveCenter(cp)
self.move(gui.topLeft())
def home(self):
#Buttons
qbtn = QtGui.QPushButton('Quit', self)
qbtn.clicked.connect(self.close_application)
rbtn = QtGui.QPushButton("Run", self)
rbtn.clicked.connect(self.close_application)
hbox = QtGui.QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(qbtn)
hbox.addWidget(rbtn)
vbox = QtGui.QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)
self.setLayout(vbox)
self.show()
#Labels and TextBox
Intervals = QtGui.QLabel('Number of intervals (0<=20) :')
Timesteps = QtGui.QLabel('Number of time steps (<=1000) : ')
IntervalsEdit = QtGui.QLineEdit()
TimestepsEdit = QtGui.QLineEdit()
grid = QtGui.QGridLayout()
grid.setSpacing(2)
grid.addWidget(Intervals, 1, 0)
grid.addWidget(IntervalsEdit, 1, 1)
grid.addWidget(Timesteps, 2, 0)
grid.addWidget(TimestepsEdit, 2, 1)
self.setLayout(grid)
self.show()
#What to display when the app is closed
def close_application(self):
#Popup message before closing the application in Binary
choice = QtGui.QMessageBox.question(self, 'Message',"Are you sure you want to exit?",
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No )
if choice == QtGui.QMessageBox.Yes:
print(" Until Next Time")
sys.exit()
else:
pass
def run():
app = QtGui.QApplication(sys.argv)
GUI = Window()
sys.exit(app.exec_())
run()
Hey i fixed the issues with your code. In my fix, i added the QGridLayout to the QHBoxLayout. If you want the grid in another place you might need to nest both layouts in a 3rd layout.
Note that you are using setLayout for grid and for vbox when you can only set 1 layout. You also call show() twice, which you don't need. You also add a QVBoxLayout to hbox but do not add any widget. As it is, this is useless. If you want hbox and grid to be vertically aligned you will need to vbox.addLayout(grid) and self.setLayout(vbox) instead.
import sys
from PyQt4 import QtGui, QtCore
class Window(QtGui.QMainWindow, QtGui.QWidget):
` def __init__(self):
super(Window, self).__init__()
self.setGeometry(50, 50, 500, 300)
self.setWindowTitle("PTE")
self.setWindowIcon(QtGui.QIcon('.png'))
self.center()
# Adding Menu to the GUI
quitAction = QtGui.QAction(QtGui.QIcon('exit.png'), "&Quit", self)
quitAction.setShortcut("Ctrl+Q")
quitAction.setStatusTip('Exit Application')
quitAction.triggered.connect(self.close_application)
undoAction = QtGui.QAction(QtGui.QIcon('undo.png'), "&Undo", self)
undoAction.setShortcut("Ctrl+Z")
undoAction.triggered.connect(self.close_application)
aboutAction = QtGui.QAction("&About PTE...", self)
self.statusBar()
#Actual Main Menu with options
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu('&File')
fileMenu.addAction(quitAction)
fileMenu = mainMenu.addMenu('&Edit')
fileMenu.addAction(undoAction)
fileMenu = mainMenu.addMenu('&Help')
fileMenu.addAction(aboutAction)
self.home()
#Centering Window on the screen
def center(self):
gui = self.frameGeometry()
cp = QtGui.QDesktopWidget().availableGeometry().center()
gui.moveCenter(cp)
self.move(gui.topLeft())
def home(self):
#Buttons
qbtn = QtGui.QPushButton('Quit', self)
qbtn.clicked.connect(self.close_application)
rbtn = QtGui.QPushButton("Run", self)
rbtn.clicked.connect(self.close_application)
hbox = QtGui.QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(qbtn)
hbox.addWidget(rbtn)
vbox = QtGui.QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)
#self.show() #this only needs to be called once
#Labels and TextBox
Intervals = QtGui.QLabel('Number of intervals (0<=20) :')
Timesteps = QtGui.QLabel('Number of time steps (<=1000) : ')
IntervalsEdit = QtGui.QLineEdit()
TimestepsEdit = QtGui.QLineEdit()
grid = QtGui.QGridLayout()
grid.setSpacing(2)
grid.addWidget(Intervals, 1, 0)
grid.addWidget(IntervalsEdit, 1, 1)
grid.addWidget(Timesteps, 2, 0)
grid.addWidget(TimestepsEdit, 2, 1)
hbox.addLayout(grid) #this will add the grid to the horizontal layout.
#if you want it to be vertcally aligned change this to vbox.addLayout(grid)...
#... and this to self.setLayout(vbox)
self.setLayout(hbox)
self.show()
#What to display when the app is closed
def close_application(self):
#Popup message before closing the application in Binary
choice = QtGui.QMessageBox.question(self, 'Message',"Are you sure you want to exit?",
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No )
if choice == QtGui.QMessageBox.Yes:
print(" Until Next Time")
sys.exit()
else:
pass

PyQt QScrollArea not scrolling

I want to put some elements of my UI in a scroll area as there can be a lot of them. I tried the following peice of code, but the area just keeps growing as I put more elements on it.
In the first part I set up a scroll area, a widget and a layout. I apply the layout to the widget and I set the widget to the scrollarea. Then I fill in my layout in an external function. The button under all of it allows to fill more elements in the layout.
scrollRow = QtGui.QScrollArea()
scrollRow.setMaximumSize(600, 400)
self.rowAssetWidget = QtGui.QWidget()
self.rowAssetLayout = QtGui.QGridLayout()
self.rowAssetLayout.setSpacing(20)
self.rowAssetWidget.setLayout(self.rowAssetLayout)
scrollRow.setWidget(self.rowAssetWidget)
#self.mainLayout.addLayout(self.rowAssetLayout, 2, 0)
self.mainLayout.addWidget(self.rowAssetWidget, 2, 0)
self.assetRow()
self.addAssetRowBtn = QtGui.QPushButton("+")
self.addAssetRowBtn.setFixedSize(20, 20)
self.mainLayout.addWidget(self.addAssetRowBtn, 3, 0)
self.connect(self.addAssetRowBtn, QtCore.SIGNAL("clicked()"), self.addAssetRow)
My elements appear fine, but it is not scrolling. Any idea ?
import sys
from PyQt4 import QtGui,QtCore
class LayoutTest(QtGui.QWidget):
def __init__(self):
super(LayoutTest, self).__init__()
self.horizontalLayout = QtGui.QVBoxLayout(self)
self.scrollArea = QtGui.QScrollArea(self)
self.scrollArea.setWidgetResizable(True)
self.scrollAreaWidgetContents = QtGui.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 380, 280))
self.horizontalLayout_2 = QtGui.QHBoxLayout(self.scrollAreaWidgetContents)
self.gridLayout = QtGui.QGridLayout()
self.horizontalLayout_2.addLayout(self.gridLayout)
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.add_button = QtGui.QPushButton("Add Items")
self.horizontalLayout.addWidget(self.scrollArea)
self.horizontalLayout.addWidget(self.add_button)
self.connect(self.add_button, QtCore.SIGNAL("clicked()"), self.addButtons)
self.setGeometry(300, 200, 400, 300)
def addButtons(self):
for i in range(0, 50):
self.r_button = QtGui.QPushButton("Button %s " % i)
self.gridLayout.addWidget(self.r_button)
def run():
app = QtGui.QApplication(sys.argv)
ex = LayoutTest()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
run()
I know its too late to answer for this question, but here is a working example and you missing the parent layout.
Yeah. My mistake was on my end is that PyQT Designer set a .setGeometry() for the ScrollAreaWidgetContents widget within the QScrollArea. My solution was to use instead the .setMinimumHeight( ) and .setMinimumWidth( ).
Remove this:
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 380, 280))
And replace with:
self.scrollAreaWidgetContents.setMinimumWidth(380)
self.scrollAreaWidgetContents.setMinimumHeight(280)

Resources