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_())
Related
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.
I wrote the following code in order to do some calculations. I want to add a Widget like the small picture such that when I click on pushbutton I can browse a CSV file and that path is shown in a LineEdite. I need to have this Widger in the Experiment Info QGroupBox below the checkBox. But I do not know how to add all these 3 Widget in one row in this group box.
import sys
from PyQt5.QtWidgets import QMainWindow, QAction, QMenu, QApplication
from PyQt5 import QtGui, QtCore
from PyQt5 import QtWidgets
class Application(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
menubar = self.menuBar()
fileMenu = menubar.addMenu('File')
run = menubar.addMenu('Run')
exit = menubar.addMenu('Exit')
impMenu = QMenu('Import', self)
impAct = QAction('Import mail', self)
impMenu.addAction(impAct)
newAct = QAction('New', self)
fileMenu.addAction(newAct)
fileMenu.addMenu(impMenu)
# ------------- Layout ---------------------------
wid =QtWidgets.QWidget(self)
self.setCentralWidget(wid)
mainLayout = QtWidgets.QVBoxLayout()
config_box = QtWidgets.QGroupBox("Configuration")
info_box = QtWidgets.QGroupBox("Info Box")
# ------------- Config Box Layut -----------------
Config_Box_Layout = QtWidgets.QGridLayout()
case_box = QtWidgets.QGroupBox("case")
operations_box = QtWidgets.QGroupBox("Operations")
Config_Box_Layout.addWidget(case_box, 0, 0)
Config_Box_Layout.addWidget(operations_box, 0, 1)
# ----------- Operations-----------------------
operation_layout = QtWidgets.QVBoxLayout()
op1 = QtWidgets.QCheckBox('Add')
op2= QtWidgets.QCheckBox('Multiplication')
operation_layout.addWidget(op1)
operation_layout.addWidget(op2)
# ----------- cases -----------------------
case_layout = QtWidgets.QVBoxLayout()
_1 = QtWidgets.QRadioButton("1")
_2 = QtWidgets.QRadioButton("2")
_3 = QtWidgets.QRadioButton("3")
case_layout.addWidget(_1)
case_layout.addWidget(_2)
case_layout.addWidget(_3)
# --------- Info Box LayOut -----------------------
Info_box_layout = QtWidgets.QVBoxLayout()
exp_input_grou = QtWidgets.QGroupBox('Experiment Info')
exp_input_layout = QtWidgets.QVBoxLayout()
version_input = QtWidgets.QComboBox()
version_input.addItem("Algo Version")
version_input.addItem("V53")
version_input.addItem("V52")
version_input.addItem("V4")
version_input.addItem("V3")
nested_folder = QtWidgets.QCheckBox('Nested Data Path')
dialog_file = QtWidgets.QFileDialog()
pushB_ = QtWidgets.QPushButton('Browse')
exp_input_layout.addWidget(version_input)
exp_input_layout.addWidget(nested_folder)
exp_input_layout.addWidget(pushB_)
exp_input_layout.addWidget(dialog_file)
exp_report = QtWidgets.QTextEdit()
progres_bar = QtWidgets.QProgressBar()
Info_box_layout.addWidget(exp_input_grou)
Info_box_layout.addWidget(exp_report)
Info_box_layout.addWidget(progres_bar)
gt_path = QtWidgets.QLineEdit()
gt_path.setFixedWidth(100)
# -------- Adding Layouts ------------------------
mainLayout.addWidget(config_box)
config_box.setLayout(Config_Box_Layout)
case_box.setLayout(case_layout)
operations_box.setLayout(operation_layout)
info_box.setLayout(Info_box_layout)
exp_input_grou.setLayout(exp_input_layout)
mainLayout.addWidget(info_box)
wid.setLayout(mainLayout)
self.setGeometry(300, 300, 300, 700)
self.setWindowTitle('Example')
app_icon = QtGui.QIcon()
app_icon.addFile('pic.jpg', QtCore.QSize(256, 256))
self.setWindowIcon(app_icon)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Application()
sys.exit(app.exec_())
If you want to add widgets horizontally in a vertical layout, you have to add an horizontal layout to it. This technique is generally referred to as "nested layouts".
Then, you don't have to create a file dialog instance within the init (otherwise it will be probably shown along with the main window), and you don't have to use the QFileDialog() constructor for your needs, since QDialog already provides static methods that easily allow you to open a standard dialog and get the selected file(s) or directory.
class Application(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
# ...
# --------- Info Box LayOut -----------------------
Info_box_layout = QtWidgets.QVBoxLayout()
exp_input_grou = QtWidgets.QGroupBox('Experiment Info')
exp_input_layout = QtWidgets.QVBoxLayout()
version_input = QtWidgets.QComboBox()
version_input.addItem("Algo Version")
version_input.addItem("V53")
version_input.addItem("V52")
version_input.addItem("V4")
version_input.addItem("V3")
nested_folder = QtWidgets.QCheckBox('Nested Data Path')
# This should not be here!!!
# dialog_file = QtWidgets.QFileDialog()
exp_input_layout.addWidget(version_input)
exp_input_layout.addWidget(nested_folder)
browse_layout = QtWidgets.QHBoxLayout()
exp_input_layout.addLayout(browse_layout)
self.gt_path = QtWidgets.QLineEdit()
pushB_ = QtWidgets.QPushButton('Browse')
pushB_.clicked.connect(self.browse_path)
browse_layout.addWidget(self.gt_path)
browse_layout.addWidget(pushB_)
# ...
def browse_path(self):
path, filter = QtWidgets.QFileDialog.getOpenFileName(self, 'Select file',
'', 'CSV files (*.csv);;All files (*)')
if path:
self.gt_path.setText(path)
QGridLayout is also a valid alternative, but it doesn't work fine with everything, as its sizes are always dependent on the size of widgets each row or column contains. Your case is very simple, so it can be used without problems:
def initUI(self):
# ...
# --------- Info Box LayOut -----------------------
Info_box_layout = QtWidgets.QVBoxLayout()
exp_input_grou = QtWidgets.QGroupBox('Experiment Info')
exp_input_layout = QtWidgets.QGridLayout()
version_input = QtWidgets.QComboBox()
version_input.addItem("Algo Version")
version_input.addItem("V53")
version_input.addItem("V52")
version_input.addItem("V4")
version_input.addItem("V3")
nested_folder = QtWidgets.QCheckBox('Nested Data Path')
self.gt_path = QtWidgets.QLineEdit()
pushB_ = QtWidgets.QPushButton('Browse')
pushB_.clicked.connect(self.browse_path)
# add the combobox to the first row, first column, but set its column
# span to 2, meaning that it occupies two "columns"
exp_input_layout.addWidget(version_input, 0, 0, 1, 2)
# the same for the checkbox, but on the second row
exp_input_layout.addWidget(nested_folder, 1, 0, 1, 2)
# add the line edit, third row, first column; if you don't specify the
# span, the widget will only occupy one "cell" of the grid layout
exp_input_layout.addWidget(self.gt_path, 2, 0)
# and the button, same row, second column
exp_input_layout.addWidget(pushB_, 2, 1)
# ...
The below code will do what you want, you just need to implement it into your code:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(387, 224)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setObjectName("lineEdit")
self.lineEdit.setReadOnly(True)
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setObjectName("label")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setObjectName("pushButton")
self.pushButton.clicked.connect(self.open_file)
self.gridLayout.addWidget(self.lineEdit, 0, 1, 1, 1)
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
self.gridLayout.addWidget(self.pushButton, 0, 2, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 387, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "Select output file"))
self.pushButton.setText(_translate("MainWindow", "..."))
def open_file(self):
self.file_name = QtWidgets.QFileDialog.getOpenFileName(None, "Open", "", "CSV Files (*.csv)")
if self.file_name[0] != '':
self.lineEdit.setText(self.file_name[0])
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_())
Output:
For example When I open the app to show me one form, when I click the button show second form that will contain the data entry fields
Home
Second form
There are several ways to achieve what you want. Easiest (not cleanest) is to group the widgets in your "forms" into containers (QFrame, QGroupbox, etc) and connect the triggered signal from your actions into suitable slots that hide/show these containers. Below you can see an example (PySide) of this, on which I'm using two QFrames in order to separate your "forms". The layout behaviour can be modified easily.
The form file (compiled from the designer's ui file):
# Form implementation generated from reading ui file 'example.ui'
#
# Created: Tue Apr 10 13:18:07 2018
# by: pyside-uic 0.2.15 running on PySide 1.2.4
#
# WARNING! All changes made in this file will be lost!
from PySide import QtCore, QtGui
class Ui_Example(object):
def setupUi(self, Example):
Example.setObjectName("Example")
Example.resize(800, 770)
self.centralwidget = QtGui.QWidget(Example)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtGui.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.fr_one = QtGui.QFrame(self.centralwidget)
self.fr_one.setFrameShape(QtGui.QFrame.StyledPanel)
self.fr_one.setFrameShadow(QtGui.QFrame.Raised)
self.fr_one.setObjectName("fr_one")
self.verticalLayout_2 = QtGui.QVBoxLayout(self.fr_one)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.bt_quit = QtGui.QPushButton(self.fr_one)
self.bt_quit.setObjectName("bt_quit")
self.verticalLayout_2.addWidget(self.bt_quit)
self.cb_selection = QtGui.QComboBox(self.fr_one)
self.cb_selection.setObjectName("cb_selection")
self.verticalLayout_2.addWidget(self.cb_selection)
spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout_2.addItem(spacerItem)
self.gridLayout.addWidget(self.fr_one, 0, 0, 1, 1)
self.fr_two = QtGui.QFrame(self.centralwidget)
self.fr_two.setFrameShape(QtGui.QFrame.StyledPanel)
self.fr_two.setFrameShadow(QtGui.QFrame.Raised)
self.fr_two.setObjectName("fr_two")
self.verticalLayout_5 = QtGui.QVBoxLayout(self.fr_two)
self.verticalLayout_5.setObjectName("verticalLayout_5")
self.verticalLayout = QtGui.QVBoxLayout()
self.verticalLayout.setSpacing(0)
self.verticalLayout.setObjectName("verticalLayout")
self.label = QtGui.QLabel(self.fr_two)
self.label.setObjectName("label")
self.verticalLayout.addWidget(self.label)
self.le_fname = QtGui.QLineEdit(self.fr_two)
self.le_fname.setObjectName("le_fname")
self.verticalLayout.addWidget(self.le_fname)
self.verticalLayout_5.addLayout(self.verticalLayout)
self.verticalLayout_3 = QtGui.QVBoxLayout()
self.verticalLayout_3.setSpacing(0)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.label_2 = QtGui.QLabel(self.fr_two)
self.label_2.setObjectName("label_2")
self.verticalLayout_3.addWidget(self.label_2)
self.le_sname = QtGui.QLineEdit(self.fr_two)
self.le_sname.setObjectName("le_sname")
self.verticalLayout_3.addWidget(self.le_sname)
self.verticalLayout_5.addLayout(self.verticalLayout_3)
self.verticalLayout_4 = QtGui.QVBoxLayout()
self.verticalLayout_4.setSpacing(0)
self.verticalLayout_4.setObjectName("verticalLayout_4")
self.label_3 = QtGui.QLabel(self.fr_two)
self.label_3.setObjectName("label_3")
self.verticalLayout_4.addWidget(self.label_3)
self.le_address = QtGui.QLineEdit(self.fr_two)
self.le_address.setObjectName("le_address")
self.verticalLayout_4.addWidget(self.le_address)
self.verticalLayout_5.addLayout(self.verticalLayout_4)
spacerItem1 = QtGui.QSpacerItem(20, 267, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout_5.addItem(spacerItem1)
self.gridLayout.addWidget(self.fr_two, 0, 1, 1, 1)
Example.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(Example)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 47))
self.menubar.setObjectName("menubar")
Example.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(Example)
self.statusbar.setObjectName("statusbar")
Example.setStatusBar(self.statusbar)
self.toolBar = QtGui.QToolBar(Example)
self.toolBar.setObjectName("toolBar")
Example.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
self.actionAction1 = QtGui.QAction(Example)
self.actionAction1.setObjectName("actionAction1")
self.actionAction2 = QtGui.QAction(Example)
self.actionAction2.setObjectName("actionAction2")
self.toolBar.addAction(self.actionAction1)
self.toolBar.addAction(self.actionAction2)
self.retranslateUi(Example)
QtCore.QMetaObject.connectSlotsByName(Example)
def retranslateUi(self, Example):
Example.setWindowTitle(QtGui.QApplication.translate("Example", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
self.bt_quit.setText(QtGui.QApplication.translate("Example", "Quit", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("Example", "First name", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("Example", "Second name", None, QtGui.QApplication.UnicodeUTF8))
self.label_3.setText(QtGui.QApplication.translate("Example", "Address", None, QtGui.QApplication.UnicodeUTF8))
self.toolBar.setWindowTitle(QtGui.QApplication.translate("Example", "toolBar", None, QtGui.QApplication.UnicodeUTF8))
self.actionAction1.setText(QtGui.QApplication.translate("Example", "action1", None, QtGui.QApplication.UnicodeUTF8))
self.actionAction2.setText(QtGui.QApplication.translate("Example", "action2", None, QtGui.QApplication.UnicodeUTF8))
The main file:
from PySide import QtGui, QtCore
from _example import Ui_Example
class Example(QtGui.QMainWindow):
def __init__(self, parent = None):
super(Example, self).__init__(parent)
self.ui = Ui_Example()
self.ui.setupUi(self)
self.ui.fr_two.setVisible(False)
self.ui.cb_selection.addItem("motif")
# here are the connections of the corresponding actions on the QToolBar
self.ui.actionAction1.triggered.connect(self._changeView1)
self.ui.actionAction2.triggered.connect(self._changeView2)
def _changeView1(self):
# fr_one is the first frame (the one that contains the 'quit' button and the QCombobox)
# fr_two is the second frame (the one that contains the QLineEdits)
self.ui.fr_one.setVisible(True)
self.ui.fr_two.setVisible(False)
def _changeView2(self):
self.ui.fr_one.setVisible(False)
self.ui.fr_two.setVisible(True)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
ex = Example()
ex.show()
app.exec_()
I am trying to design a list of items each of which is a custom widget (not necessarily though, I want to display an image and three texts in each item).
In PyQt, the function addItem can be used to add an item to the list that takes as argument QListWidgetItem.
As such, I was trying to cast my custom defined widget to QListWidetItem with no success. I tried the following chunk of code:
listWidget = QtWidgets.QListWidget(self.centralwidget)
item = QListWidgetItem(self.listWidget)
custom_item = CustomWidget()
listWidget.addItem(item)
listWidget.setItemWidget(item, item_widget)
The list displays an empty list, and this is expected since I am never inflating the custom_item with the above code. How to fix this in PyQT?
I am not sure, but the custom widget might be relevant:
class CustomWidget(QWidget):
def __init__(self, user):
QWidget.__init__(self)
self.user = user
self.horizontalLayoutWidget = QtWidgets.QWidget()
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(0, 0, 211, 41))
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.UserImage = QtWidgets.QLabel(self.horizontalLayoutWidget)
self.UserImage.setText("This is an Image")
self.UserImage.setObjectName("UserImage")
self.horizontalLayout.addWidget(self.UserImage)
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.UserName = QtWidgets.QLabel(self.horizontalLayoutWidget)
self.UserName.setText("My name is jeff")
self.UserName.setObjectName("UserName")
self.verticalLayout.addWidget(self.UserName)
self.UserStatus = QtWidgets.QLabel(self.horizontalLayoutWidget)
self.UserStatus.setText("I am available")
self.UserStatus.setObjectName("UserStatus")
self.verticalLayout.addWidget(self.UserStatus)
self.horizontalLayout.addLayout(self.verticalLayout)
self.horizontalLayout.setStretch(0, 1)
self.horizontalLayout.setStretch(1, 3)
What I notice from your code is that the widget is not built correctly, self.horizontalLayout is the main widget but it has no parent so it will never be drawn, besides that you can avoid that widget. On the other hand, you must set the size of the item with setSizeHint():
from PyQt5 import QtWidgets, QtCore
class CustomWidget(QtWidgets.QWidget):
def __init__(self, user, *args, **kwargs):
QtWidgets.QWidget.__init__(self, *args, **kwargs)
self.user = user
self.setGeometry(QtCore.QRect(0, 0, 211, 41))
self.horizontalLayout = QtWidgets.QHBoxLayout(self)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.UserImage = QtWidgets.QLabel(self)
self.UserImage.setText("This is an Image")
self.UserImage.setObjectName("UserImage")
self.horizontalLayout.addWidget(self.UserImage)
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.UserName = QtWidgets.QLabel(self)
self.UserName.setText("My name is jeff")
self.UserName.setObjectName("UserName")
self.verticalLayout.addWidget(self.UserName)
self.UserStatus = QtWidgets.QLabel(self)
self.UserStatus.setText("I am available")
self.UserStatus.setObjectName("UserStatus")
self.verticalLayout.addWidget(self.UserStatus)
self.horizontalLayout.addLayout(self.verticalLayout)
self.horizontalLayout.setStretch(0, 1)
self.horizontalLayout.setStretch(1, 3)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
listWidget = QtWidgets.QListWidget()
item = QtWidgets.QListWidgetItem(listWidget)
item_widget = CustomWidget("user")
listWidget.addItem(item)
listWidget.setItemWidget(item, item_widget)
item.setSizeHint(item_widget.sizeHint())
listWidget.show()
sys.exit(app.exec_())
Why i can't receive self.sender() output? My point is to identify which button is clicked (to start a download function) and then match the corresponding progress bar for a downloading indicator.
The error output is:
Traceback (most recent call last):
File "final.py", line 308, in buttonClicked
buttonHandle = self.sender()
AttributeError: 'Ui_MainWindow' object has no attribute 'sender'
thnx a lot.
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.setGeometry(600,300,727,455)
MainWindow.setMinimumSize(QtCore.QSize(727, 455))
#MainWindow.setMaximumSize(QtCore.QSize(727, 455))
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 727, 23))
self.menubar.setObjectName(_fromUtf8("menubar"))
self.menuFile = QtGui.QMenu(self.menubar)
self.menuFile.setObjectName(_fromUtf8("menuFile"))
self.menuAbout = QtGui.QMenu(self.menubar)
self.menuAbout.setObjectName(_fromUtf8("menuAbout"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.actionExit = QtGui.QAction(MainWindow)
self.actionExit.setObjectName(_fromUtf8("actionExit"))
self.actionPythAri = QtGui.QAction(MainWindow)
self.actionPythAri.setObjectName(_fromUtf8("actionPythAri"))
self.menuFile.addAction(self.actionExit)
self.menuAbout.addAction(self.actionPythAri)
self.menubar.addAction(self.menuFile.menuAction())
self.menubar.addAction(self.menuAbout.menuAction())
# scrollArea
self.mainLayout = QtGui.QVBoxLayout()
self.scrollArea = QtGui.QScrollArea()
self.scrollArea.setWidgetResizable(True)
self.scrollAreaLayout = QtGui.QVBoxLayout()
#groupBoxes
self.groupBoxes = QtGui.QWidget()
self.groupBoxesLayout = QtGui.QVBoxLayout()
self.groupBoxes.setLayout(self.groupBoxesLayout)
self.groupBoxesLayout.setContentsMargins(5,5,5,5)
for i in range(3):
groupBox = QtGui.QGroupBox(_fromUtf8('Issue #%d' %i))
groupLayout = QtGui.QVBoxLayout()
#groupEllements
self.groupBoxUpWidget = QtGui.QWidget()
self.groupBoxUpLayout = QtGui.QHBoxLayout()
self.groupBoxDownWidget = QtGui.QWidget()
self.groupBoxDownLayout = QtGui.QHBoxLayout()
self.groupBoxUpWidget.setLayout(self.groupBoxUpLayout)
self.groupBoxDownWidget.setLayout(self.groupBoxDownLayout)
#mainwidget-temp
self.groupBoxMainWidget = QtGui.QWidget()
self.groupBoxMainLayout = QtGui.QVBoxLayout()
self.groupBoxMainWidget.setLayout(self.groupBoxMainLayout)
# ISSUE THUMB
self.issueThumb(self.groupBoxUpLayout)
#SETTING MAIN LAYOUT FOR EVERY GROUPBOX
groupBox.setLayout(groupLayout)
# text box
#self.txtLayout = QtGui.QHBoxLayout()
txt = QtGui.QLabel()
txt.setMaximumWidth(500)
txt.setText(_fromUtf8('Issue Description'))
#self.txtLayout.addWidget(self.txt)
#self.txt.setLayout(self.txtLayout)
#progressBars
progressBar = QtGui.QProgressBar()
progressBar.setMaximumWidth(500)
# controls
readBtn = QtGui.QPushButton(_fromUtf8('Read it!'),groupBox)
readBtn.setMaximumWidth(100)
#readBtn.setText()
readBtn.clicked.connect(self.buttonClicked)
# ADD EVERY WIDGET TO THE APPROPRIATE LAYOUT
self.groupBoxUpLayout.addWidget(txt)
self.groupBoxDownLayout.addWidget(readBtn)
self.groupBoxDownLayout.addWidget(progressBar)
# ADD PARENT WIDGETS TO MAIN GROUPBOX LAYOUT
groupLayout.addWidget(self.groupBoxUpWidget)
groupLayout.addWidget(self.groupBoxDownWidget)
groupLayout.addWidget(self.groupBoxMainWidget)
#ADD EVERY GROUPBOX TO A MAIN LAYOUT
self.groupBoxesLayout.addWidget(groupBox)
#self.scrollArea.setLayout(self.scrollAreaLayout)
self.scrollArea.setWidget(self.groupBoxes)
self.mainLayout.addWidget(self.scrollArea)
self.centralwidget.setLayout(self.mainLayout)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
authenticatedUser = False
authenticatedUser = self.authenticateDialog()
print authenticatedUser
if authenticatedUser == False:
sys.exit(0)
def buttonClicked(self):
buttonHandle = self.sender()
print buttonHandle
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui2 = Ui_MainWindow()
ui2.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
def buttonClicked(self):
buttonHandle = self.sender()
print buttonHandle
self here would be the Ui_MainWindow which is not a QT object, you probably want to check .sender of MainWindow. so set a class variable of UI_MainWindow to the MainWindow object and check sender of that object.
def setupUi(self, MainWindow):
self.MainWindow = MainWindow
....
def buttonClicked(self):
buttonHandle = self.MainWindow.sender()
print buttonHandle