How do i Acess Items that i created with Qt Designer? - python

that may be an easy Question for many, however i still struggle with acessing Items that i created in QT Designer.
I created a simple GUI that shows a 16x5 Table with QT Designer and converted the .ui to a .py file.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(686, 539)
self.widget = QtWidgets.QWidget(Form)
self.widget.setGeometry(QtCore.QRect(10, 60, 258, 223))
self.widget.setObjectName("widget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.widget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.tableWidget = QtWidgets.QTableWidget(self.widget)
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(4)
self.tableWidget.setRowCount(4)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(3, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(3, item)
self.verticalLayout.addWidget(self.tableWidget)
self.pushButton = QtWidgets.QPushButton(self.widget)
self.pushButton.setObjectName("pushButton")
self.verticalLayout.addWidget(self.pushButton)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
item = self.tableWidget.verticalHeaderItem(0)
item.setText(_translate("Form", "1"))
item = self.tableWidget.verticalHeaderItem(1)
item.setText(_translate("Form", "2"))
item = self.tableWidget.verticalHeaderItem(2)
item.setText(_translate("Form", "3"))
item = self.tableWidget.verticalHeaderItem(3)
item.setText(_translate("Form", "4"))
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("Form", "A"))
item = self.tableWidget.horizontalHeaderItem(1)
item.setText(_translate("Form", "B"))
item = self.tableWidget.horizontalHeaderItem(2)
item.setText(_translate("Form", "C"))
item = self.tableWidget.horizontalHeaderItem(3)
item.setText(_translate("Form", "D"))
At first i tried to Code within the file that was generated but thanks to User:musicamante, which commented on my Last Question, i threw away that idea.
Now i just load the file like that.
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QTableWidgetItem
import sys
from GUI import Ui_Form
class ExampleApp(QtWidgets.QWidget, Ui_Form):
def __init__(self, parent=None):
super(ExampleApp, self).__init__(parent)
self.setupUi(self)
def update_now():
#Store some Measurement Values
WriteDatatoTable()
def WriteDatatoTable():
**Test=Ui_Form()**
**Test.tableWidget.setItem(0,1, QTableWidgetItem("123")**
def main():
app = QApplication(sys.argv)
form = ExampleApp()
timer=QtCore.QTimer()
timer.timeout.connect(update_now)
timer.start(1000)
form.show()
app.exec_()
if __name__ == '__main__':
main()
I just want to print the Data to my GUI Table. But when i tried my approach i get the Error that Ui_Form does not have a attribute called "tableWidget". Besides knowing why that Error occurs, i sadly have no idea how to fix that. Or am i completly wrong with my idea?
I hope anyone can help.

You should make it that your functions are methods of the ExampleApp class and make it the connections of what is about an "UI class" inside that class. This down here should work. Maybe this is not the best way, but this is how I would do it. I hope it helps you.
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QTableWidgetItem
import sys
from GUI import Ui_Form
class ExampleApp(QtWidgets.QWidget, Ui_Form):
def __init__(self, parent=None):
super(ExampleApp, self).__init__(parent)
self.setupUi(self)
self.timer = QtCore.QTimer()
self._connect()
self.timer.start(1000)
def _connect(self):
self.timer.timeout.connect(self.update_now)
def update_now(self):
self.writeDataToTable()
def writeDataToTable(self):
self.tableWidget.setItem(0, 1, QTableWidgetItem("123"))
def main():
app = QApplication(sys.argv)
form = ExampleApp()
form.show()
app.exec_()
if __name__ == '__main__':
main()

Related

How to get selected items from QComboBox to be displayed in QTableWidget in PyQt5? (QComboBox has checkbox to pick items)

I have QTableWidget in which I have QComboBox in each row for particular column. My each QCombobox has multiple values with checkboxes. I want to display selected item/s from each combobox in the next respective column 'SelectedMonths' in the same row and remove them when unchecked (Vice-versa).
Until now I have Script ready which gives me what all items have been checked/unchecked but I dont know how to get the index of the row for which combobox is activated.
Snippet to get the workflow
Sample Code:
Code Generated by QtDesigner: Demo.py
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(464, 291)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setGeometry(QtCore.QRect(30, 30, 411, 221))
self.tableWidget.setRowCount(1)
self.tableWidget.setColumnCount(2)
self.tableWidget.setObjectName("tableWidget")
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(0, 0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(0, 1, item)
self.tableWidget.horizontalHeader().setVisible(False)
self.tableWidget.verticalHeader().setVisible(False)
MainWindow.setCentralWidget(self.centralwidget)
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"))
__sortingEnabled = self.tableWidget.isSortingEnabled()
self.tableWidget.setSortingEnabled(False)
item = self.tableWidget.item(0, 0)
item.setText(_translate("MainWindow", "Select Months"))
item = self.tableWidget.item(0, 1)
item.setText(_translate("MainWindow", "Selected Months"))
self.tableWidget.setSortingEnabled(__sortingEnabled)
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_())
Code which I have written: DemoCode.py
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtWidgets import QTableWidgetItem
from PyQt5.QtGui import QStandardItem, QStandardItemModel
from PyQt5.QtCore import Qt
from datetime import date
from dateutil.relativedelta import relativedelta
from Demo import Ui_MainWindow
def CheckableCombobox(combo, options):
model = QStandardItemModel(len(options), 1)
firstItem = QtGui.QStandardItem("SelectMonths")
firstItem.setBackground(QtGui.QBrush(QtGui.QColor(200, 200, 200)))
firstItem.setSelectable(False)
model.setItem(0, 0, firstItem)
for i, area in enumerate(options):
item = QStandardItem(area)
item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
item.setData(Qt.Unchecked, Qt.CheckStateRole)
model.setItem(i+1, 0, item)
combo.setModel(model)
class DemoCode(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super(DemoCode, self).__init__()
self.setupUi(self)
self.rowPosition = self.tableWidget.rowCount()
for row in range(0,3):
self.tableWidget.insertRow(self.rowPosition)
for column in range(0,2):
if column == 0:
self.ComboBox = QtWidgets.QComboBox()
dtStart = date.today()
self.Monthlist = []
for n in range(1, 5):
self.Monthlist.append((dtStart + relativedelta(months=-n)).strftime('1-%b-%Y'))
CheckableCombobox(self.ComboBox, self.Monthlist)
self.ComboBox.model().itemChanged.connect(self.on_itemChanged)
self.tableWidget.setCellWidget(self.rowPosition, column, self.ComboBox)
elif column == 1:
item = QTableWidgetItem('')
self.tableWidget.setItem(self.rowPosition, column, item)
self.rowPosition += 1
self.tableWidget.setColumnWidth(1,150)
def on_itemChanged(self, item):
current_state = item.data(Qt.CheckStateRole)
print(current_state, item.text())
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
window = DemoCode()
window.show()
sys.exit(app.exec_())
You should find a way to keep track of the row for each combo model, so that you can set the item text accordingly.
Note that I changed your code logic a bit, as there were some conceptual mistakes:
don't set instance attributes if they are not required: all those self.rowPosition, self.monthList, etc, change everytime the for loop cycles, and you don't need them after that;
avoid using uppercase names for variables and functions
the month list is always the same, build it before the for cycle instead of computing it each time
instead of setting the model to the combo in the function, make it return the model
Edit: added copy function after comment request
def createModel(options):
model = QStandardItemModel(len(options), 1)
firstItem = QtGui.QStandardItem("SelectMonths")
firstItem.setBackground(QtGui.QBrush(QtGui.QColor(200, 200, 200)))
firstItem.setSelectable(False)
model.setItem(0, 0, firstItem)
for i, area in enumerate(options):
item = QStandardItem(area)
item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
item.setData(Qt.Unchecked, Qt.CheckStateRole)
model.setItem(i+1, 0, item)
return model
class DemoCode(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super(DemoCode, self).__init__()
self.setupUi(self)
monthList = [(date.today() + relativedelta(months=-n)).strftime('1-%b-%Y') for n in range(1, 5)]
self.models = {}
rows = self.tableWidget.rowCount()
for row in range(rows, rows + 3):
self.tableWidget.insertRow(row)
comboBox = QtWidgets.QComboBox()
model = createModel(monthList)
comboBox.setModel(model)
model.itemChanged.connect(lambda _, row=row: self.on_itemChanged(row))
self.models[row] = model
self.tableWidget.setCellWidget(row, 0, comboBox)
item = QTableWidgetItem()
self.tableWidget.setItem(row, 1, item)
self.tableWidget.setColumnWidth(1,150)
def on_itemChanged(self, tableRow):
model = self.models[tableRow]
items = []
for row in range(model.rowCount()):
comboItem = model.index(row, 0)
if comboItem.data(Qt.CheckStateRole):
items.append(comboItem.data())
self.tableWidget.item(tableRow, 1).setText(', '.join(items))
def copyFromRow(self, tableRow):
sourceModel = self.models[tableRow]
checkedRows = []
for row in range(sourceModel.rowCount()):
if sourceModel.index(row, 0).data(Qt.CheckStateRole):
checkedRows.append(row)
for model in self.models.values():
if model == sourceModel:
continue
for row in range(model.rowCount()):
model.setData(
model.index(row, 0),
Qt.Checked if row in checkedRows else Qt.Unchecked,
Qt.CheckStateRole)
I'd also suggest to remove the "Select Months" and "Selected Months" items, and use them as table headers.

PyQt5 Selecting a row after insert

Using PyQt5 with a QTableView, QStandardItemModel and QSortFilterProxy. After doing an insertRow on the model the Sort Proxy displays the data in the View Table in the correct sort order; however, I need to issue a view.selectRow on the record that was just inserted. Not sure how to do this if the ItemModel stores the data in unsorted order.
Similar but shorter example:
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import Qt, QSortFilterProxyModel
from PyQt5.QtGui import QStandardItemModel, QStandardItem
from PyQt5.QtWidgets import QWidget, QInputDialog
class Ui_Dialog(QWidget):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(282, 247)
self.tableView = QtWidgets.QTableView(Dialog)
self.tableView.setGeometry(QtCore.QRect(10, 10, 256, 192))
self.tableView.setObjectName("tableView")
self.tableModel = QStandardItemModel()
self.tableModel.setColumnCount(1)
self.tableModel.setHeaderData(0, Qt.Horizontal, "Category Name")
self.tableProxy = QSortFilterProxyModel()
self.tableProxy.setSourceModel(self.tableModel)
self.tableView.setModel(self.tableProxy)
self.tableProxy.setSortCaseSensitivity(Qt.CaseInsensitive)
self.pushButton = QtWidgets.QPushButton(Dialog)
self.pushButton.setGeometry(QtCore.QRect(90, 210, 87, 29))
self.pushButton.setObjectName("pushButton")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
self.setup_connections()
self.load_data()
self.tableProxy.sort(0)
self.tableView.selectRow(0)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.pushButton.setText(_translate("Dialog", "New"))
def setup_connections(self):
self.pushButton.clicked.connect(self.add_record)
def load_data(self):
data = ('Alpha', 'Charlie', 'Foxtrot', 'Zulu', 'Bravo', 'Tango')
for ndx, val in enumerate(data):
print(ndx, val)
item = QStandardItem(val)
self.tableModel.insertRow(ndx, item)
def add_record(self):
i, ok = QInputDialog.getText(self, "Value Editor", "Emter A Value:")
if ok:
item = QStandardItem(i)
self.tableModel.insertRow(self.tableModel.rowCount(), item)
### NEED TO TRIGGER TABLE TO SELECT THE ROW JUST INSERTED ###
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
To select an item you must use the selectionModel() of the view, you have to pass the index of the model passed to the view, that is, the proxy, and the flag of the selection type. To obtain the index of the proxy you must first obtain the index of the sourceModel, for this you use indexFromItem() converting the QStandardItem to QModelIndex, and then use mapFromSource() to convert from the source to the proxy:
from PyQt5 import QtCore, QtGui, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.tableView = QtWidgets.QTableView()
self.tableModel = QtGui.QStandardItemModel()
self.tableModel.setColumnCount(1)
self.tableModel.setHeaderData(0, QtCore.Qt.Horizontal, "Category Name")
self.tableProxy = QtCore.QSortFilterProxyModel()
self.tableProxy.setSourceModel(self.tableModel)
self.tableView.setModel(self.tableProxy)
self.tableProxy.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.pushButton = QtWidgets.QPushButton("New")
self.setup_connections()
self.load_data()
self.tableProxy.sort(0)
self.tableView.selectRow(0)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.tableView)
lay.addWidget(self.pushButton)
def setup_connections(self):
self.pushButton.clicked.connect(self.add_record)
def load_data(self):
data = ('Alpha', 'Charlie', 'Foxtrot', 'Zulu', 'Bravo', 'Tango')
for ndx, val in enumerate(data):
item = QtGui.QStandardItem(val)
self.tableModel.insertRow(ndx, item)
#QtCore.pyqtSlot()
def add_record(self):
i, ok = QtWidgets.QInputDialog.getText(self, "Value Editor", "Emter A Value:")
if ok:
item = QtGui.QStandardItem(i)
self.tableModel.insertRow(self.tableModel.rowCount(), item)
ix = self.tableModel.indexFromItem(item)
ix_proxy = self.tableProxy.mapFromSource(ix)
self.tableView.selectionModel().select(ix_proxy, QtCore.QItemSelectionModel.ClearAndSelect)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())

Using Pyqt Print support but getting error "Object is not callable"

I am new to python and I am learning from different resources
I am trying to use PYQT5 print support but I am getting error, I try my best to solve this problem from google but i found no solution so I am asking this question here please
below is my code
from PyQt5 import QtCore, QtGui, QtWidgets ,QtPrintSupport
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(615, 356)
self.frame = QtWidgets.QFrame(Form)
self.frame.setGeometry(QtCore.QRect(10, 10, 571, 301))
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.textEdit = QtWidgets.QTextEdit(self.frame)
self.textEdit.setGeometry(QtCore.QRect(100, 10, 331, 71))
self.textEdit.setObjectName("textEdit")
self.tableWidget = QtWidgets.QTableWidget(self.frame)
self.tableWidget.setGeometry(QtCore.QRect(30, 90, 521, 121))
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(3)
self.tableWidget.setRowCount(3)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(2, item)
self.pushButton = QtWidgets.QPushButton(self.frame)
self.pushButton.setGeometry(QtCore.QRect(240, 250, 91, 41))
self.pushButton.setObjectName("pushButton")
self.pushButton.clicked.connect(self.print)
item.setText(_translate("Form", "New Column"))
self.pushButton.setText(_translate("Form", "Print"))
def print (self):
dialog = QtPrintSupport.QPrintDialog()
if dialog.exec_() == QtWidgets.QDialog.Accepted:
self.frame().print_(dialog.printer())
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
ui = Ui_Form()
ui.setupUi(Form)
Form.show()
sys.exit(app.exec_())
and i am getting this error
File "print.py", line 74, in print
self.frame().print_(dialog.printer())
TypeError: 'QFrame' object is not callable
please tell me the solution as I am new in python
Thanks in advance
Your code has several problems:
An object is not callable, so you should not use (), a class if it is.
A QFrame does not have the print_ method, only QTextEdit and some classes have it, in the general case you should use QPainter.
The class that provides Qt Designer is not a widget so I recommend you not to modify it or implement the logic there since you will have several problems, it is best to create a class that inherits the appropriate widget according to the template and use the class of Qt Designer to fill it
Considering the above, the solution is as follows:
from PyQt5 import QtCore, QtGui, QtWidgets, QtPrintSupport
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(615, 356)
self.frame = QtWidgets.QFrame(Form)
self.frame.setGeometry(QtCore.QRect(10, 10, 571, 301))
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.textEdit = QtWidgets.QTextEdit(self.frame)
self.textEdit.setGeometry(QtCore.QRect(100, 10, 331, 71))
self.textEdit.setObjectName("textEdit")
self.tableWidget = QtWidgets.QTableWidget(self.frame)
self.tableWidget.setGeometry(QtCore.QRect(30, 90, 521, 121))
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(3)
self.tableWidget.setRowCount(3)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(2, item)
self.pushButton = QtWidgets.QPushButton(self.frame)
self.pushButton.setGeometry(QtCore.QRect(240, 250, 91, 41))
self.pushButton.setObjectName("pushButton")
self.pushButton.setText("Print")
class Widget(QtWidgets.QWidget, Ui_Form):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.setupUi(self)
self.pushButton.clicked.connect(self.print)
def print(self):
printer = QtPrintSupport.QPrinter()
printer.setOutputFormat(QtPrintSupport.QPrinter.PdfFormat)
printer.setPageMargins(12, 16, 12, 20, QtPrintSupport.QPrinter.Millimeter)
printer.setFullPage(False)
dialog = QtPrintSupport.QPrintDialog(printer, self)
if dialog.exec_() == QtWidgets.QDialog.Accepted:
painter = QtGui.QPainter(dialog.printer())
xscale = printer.pageRect().width() /float(w.width())
yscale = printer.pageRect().height() /float(w.height())
scale = min(xscale, yscale)
painter.translate(printer.paperRect().center())
painter.scale(scale, scale)
painter.translate(-w.width()/ 2, -w.height()/ 2)
self.frame.render(painter)
painter.end()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())

PyQt5 How to identify and grab data from a QT combobox that has been created along with other combobox using a function

I wrote a script that automatically creates a QT "object" made up of a category label, a combobox_1 with possible attributes, a push button and a combobox_2 to list all values available for the attribute selected. the script creates as many of these "objects" as necessary.
For each "object" the push button created is meant to grab the selected attribute in combobox_1 and use this information to retrieve relevant values from the database and populate combobx_2
Now the problem I have is that I can't figure out how to reference the comboboxes once they have been created. For the buttons, I use the serve function which listen to any button for a click so that's fine, but how can I reference combobox that have been created with a function. Although they all have different setObjectName, there doesn't seem to be a way of referencing that attribute so when I click on any button they all return the value of the last object's combobox instead of the value of its related comboxbox to which they are attached.
here is the Frontend script:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(709, 357)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout_2 = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout_2.setObjectName("gridLayout_2")
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.gridLayout_4 = QtWidgets.QGridLayout()
self.gridLayout_4.setObjectName("gridLayout_4")
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout_4.addItem(spacerItem, 1, 1, 1, 1)
self.VLayout_0 = QtWidgets.QVBoxLayout()
self.VLayout_0.setObjectName("VLayout_0")
self.HLayout_0 = QtWidgets.QHBoxLayout()
self.HLayout_0.setObjectName("HLayout_0")
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
self.HLayout_0.addItem(spacerItem1)
self.CB_L0 = QtWidgets.QComboBox(self.centralwidget)
self.CB_L0.setObjectName("CB_L0")
self.HLayout_0.addWidget(self.CB_L0)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pushButton.sizePolicy().hasHeightForWidth())
self.pushButton.setSizePolicy(sizePolicy)
self.pushButton.setMaximumSize(QtCore.QSize(40, 16777215))
self.pushButton.setObjectName("pushButton")
self.HLayout_0.addWidget(self.pushButton)
spacerItem2 = QtWidgets.QSpacerItem(50, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
self.HLayout_0.addItem(spacerItem2)
self.VLayout_0.addLayout(self.HLayout_0)
spacerItem3 = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
self.VLayout_0.addItem(spacerItem3)
self.gridLayout_4.addLayout(self.VLayout_0, 1, 0, 1, 1)
self.PB_create_cb = QtWidgets.QPushButton(self.centralwidget)
self.PB_create_cb.setObjectName("PB_create_cb")
self.gridLayout_4.addWidget(self.PB_create_cb, 0, 1, 1, 1)
self.gridLayout.addLayout(self.gridLayout_4, 0, 0, 1, 1)
self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 709, 22))
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.pushButton.setText(_translate("MainWindow", "search"))
self.PB_create_cb.setText(_translate("MainWindow", "Create dropdown"))
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_())
and here is the backend example (which creates two "objects"):
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QAction, QTableWidget, QTableWidgetItem, QVBoxLayout, QMessageBox, QDialog, QLineEdit, QPushButton, QMenu, QSizePolicy, QLabel,QTreeWidget,QTreeWidgetItem
from PyQt5.QtWidgets import (QApplication, QWidget, QToolTip, QPushButton, QMessageBox)
import sys
from test3 import *
class Run_script(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(Run_script, self).__init__(parent)
self.setupUi(self)
print("Run script initizalised")
self.PB_create_cb.clicked.connect(self.click_select)
def create_V_0_object(self,List_attributes):
V_list = []
for i,x in enumerate(List_attributes):
for k,v in x.items():
if type(v) == dict:
for k1,v1 in v.items():
if type(v) == dict:
self.HLayout_1 = QtWidgets.QHBoxLayout()
self.HLayout_1.setObjectName("H_layout_1")
self.VLayout_0 = QtWidgets.QVBoxLayout()
self.VLayout_0.setObjectName("V_L2"+k+str(i))
self.Attr_label = QtWidgets.QLabel(self.centralwidget)
self.Attr_label.setObjectName(k)
self.Attr_label.setText(k)
self.VLayout_0.addWidget(self.Attr_label)
self.attr_list = []
for k1,v1 in v.items():
self.attr_list.append(k1)
print("K1 is "+str(k1))
self.comboBox = QtWidgets.QComboBox(self.centralwidget)
self.comboBox.setObjectName("CB_"+k)
self.comboBox.addItems(self.attr_list)
self.comboBox.setToolTip("CB_"+k)
self.VLayout_0.addWidget(self.comboBox)
self.comboBox1 = QtWidgets.QComboBox(self.centralwidget)
self.comboBox1.setObjectName("CB_l2_"+k)
self.comboBox1.setToolTip("CB_l2_"+k)
self.VLayout_0.addWidget(self.comboBox1)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
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.setMaximumSize(QtCore.QSize(40, 16777215))
PB_name = "PB_"+str(k)
self.pushButton.setObjectName(PB_name)
self.pushButton.setToolTip("Search " + str(PB_name))
self.pushButton.setText(PB_name)
self.pushButton.clicked.connect(self.buttonClicked)
self.HLayout_1.addLayout(self.VLayout_0)
self.HLayout_1.addWidget(self.pushButton)
else:
pass
V_list.append(self.HLayout_1)
return V_list
def buttonClicked(self):
sender = self.sender()
cat_l_0 = sender.text()
for i in range(self.VLayout_0.count()):
name = self.VLayout_0.itemAt(i).widget().objectName()
print("this is:",name)
def click_select(self):
self.selection = [{"Category1":{"Attr1": "test1","Attr2":"test2"}},{"Category2":{"Attr1":"test3","Attr2":"test4"}}]
self.v = self.create_V_0_object(self.selection)
self.create_horizontal_display(self.v)
def deleteItemsOfLayout(self,layout):
if layout is not None:
while layout.count():
item = layout.takeAt(0)
widget = item.widget()
if widget is not None:
widget.setParent(None)
else:
self.deleteItemsOfLayout(item.layout())
def create_horizontal_display(self,vertical_layout_list):
self.deleteItemsOfLayout(self.HLayout_0)
for i,x in enumerate(vertical_layout_list):
self.HLayout_0.addLayout(x)
if __name__ == '__main__':
app = QApplication(sys.argv)
prog = Run_script()
prog.show()
sys.exit(app.exec_())
to create the objects just press the "create dropdown" button
You have many bad practices:
The variables that are created in a loop are generally not going to be a member of the class because they are temporary variables, so do not use them as they will be overwritten, therefore when accessing self.VLayout_0 you will always get the last element.
Another bad habit is that everything you want to do in one place, as you say the "object" s are similar except for the data so you should create a class that builds it, as they say: divide and conquer.
You have other errors but they are minor, correcting the above you have the following:
from PyQt5 import QtCore, QtGui, QtWidgets
from test3 import Ui_MainWindow
class Widget(QtWidgets.QWidget):
clicked = QtCore.pyqtSignal()
def __init__(self, text, values, parent=None):
super(Widget, self).__init__(parent)
hlay = QtWidgets.QHBoxLayout(self)
vlay = QtWidgets.QVBoxLayout()
self.label = QtWidgets.QLabel(text)
self.combobox_1 = QtWidgets.QComboBox()
self.combobox_1.addItems(values.keys())
self.combobox_2 = QtWidgets.QComboBox()
vlay.addWidget(self.label)
vlay.addWidget(self.combobox_1)
vlay.addWidget(self.combobox_2)
hlay.addLayout(vlay)
self.button = QtWidgets.QPushButton(text)
self.button.clicked.connect(self.clicked)
hlay.addWidget(self.button)
self.setFixedSize(self.sizeHint())
class Run_script(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(Run_script, self).__init__(parent)
self.setupUi(self)
print("Run script initizalised")
self.PB_create_cb.clicked.connect(self.click_select)
def create_V_0_object(self, attributes):
v_list = []
for x in attributes:
for key, value in x.items():
w = Widget(key, value)
w.clicked.connect(self.buttonClicked)
v_list.append(w)
return v_list
def buttonClicked(self):
w = self.sender()
print(w.combobox_1.currentText())
print(w.combobox_2.currentText())
print(w.label.text())
print(w.button.text())
def click_select(self):
selection = [{"Category1":{"Attr1": "test1","Attr2":"test2"}},{"Category2":{"Attr1": "test3", "Attr2": "test4"}}]
v = self.create_V_0_object(selection)
self.create_horizontal_display(v)
def deleteItemsOfLayout(self,layout):
if layout is not None:
while layout.count():
item = layout.takeAt(0)
widget = item.widget()
if widget is not None:
widget.setParent(None)
else:
self.deleteItemsOfLayout(item.layout())
def create_horizontal_display(self, vertical_layout_list):
self.deleteItemsOfLayout(self.HLayout_0)
for i, x in enumerate(vertical_layout_list):
self.HLayout_0.addWidget(x)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
prog = Run_script()
prog.show()
sys.exit(app.exec_())

Pyqt5: dyamically add a table to a tab

In my main program, I have a Dock widget (Vertical layout) containing a TabWidget (layouts added per tab). In my first tab I have added a static table, which resizes with the dock.
I am trying to allow the user to dynamically add a tab by importing a TableWidget design from another file into a tab; however, I am having trouble getting the layout to mimic the first tab.
Below is my code. I can make the table appear in the freshly made tab, just not fully adjust to the dock window.
My python start file:
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import mainwindow, sys, os, PyQt5, resources, dataTable
class dataForm(QtWidgets.QWidget, dataTable.Ui_Form)
def __init__(self, parent=None):
super(dataForm, self).__init__(parent)
self.setupUi(self)
class Example(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
def __init__(self, parent=None):
super(Example, self).__init__(parent)
self.setupUi(self)
self.shortcut.activated.connect(self.addTabs)
def Resolution(self):
app = QtWidgets.QApplication([])
resolution = app.desktop().screenGeometry()
width, height = resolution.width(), resolution.height()
self.setMaximumSize(QtCore.QSize(width, height))
def addTabs(self):
self.DataSets.setUpdatesEnabled(True)
self.tab = QtWidgets.QWidget()
self.tab.setAutoFillBackground(False)
self.tab.setObjectName("userAdded")
pages = self.count()
# Set the tab layout
self.tableLayout = QtWidgets.QVBoxLayout(self.tab)
self.tableLayout.setContentsMargins(1, 0, 1, 0)
self.tableLayout.setSpacing(0)
self.tableLayout.setObjectName("tableGrid")
# Add table to the new tab widget
self.table = dataForm(self.tab)
# Add table to layout
self.tableLayout.addWidget(self.table)
self.tableLayout.addStretch()
# Add the tab and go to that location
self.DataSets.insertTab((pages-1), self.tab, "Set %d" %(pages))
self.DataSets.setCurrentIndex(pages-1)
def main():
app = QtWidgets.QApplication(sys.argv)
form = Example()
form.showMaximized()
app.exec_()
if __name__ == '__main__':
main()
and my dataTable.ui form:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(242, 450)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
Form.setSizePolicy(sizePolicy)
self.tableWidget = QtWidgets.QTableWidget(Form)
self.tableWidget.setGeometry(QtCore.QRect(1, 0, 240, 450))
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.tableWidget.sizePolicy().hasHeightForWidth())
self.tableWidget.setSizePolicy(sizePolicy)
self.tableWidget.setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)
self.tableWidget.setAutoFillBackground(True)
self.tableWidget.setStyleSheet("QHeaderView::section { background-color:rgb(140, 200, 172)};\n"
"")
self.tableWidget.setFrameShape(QtWidgets.QFrame.Panel)
self.tableWidget.setFrameShadow(QtWidgets.QFrame.Plain)
self.tableWidget.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContentsOnFirstShow)
self.tableWidget.setDragEnabled(True)
self.tableWidget.setAlternatingRowColors(True)
self.tableWidget.setGridStyle(QtCore.Qt.SolidLine)
self.tableWidget.setRowCount(35)
self.tableWidget.setColumnCount(10)
self.tableWidget.setObjectName("tableWidget")
item = QtWidgets.QTableWidgetItem()
brush = QtGui.QBrush(QtGui.QColor(50, 0, 0))
brush.setStyle(QtCore.Qt.NoBrush)
item.setForeground(brush)
self.tableWidget.setItem(0, 1, item)
self.tableWidget.horizontalHeader().setCascadingSectionResizes(False)
self.tableWidget.horizontalHeader().setDefaultSectionSize(70)
self.tableWidget.horizontalHeader().setHighlightSections(True)
self.tableWidget.horizontalHeader().setMinimumSectionSize(39)
self.tableWidget.verticalHeader().setVisible(True)
self.tableWidget.verticalHeader().setDefaultSectionSize(20)
self.tableWidget.verticalHeader().setSortIndicatorShown(True)
self.tableWidget.verticalHeader().setStretchLastSection(False)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.tableWidget.setSortingEnabled(True)
__sortingEnabled = self.tableWidget.isSortingEnabled()
self.tableWidget.setSortingEnabled(False)
self.tableWidget.setSortingEnabled(__sortingEnabled)
I'm pretty close, I think. Any suggestions?
Edit: Updated code to make the dataTable classified as a QWidget & passed self.tab as its parent in def AddTabs. Also, I added a part of the layout of AddTabs that was cut out accidentally.

Categories