ABK
ABK

Reputation: 155

To edit part of a line in a QlistWidget using python

My list widget placed inside a window prints out values (0 - 1000) when button1 is pressed. But some of these values are 0's and signify an error. The user is expected to update these values with any other positive integer. Once the value is confirmed by pressing a button2, the list will be updated or an error is shown that it needs to be further updated.

The following is my code.

import Ui_ImageSort # designed using Qt-Designer
from PyQt5 import QtCore
from PyQt5.QtWidgets import QMainWindow, QListWidgetItem

class ImageSort(Ui_ImageSort.Ui_MainWindow, QMainWindow):
    def __init__(self):
        super(ImageSort, self).__init__()
        self.setupUi(self)

    self.pushButton_1.clicked.connect(list_view)
    self.pushButton_2.clicked.connect(print_scales)

    def list_view(self):
        self.listWidget.clear()
        for i in range(len(self.scale_txt)):
            item = QListWidgetItem(str(self.scale_txt[i]))
            self.listWidget.addItem(str(i + 1) + ") " + item.text())            

    def print_scales(self):
        self.listWidget.clear()
        error = 0
        for i in range(len(self.scale_txt)):
            if (self.scale_txt[i]==0):
                error = 1

        if (error ==0):
            self.listWidget.addItem("\nThe scale values are confirmed ")
            for i in range(len(self.scale_txt)):
                    print(self.scale_txt[i])
                    print("\n")
        else:
            self.listWidget.addItem("\nThe scale values have an error")
            self.listWidget.addItem("Press button 1 again to edit")

I would like to edit only the digits the the listwidget prints out. The output will look something like this:

1) 100 microns
2) 200 microns
3) 0 microns
4) 100 microns

The value 0 needs to be corrected. So it should be marked red. And the user can change without affecting the remaining line ("microns"). For example: "0 microns" is invalid, marked in red and should be editable, but after the user replaces it with some other digits, presses button2, then it becomes valid and is, therefore, turned black and is no longer editable.

Upvotes: 0

Views: 710

Answers (1)

eyllanesc
eyllanesc

Reputation: 243897

One possible solution is to use a delegate, and the data is passed through the roles:

from PyQt5 import QtCore, QtGui, QtWidgets

MaskRole = QtCore.Qt.UserRole + 1000

class ListDelegate(QtWidgets.QStyledItemDelegate):
    def createEditor(self, parent, option, index):
        mask = index.data(MaskRole)
        if mask is not None:
            editor = QtWidgets.QLineEdit(parent)
            editor.setInputMask(mask)
            return editor

    def setModelData(self, editor, model, index):
        if editor.hasAcceptableInput():
            text = editor.text()
            model.setData(index, text, QtCore.Qt.DisplayRole)

        re = QtCore.QRegularExpression(r"(\d+)\) (\d+) microns")
        match = re.match(index.data())
        color = QtGui.QColor("red")
        if match.hasMatch():
            val = match.captured(match.lastCapturedIndex())
            if val != "0":
                color = QtGui.QColor("black")
        model.setData(index, color, QtCore.Qt.ForegroundRole)

if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = QtWidgets.QListWidget()
    delegate = ListDelegate(w)
    w.setItemDelegate(delegate)
    scales = [100, 200, 0, 500, 0, 300, 0]
    for i, scale in enumerate(scales):
        item = QtWidgets.QListWidgetItem()
        if scale == 0:
            item.setData(MaskRole, "{}) 900 micro\\ns".format(i))
            item.setFlags(item.flags() | QtCore.Qt.ItemIsEditable)
            item.setForeground(QtCore.Qt.red)
        item.setText("{}) {} microns".format(i, scale))
        w.addItem(item)
    w.show()
    sys.exit(app.exec_())

Upvotes: 1

Related Questions