问题
I am trying to update/refresh a QListWidget after I click a button in a CustomFormWidget
.
What I am trying to do is when I click the button in a CustomFormWidget
, it updates the class variable data in the ParentWid
and then rebuilds/updated/refreshes ParentWid.ui.listWidget
. Where and how should I add this logic. Should I add to my CustomFormWidget.on_click
method or should my logic be set in the ParentWid
?
So far my code looks like:
from PyQt5 import QtCore, QtGui, QtWidgets
class ParentWid(QtWidgets.QDialog):
data = [
{
'id': 1,
'name': 'pkg-foo',
'version': '0.1',
'installed': False
},
{
'id': 2,
'name': 'pkg-bar',
'version': '0.1',
'installed': False
}
]
def __init__(self, parent=None):
super(ParentWid, self).__init__(parent)
self.ui = Ui_ParentWidget()
self.ui.setupUi(self)
self.set_widget_data()
@classmethod
def update_installed_packages(cls, value):
for item in ParentWid.data:
if item["id"] == value:
item["installed"] = not item["installed"]
def set_widget_data(self):
for item in ParentWid.data:
custFormItem = CustomFormWidget(item)
lst_item = QtWidgets.QListWidgetItem()
self.ui.listWidget.insertItem(
self.ui.listWidget.count(),
lst_item
)
self.ui.listWidget.setItemWidget(lst_item, custFormItem)
lst_item.setSizeHint(custFormItem.sizeHint())
class CustomFormWidget(QtWidgets.QWidget):
def __init__(self, data, parent=None):
super(CustomFormWidget, self).__init__(parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
self.data = data
self.ui.pkg_name.setText(self.data['name'])
self.ui.pkg_version.setText(self.data['version'])
if self.data["installed"] is True:
self.ui.install_btn.setText("Installed")
self.ui.install_btn.setEnabled(False)
self.ui.install_btn.clicked.connect(self.on_click)
def on_click(self):
print('installed pkg')
## install LOGIG
ParentWid.update_installed_packages(self.data["id"])
回答1:
In this case it is better that each item manages its data, for this we can pass the QListWidget to the custom widget and in it handle through roles. In the following example, each widget modifies its data, and when the application is closed, the updated data is printed:
class Roles:
IdRole = QtCore.Qt.UserRole + 1000
NameRole = QtCore.Qt.UserRole + 1001
VersionRole = QtCore.Qt.UserRole + 1002
InstalledRole = QtCore.Qt.UserRole + 1003
class ParentWid(QtWidgets.QDialog, Ui_ParentWidget):
def __init__(self, data={}, parent=None):
super(ParentWid, self).__init__(parent)
self.data = data
self.setupUi(self)
self.set_widget_data()
def set_widget_data(self):
for item in self.data:
lst_item = QtWidgets.QListWidgetItem()
self.listWidget.addItem(lst_item)
custFormItem = CustomFormWidget(item, lst_item)
lst_item.setSizeHint(custFormItem.sizeHint())
def print_results(self):
v = (("id", Roles.IdRole), ("name", Roles.NameRole), ("version", Roles.VersionRole), ("installed", Roles.InstalledRole),)
results = []
for i in range(self.listWidget.count()):
it = self.listWidget.item(i)
d = {}
for k, r in v:
d[k] = it.data(r)
results.append(d)
print(results)
# test
def closeEvent(self, event):
self.print_results()
super(ParentWid, self).closeEvent(event)
class CustomFormWidget(QtWidgets.QWidget, Ui_Form):
def __init__(self, data, item, parent=None):
super(CustomFormWidget, self).__init__(parent)
self._item = item
self._item.listWidget().setItemWidget(self._item, self)
self.setupUi(self)
v = (("id", Roles.IdRole), ("name", Roles.NameRole), ("version", Roles.VersionRole), ("installed", Roles.InstalledRole),)
for k, r in v:
self._item.setData(r, data[k])
self.update_view()
self.install_btn.clicked.connect(self.on_click)
def update_view(self):
self.pkg_name.setText(self._item.data(Roles.NameRole))
self.pkg_version.setText(self._item.data(Roles.VersionRole))
v = self._item.data(Roles.InstalledRole)
self.install_btn.setText("Installed" if v else "Not Installed")
self.install_btn.setEnabled(not v)
@QtCore.pyqtSlot()
def on_click(self):
self._item.setData(Roles.InstalledRole, not self._item.data(Roles.InstalledRole))
self.update_view()
v = (("id", Roles.IdRole), ("name", Roles.NameRole), ("version", Roles.VersionRole), ("installed", Roles.InstalledRole),)
for k, r in v:
print(k, self._item.data(r))
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
data = [
{
'id': 1,
'name': 'pkg-foo',
'version': '0.1',
'installed': False
},
{
'id': 2,
'name': 'pkg-bar',
'version': '0.1',
'installed': False
}
]
w = ParentWid(data)
w.show()
sys.exit(app.exec_())
来源:https://stackoverflow.com/questions/53597853/pyqt5-refresh-update-qlistwidget-based-on-event-in-custom-widget