PyQt add a scrollbar to MainWindow - python

This a recuring question and i've read many topics some helped a bit (python Qt: main widget scroll bar, PyQt: Put scrollbars in this), some not at all (PyQt adding a scrollbar to my main window), I still have problem with the scrollbars. They're not usable, the're 'grey'.
Here is my code (I'm using PyQt5) :
def setupUi(self, Interface):
Interface.setObjectName("Interface")
Interface.resize(1152, 1009)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(Interface.sizePolicy().hasHeightForWidth())
Interface.setSizePolicy(sizePolicy)
Interface.setMouseTracking(False)
icon = QtGui.QIcon()
self.centralWidget = QtWidgets.QWidget(Interface)
self.centralWidget.setObjectName("centralWidget")
self.scrollArea = QtWidgets.QScrollArea(self.centralWidget)
self.scrollArea.setGeometry(QtCore.QRect(0, 0, 1131, 951))
self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName("scrollArea")
self.scrollArea.setEnabled(True)
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 1112, 932))
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents)
self.horizontalLayout.setObjectName("horizontalLayout")
So i would like to put the scrollbars on the main widget, so if the user resizes the main window, the scrollbar appears, and let he move up and down to see child widgets that is outside the smaller window widget, allowing it to move right and left.
Help appreciated !

There are several things wrong with the example code. The main problems are that you are not using layouts properly, and the content widget is not being added to the scroll-area.
Below is a fixed version (the commented lines are all junk, and can be removed):
def setupUi(self, Interface):
# Interface.setObjectName("Interface")
# Interface.resize(1152, 1009)
# sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
# sizePolicy.setHorizontalStretch(0)
# sizePolicy.setVerticalStretch(0)
# sizePolicy.setHeightForWidth(Interface.sizePolicy().hasHeightForWidth())
# Interface.setSizePolicy(sizePolicy)
# Interface.setMouseTracking(False)
# icon = QtGui.QIcon()
self.centralWidget = QtWidgets.QWidget(Interface)
# self.centralWidget.setObjectName("centralWidget")
layout = QtWidgets.QVBoxLayout(self.centralWidget)
self.scrollArea = QtWidgets.QScrollArea(self.centralWidget)
# self.scrollArea.setGeometry(QtCore.QRect(0, 0, 1131, 951))
# self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
# self.scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
# self.scrollArea.setWidgetResizable(True)
# self.scrollArea.setObjectName("scrollArea")
# self.scrollArea.setEnabled(True)
layout.addWidget(self.scrollArea)
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 1112, 932))
# self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
layout = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents)
# self.horizontalLayout.setObjectName("horizontalLayout")
# add child widgets to this layout...
Interface.setCentralWidget(self.centralWidget)

The scrollbars are grayed out because you made them always visible by setting the scrollbar policy to Qt.ScrollBarAlwaysOn but actually there is no content to be scrolled so they are disabled. If you want scrollbars to appear only when they are needed you need to use Qt.ScrollBarAsNeeded.
There is no content to be scrolled because there is only 1 widget in the QHBoxLayout (see self.scrollAreaWidgetContents). Also if this method is being executed from a QMainWindow you also have an error when setting the central widget: self.centralWidget is a method to retrieve the central widget. It's working because you are overwriting it with a QWidget instance (and I believe python allows you to do that). To correctly set the central widget you need to use setCentralWidget() in QMainWindow.
def setupUi(self, Interface):
Interface.setObjectName("Interface")
Interface.resize(1152, 1009)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(Interface.sizePolicy().hasHeightForWidth())
Interface.setSizePolicy(sizePolicy)
Interface.setMouseTracking(False)
icon = QtGui.QIcon()
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.scrollArea = QtWidgets.QScrollArea()
self.scrollArea.setGeometry(QtCore.QRect(0, 0, 1131, 951))
self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
self.scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName("scrollArea")
self.scrollArea.setEnabled(True)
self.horizontalLayout.addWidget(self.scrollArea)
centralWidget = QWidgets.QWidget()
centralWidget.setObjectName("centralWidget")
centralWidget.setLayout(self.horizontalLayout)
self.setCentralWidget(centralWidget)
I left Interface out since I don't know what it is, but the rest should be ok.

Related

Python file launched by bash produces error

I have a python script that runs fine when launched on its own.
I want to write a bash script that will run one python script, and then another when the first ends.
Bash script:
#!/bin/bash
python /FILEPATH/FILE1.py ;
python /FILEPATH/FILE2.py
When I execute the bash file, I get this error message:
File "Filename of first python script", line 149
self.label_2.setText(f'Invalid: {input_str}')
File "Filename of second python script", line 139
self.label_2.setText(f'Invalid: {input_str}')
with an accent pointing at the last single quote of both lines.
(The scripts are identical, save for the values contained in the dictionary.
Here is that code
import sys
import os
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import QMovie, QPixmap
from PyQt5.QtWidgets import *
WINDOW_STYLE = '''
background-color:black;
color:white;
'''
class Ui_Widget(QWidget):
# You need to change this
CARD_DICT = {
# PIN: IMAGE_PATH
'1360739516458': 'images/1.png', # Right lung
'1360743335192': 'images/2.png', # Left lung apex
'1360341692930': 'images/3.png', # Left heart
'136073147157207': 'images/4.png', # Spleen
'136075353245': 'images/5.png', # Subxiphoid cardiac
# '136072179130241': 'images/6.png', # Diaphragm?
# '136073133188248': 'images/7.png', # Supra umbilicus
# '136035223197177': 'images/8.png', # right lateral
# '1360341562547': 'images/9.png', # left lateral
# '13607311245156': 'images/10.png', # Sub umbilicus
# the following are for testing purposes only
'60013620412116': 'images/6.png', # Diaphragm?
'13603447120253': 'images/7.png', # Supra umbilicus
'1360341002204': 'images/8.png', # right lateral
'13607217912415': 'images/9.png', # left lateral
'136073209222206': 'images/10.png', # Sub umbilicus
}
def __init__(self):
super(Ui_Widget, self).__init__()
self.setWindowTitle('Simulated Ultrasound')
# Full screen
self.setWindowState(Qt.WindowMaximized)
# No close, minimize and miximaze window button
self.setWindowFlag(Qt.FramelessWindowHint)
self.setAttribute(QtCore.Qt.WA_StyledBackground, True)
self.setStyleSheet(WINDOW_STYLE)
self.setupUi(self)
def setupUi(self, Widget):
Widget.setObjectName("Widget")
Widget.resize(800, 600)
self.verticalLayout_2 = QtWidgets.QVBoxLayout(Widget)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
self.gridLayout.setObjectName("gridLayout")
self.label = QtWidgets.QLabel(Widget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth())
self.label.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setPointSize(50)
self.label.setFont(font)
self.label.setFrameShape(QtWidgets.QFrame.NoFrame)
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
self.verticalLayout_2.addLayout(self.gridLayout)
self.lineEdit = QtWidgets.QLineEdit(Widget)
sizePolicy = QtWidgets.QSizePolicy(
QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred
)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lineEdit.sizePolicy().hasHeightForWidth())
self.lineEdit.setSizePolicy(sizePolicy)
self.lineEdit.setMinimumSize(QtCore.QSize(780, 0))
self.lineEdit.setAlignment(QtCore.Qt.AlignCenter)
self.lineEdit.setObjectName("lineEdit")
self.verticalLayout_2.addWidget(self.lineEdit)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize)
self.horizontalLayout.setSpacing(10)
self.horizontalLayout.setObjectName("horizontalLayout")
self.label_2 = QtWidgets.QLabel(Widget)
sizePolicy = QtWidgets.QSizePolicy(
QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum
)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_2.sizePolicy().hasHeightForWidth())
self.label_2.setSizePolicy(sizePolicy)
self.label_2.setMinimumSize(QtCore.QSize(0, 10))
self.label_2.setObjectName("label_2")
self.horizontalLayout.addWidget(self.label_2)
spacerItem = QtWidgets.QSpacerItem(
40, 10, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum
)
self.horizontalLayout.addItem(spacerItem)
self.pushButton = QtWidgets.QPushButton(Widget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pushButton.sizePolicy().hasHeightForWidth())
self.pushButton.setSizePolicy(sizePolicy)
self.pushButton.setMinimumSize(QtCore.QSize(0, 26))
self.pushButton.setObjectName("pushButton")
self.horizontalLayout.addWidget(self.pushButton)
self.verticalLayout_2.addLayout(self.horizontalLayout)
self.retranslateUi(Widget)
QtCore.QMetaObject.connectSlotsByName(Widget)
# I think this is the line to change to make it launch another script
self.pushButton.pressed.connect(Widget.close) # type: ignore
# self.pushButton.pressed.connect(Widget.post_intervention) # type: ignore
# Check every time the text line input changed
self.lineEdit.textChanged.connect(self.submit_pass) # type: ignore
def retranslateUi(self, Widget):
_translate = QtCore.QCoreApplication.translate
Widget.setWindowTitle(_translate("Widget", "Widget"))
self.label.setText(_translate("Widget", "Scan patient to begin"))
self.lineEdit.setPlaceholderText(_translate("Widget", "PIN Phrase"))
self.label_2.setText(_translate("Widget", "Arthur: PRE-intervention"))
self.pushButton.setText(_translate("Widget", "Click here after performing interventions"))
def submit_pass_str(self, input_str):
"""here the application accept user input"""
if input_str in self.CARD_DICT:
self.display_image(self.CARD_DICT[input_str])
self.label_2.setText('')
else:
self.label_2.setText(f'Invalid: {input_str}')
def display_image(self, path):
name, ext = os.path.splitext(path)
if ext and ext.lower() == '.gif':
movie = QMovie(path)
self.label.setMovie(movie)
movie.start()
else:
image = QPixmap(path)
self.label.setPixmap(image)
self.label.setMinimumSize(1, 1)
def submit_pass(self):
"""Usage example using PIN Phrase input form"""
self.submit_pass_str(self.lineEdit.text())
app = QApplication(sys.argv)
window = Ui_Widget()
window.show()
# sys.exit(post_intervention())
sys.exit(app.exec_())

Reading/accessing stackedwidgets child widget's parameters through objectName

I have a few layouts. Amongst them, one houses the Page buttons, while another constitutes stackedWidget. I was able to dynamically add new Page buttons and new pages in the stackedwidget through add_command function. Each new stackedWidget pages has a dynamically added label and them given objectName as well.
How to access(read) the objects in the dynamically added pages and labels through objectName? New Pages, which were also given objectName were only accessible through setCurrentIndex(index) instead of setCurrentWidget(objectName). The reason being is that I want to upload the values later into a database. Code shared here is an MWE.
For example, reading the lblPage2 which were dynamically added in the display function, returns AttributeError:
AttributeError: 'Ui_MainWindow' object has no attribute 'lblPage2'. Did you mean: 'lblPage1'?
Similarly, showing newly added stackedWidget pages though objectName, e.g. page2 returns a similar error (only accessible through index). I have a guess that these errors are due to the objects weren't initialized when the main class was called.
How to access/read the dynamically added objects through objectName? Or should there be a second init?
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(277, 300)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout_5.setObjectName("verticalLayout_5")
self.verticalLayout_4 = QtWidgets.QVBoxLayout()
self.verticalLayout_4.setObjectName("verticalLayout_4")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.btnPage1 = QtWidgets.QPushButton(self.centralwidget)
self.btnPage1.setObjectName("btnPage1")
self.btnPage1.setText("Page 1")
self.btnPage1.clicked.connect(lambda i=0 :self.display(i))
self.verticalLayout.addWidget(self.btnPage1)
self.horizontalLayout.addLayout(self.verticalLayout)
self.verticalLayout_2 = QtWidgets.QVBoxLayout()
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.stackedWidget = QtWidgets.QStackedWidget(self.centralwidget)
self.stackedWidget.setFrameShape(QtWidgets.QFrame.Panel)
self.stackedWidget.setObjectName("stackedWidget")
self.page1 = QtWidgets.QWidget()
self.page1.setObjectName("page1")
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.page1)
self.verticalLayout_6.setObjectName("verticalLayout_6")
self.lblPage1 = QtWidgets.QLabel(self.page1)
self.lblPage1.setObjectName("lblPage1")
self.lblPage1.setText("This is Page 1")
self.verticalLayout_6.addWidget(self.lblPage1)
self.stackedWidget.addWidget(self.page1)
self.verticalLayout_2.addWidget(self.stackedWidget)
self.horizontalLayout.addLayout(self.verticalLayout_2)
self.verticalLayout_4.addLayout(self.horizontalLayout)
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_3.addItem(spacerItem)
self.verticalLayout_3 = QtWidgets.QVBoxLayout()
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.btnAdd = QtWidgets.QPushButton(self.centralwidget)
self.btnAdd.setObjectName("btnAdd")
self.btnAdd.setText("Add")
self.btnAdd.clicked.connect(self.add_command)
self.verticalLayout_3.addWidget(self.btnAdd)
self.btnRemove = QtWidgets.QPushButton(self.centralwidget)
self.btnRemove.setObjectName("btnRemove")
self.btnRemove.setText("Remove")
self.btnRemove.clicked.connect(self.remove_command)
self.verticalLayout_3.addWidget(self.btnRemove)
self.horizontalLayout_3.addLayout(self.verticalLayout_3)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_3.addItem(spacerItem1)
self.verticalLayout_4.addLayout(self.horizontalLayout_3)
self.verticalLayout_5.addLayout(self.verticalLayout_4)
MainWindow.setCentralWidget(self.centralwidget)
self.stackedWidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def add_command(self):
#add new page button
btn_count = self.stackedWidget.count()
new_btn_count = str(btn_count + 1)
new_btn_text = str(new_btn_count)
new_btn = QtWidgets.QPushButton(self.centralwidget)
new_btn.setText("Page{0}".format(new_btn_text))
new_btn.clicked.connect(lambda: self.display(btn_count))
self.verticalLayout.addWidget(new_btn)
#add new page
new_page_count = str(btn_count + 1)
new_page_text = str(new_btn_count)
new_page = QtWidgets.QWidget()
new_page.setObjectName("page{0}".format(new_page_text))
self.new_verticalLayout = QtWidgets.QVBoxLayout(new_page)
new_lbl = QtWidgets.QLabel(new_page)
new_lbl.setObjectName("lblPage{0}".format(new_page_text))
new_lbl.setText("This is Page {0}".format(new_page_text))
self.new_verticalLayout.addWidget(new_lbl)
self.stackedWidget.addWidget(new_page)
self.stackedWidget.setCurrentIndex(btn_count)
print("Added")
def remove_command(self):
#remove page code
print("Removed")
def display(self,i):
self.stackedWidget.setCurrentIndex(i)
#self.stackedWidget.setCurrentWdiget(Page2) - returns error
print(self.lblPage2.text()) #returns error
#print(self.lblPage3.text())
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())

How do I go about creating a dynamic grid QScrollarea in PyQt5?

I'm developing some custom software that involves creating a workspace and working in it. I want to display all the existing workSpace directories in a dynamic scrollarea grid comprised of buttons that changes the positions of the buttons depending on the amount of screen real estate the scrollarea is taking up so that as many buttons as possible are inserted in the highest possible row.( So basically like the file explorer changes the layout of the folders and files to fit the screen in a grid depending on how you resize the window) I tried doing this using a gridlayout inside the scrollarea. I also tried to add qhboxlayouts in a qvboxlayout to no avail since I had no idea how to check whether there is space for another button to remove one from a lower qhboxlayout and append to a higher one.
This is my current code:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QFileDialog
class Ui_AutoCal(object):
def setupUi(self, AutoCal):
AutoCal.setObjectName("AutoCal")
AutoCal.resize(513, 551)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(AutoCal.sizePolicy().hasHeightForWidth())
AutoCal.setSizePolicy(sizePolicy)
AutoCal.setCursor(QtGui.QCursor(QtCore.Qt.CrossCursor))
AutoCal.setStyleSheet("*{\n"
"background-color: rgb(54, 54, 54);\n"
"color:rgb(255,255,255)\n"
"}\n"
"\n"
"QPushButton\n"
"{\n"
"border-radius: 25px;\n"
"}\n"
"\n"
"QLineEdit\n"
"{\n"
"color:rgb(0,0,0)\n"
"}")
self.centralwidget = QtWidgets.QWidget(AutoCal)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.groupBox.sizePolicy().hasHeightForWidth())
self.groupBox.setSizePolicy(sizePolicy)
self.groupBox.setAlignment(QtCore.Qt.AlignCenter)
self.groupBox.setObjectName("groupBox")
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.groupBox)
self.verticalLayout_6.setObjectName("verticalLayout_6")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.label = QtWidgets.QLabel(self.groupBox)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth())
self.label.setSizePolicy(sizePolicy)
self.label.setObjectName("label")
self.horizontalLayout_3.addWidget(self.label)
self.lineEdit = QtWidgets.QLineEdit(self.groupBox)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lineEdit.sizePolicy().hasHeightForWidth())
self.lineEdit.setSizePolicy(sizePolicy)
self.lineEdit.setObjectName("lineEdit")
self.horizontalLayout_3.addWidget(self.lineEdit)
self.pushButton = QtWidgets.QPushButton(self.groupBox)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pushButton.sizePolicy().hasHeightForWidth())
self.pushButton.setSizePolicy(sizePolicy)
self.pushButton.setObjectName("pushButton")
# self.pushButton.clicked.connect(self.openFileNameDialog )
self.horizontalLayout_3.addWidget(self.pushButton)
self.verticalLayout_6.addLayout(self.horizontalLayout_3)
self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.label_2 = QtWidgets.QLabel(self.groupBox)
self.label_2.setObjectName("label_2")
self.horizontalLayout_4.addWidget(self.label_2)
self.lineEdit_2 = QtWidgets.QLineEdit(self.groupBox)
self.lineEdit_2.setText("")
self.lineEdit_2.setObjectName("lineEdit_2")
self.horizontalLayout_4.addWidget(self.lineEdit_2)
self.pushButton_2 = QtWidgets.QPushButton(self.groupBox)
self.pushButton_2.setObjectName("pushButton_2")
self.horizontalLayout_4.addWidget(self.pushButton_2)
self.verticalLayout_6.addLayout(self.horizontalLayout_4)
self.verticalLayout.addWidget(self.groupBox)
self.verticalLayout_3 = QtWidgets.QVBoxLayout()
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.groupBox_2 = QtWidgets.QGroupBox(self.centralwidget)
self.groupBox_2.setEnabled(True)
self.groupBox_2.setAlignment(QtCore.Qt.AlignCenter)
self.groupBox_2.setObjectName("groupBox_2")
self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.groupBox_2)
self.verticalLayout_5.setObjectName("verticalLayout_5")
self.scrollArea = QtWidgets.QScrollArea(self.groupBox_2)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.scrollArea.sizePolicy().hasHeightForWidth())
self.scrollArea.setSizePolicy(sizePolicy)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName("scrollArea")
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.gridLayout = QtWidgets.QGridLayout(self.scrollAreaWidgetContents)
# self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 467, 331))
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.fillScrollArea()
self.verticalLayout_5.addWidget(self.scrollArea)
self.verticalLayout_3.addWidget(self.groupBox_2)
self.verticalLayout.addLayout(self.verticalLayout_3)
AutoCal.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(AutoCal)
self.menubar.setGeometry(QtCore.QRect(0, 0, 513, 22))
self.menubar.setObjectName("menubar")
self.menuWorkSpace = QtWidgets.QMenu(self.menubar)
self.menuWorkSpace.setObjectName("menuWorkSpace")
self.menuRecipients = QtWidgets.QMenu(self.menubar)
self.menuRecipients.setObjectName("menuRecipients")
AutoCal.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(AutoCal)
self.statusbar.setObjectName("statusbar")
AutoCal.setStatusBar(self.statusbar)
self.menubar.addAction(self.menuWorkSpace.menuAction())
self.menubar.addAction(self.menuRecipients.menuAction())
self.retranslateUi(AutoCal)
QtCore.QMetaObject.connectSlotsByName(AutoCal)
def retranslateUi(self, AutoCal):
_translate = QtCore.QCoreApplication.translate
AutoCal.setWindowTitle(_translate("AutoCal", "AutoCal"))
self.groupBox.setTitle(_translate("AutoCal", "Create New WorkSpace"))
self.label.setText(_translate("AutoCal", "Choose WorkSpace Directory"))
self.pushButton.setText(_translate("AutoCal", "Browse"))
self.label_2.setText(_translate("AutoCal", "WorkSpace Name"))
self.pushButton_2.setText(_translate("AutoCal", "Create"))
self.groupBox_2.setTitle(_translate("AutoCal", "Choose Existing WorkSpace"))
self.menuWorkSpace.setTitle(_translate("AutoCal", "WorkSpace"))
self.menuRecipients.setTitle(_translate("AutoCal", "Recipients"))
def fillScrollArea(self):
for i in range(50):
for j in range(50):
self.gridLayout.addWidget(QtWidgets.QPushButton("Test"), i, j)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
AutoCal = QtWidgets.QMainWindow()
ui = Ui_AutoCal()
ui.setupUi(AutoCal)
AutoCal.show()
sys.exit(app.exec_())
This produces the following scrollArea (ignore the forms):
Current Scroll Area
The main problem is that i need the buttons to always be in the visible section of the scrollArea, whereas as you can see many of them are hidden behind the scrollarea and their text is cut off. I know this is because of the positioning that my function applies to the grid layout but I'm not aware of any other way to position them. I also need the buttons to be dynamic in the sense that if horizontal space becomes greater in a higher row, the ones in the lower row will take up that space. Because of this I dont need horizontal scrolling either, which is why it's disabled.
My issue is now resolved. While flow layout was useful, it was much more intuitive to simply use QListWidget. Many thanks to both eyllanesc and musicamante for their help.
For anyone who has the same issue, the desired result can be achieved by simply creating a QlistWidget and adding items to it:
size = QSize(100,100)
self.listWidget = QListWidget()
size = QtCore.QSize(80,80)
self.listWidget.setResizeMode(QListView.Adjust)
self.listWidget.setIconSize(size)
self.listWidget.itemDoubleClicked.connect(self.itemClicked)
self.listWidget.setViewMode(QListView.IconMode)

remove a tuggled checkbox from a scroll area when a button is clicked

I am creating a program that has the function that a checkbox is deleted when it toggled. But when I click the delete button it is not deleted from my scroll area.
I have tried some solutions, but I still have problems on it. An the below code is the best condition I managed until now.
# -*- coding: utf-8 -*-
import sys
from PySide2 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(300, 495)
MainWindow.setMaximumSize(QtCore.QSize(300, 16777215))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.frame_3 = QtWidgets.QFrame(self.centralwidget)
self.frame_3.setMaximumSize(QtCore.QSize(500, 50))
self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_3.setObjectName("frame_3")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.frame_3)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.label = QtWidgets.QLabel(self.frame_3)
self.label.setObjectName("label")
self.horizontalLayout_2.addWidget(self.label)
self.verticalLayout.addWidget(self.frame_3)
self.frame = QtWidgets.QFrame(self.centralwidget)
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.frame)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.scrollArea = QtWidgets.QScrollArea(self.frame)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName("scrollArea")
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 260, 357))
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.frame_4 = QtWidgets.QFrame(self.scrollAreaWidgetContents)
self.frame_4.setFrameShape(QtWidgets.QFrame.NoFrame)
self.frame_4.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_4.setObjectName("frame_4")
self.verticalLayout_3.addWidget(self.frame_4)
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.verticalLayout_2.addWidget(self.scrollArea)
self.verticalLayout.addWidget(self.frame)
self.frame_2 = QtWidgets.QFrame(self.centralwidget)
self.frame_2.setMaximumSize(QtCore.QSize(500, 50))
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame_2)
self.horizontalLayout.setObjectName("horizontalLayout")
self.pushButton = QtWidgets.QPushButton(self.frame_2)
self.pushButton.setObjectName("pushButton")
self.horizontalLayout.addWidget(self.pushButton)
self.pushButton_2 = QtWidgets.QPushButton(self.frame_2)
self.pushButton_2.setObjectName("pushButton_2")
self.horizontalLayout.addWidget(self.pushButton_2)
self.verticalLayout.addWidget(self.frame_2)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QtWidgets.QApplication.translate("MainWindow", "MainWindow", None, -1))
self.label.setText(QtWidgets.QApplication.translate("MainWindow", "Chose Number", None, -1))
self.pushButton.setText(QtWidgets.QApplication.translate("MainWindow", "add", None, -1))
self.pushButton_2.setText(QtWidgets.QApplication.translate("MainWindow", "remove", None, -1))
class Remove_checkBox(QtWidgets.QMainWindow,
Ui_MainWindow):
def __init__(self,n):
super(Remove_checkBox, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.checkBox = []
self.fill_comboBox(n)
#Signals
self.ui.pushButton.clicked.connect(lambda: self.add_param())
self.ui.pushButton_2.clicked.connect(lambda: self.remove_param())
def fill_comboBox(self,n):
self.comboBox = QtWidgets.QComboBox(self.ui.frame_3)
self.comboBox.addItem("")
self.comboBox.setItemText(0, QtWidgets.QApplication.translate("MainWindow", "", None, -1))
self.ui.horizontalLayout_2.addWidget(self.comboBox)
for i in range(n):
self.comboBox.addItem("")
self.comboBox.setItemText(i+1, QtWidgets.QApplication.translate("MainWindow", str(i), None, -1))
def add_param(self):
num = self.comboBox.currentText()
self.checkBox.append(QtWidgets.QCheckBox(self.ui.scrollAreaWidgetContents))
self.ui.verticalLayout_3.addWidget(self.checkBox[-1])
self.checkBox[-1].setText(QtWidgets.QApplication.translate("MainWindow", num, None, -1))
self.ui.verticalLayout_3.removeWidget(self.ui.frame_4)
self.ui.verticalLayout_3.addWidget(self.ui.frame_4)
def remove_param(self):
for i in range(len(self.checkBox)):
if self.checkBox[i].isChecked():
self.ui.verticalLayout_3.removeWidget(self.checkBox[i])
self.ui.verticalLayout_3.removeWidget(self.ui.frame_4)
self.ui.verticalLayout_3.addWidget(self.ui.frame_4)
if __name__ == "__main__":
n=10
app = QtWidgets.QApplication.instance()
if app == None:
app = QtWidgets.QApplication([])
myApp = Remove_checkBox(n)
myApp.show()
sys.exit(app.exec_())
It took me a while to find a solution that worked with my issue, but I finally arrived to the solution below presented, based on: What is best way to remove items from layout in pyqt
def remove_element(self, support_layout, element_to_remove, control_list_name):
"""
This function aims to remove selected elements that are contained in a
widget.
Parameters
----------
support_layout : QtWigget Layout
Layout that supports the object that will be removed
element_to_remove : list with QtWidget
A list with Qtwidget items that ones whant to remove.
control_list_name : list with strings
A list with Qtwidget added items string name
Returns
-------
None.
"""
for i in reversed(range(support_layout.count()-1)):
if element_to_remove[i].isChecked():
# Remove checkbox from frame
item = support_layout.takeAt(i)
widget = item.widget()
widget.deleteLater()
# Remove list selected items
control_list_name.remove(element_to_remove[i].text())
element_to_remove.remove(element_to_remove[i])
With this function my problem was solved I am able to follow my project.

How to extend the QTreeView in a Grid layout?

I am trying to create a Dialog with a tree view and a web view. Both the views are set as grid layout. The issue is that the treeview cannot be expended once the application is launched. It changes the size with the change in the whole dialog box but when I specifically try to expand the treeview without changing the dialog window size, it doesn't provide me that option. I am using PyQt4 to design the Dialog. Here is the code:
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName(_fromUtf8("Dialog"))
Dialog.resize(511, 393)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(Dialog.sizePolicy().hasHeightForWidth())
Dialog.setSizePolicy(sizePolicy)
Dialog.setWindowTitle(QtGui.QApplication.translate("Dialog", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
self.gridLayout = QtGui.QGridLayout(Dialog)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.verticalLayout = QtGui.QVBoxLayout()
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.listView = QtGui.QListView(Dialog)
self.listView.setObjectName(_fromUtf8("listView"))
self.verticalLayout.addWidget(self.listView)
self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)
self.verticalLayout_2 = QtGui.QVBoxLayout()
self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
self.webView = QtWebKit.QWebView(Dialog)
self.webView.setUrl(QtCore.QUrl(_fromUtf8("about:blank")))
self.webView.setObjectName(_fromUtf8("webView"))
self.verticalLayout_2.addWidget(self.webView)
self.gridLayout.addLayout(self.verticalLayout_2, 0, 1, 1, 1)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
pass
from PyQt4 import QtWebKit
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
Dialog = QtGui.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
Once a widget is inside a layout, generally the layout decides how big the widget will be.
You can influence this by setting the size policy or stretch factors on the widget. See: http://doc.qt.nokia.com/4.7-snapshot/layout.html
If you want to force the widget to have a specific size, use QWidget.setFixedSize.

Categories