Für die Bearbeitung von Datensätzen aus einer Liste, habe ich unten folgenden Code erstellt.
Dieser ist lauffähig, um ihn testen zu können.
Mein Problem ist, dass bei bestimmten Ereignissen, der Focus auf das betreffende Item gesetzt werden soll. Siehe dazu die Funktion "self.VerificationCompulsoryEntryFields".
Leider konnte ich noch keine Lösung finden, die auch bei mir funktioniert hätte.
Daher würde ich mich sehr über Eure Hilfe freuen!
Code: Alles auswählen
import sys
import datetime
date_now = datetime.date.today()
date_time = datetime.datetime.now().strftime('%Y.%m.%d_%H:%M:%S')
from PyQt5.QtCore import Qt, QEvent, QSize, QSortFilterProxyModel
from PyQt5.QtGui import QColor, QStandardItem, QStandardItemModel
from PyQt5.QtWidgets import (QAction, QApplication, QGridLayout, 
    QHeaderView, QLineEdit, QMainWindow, QMdiArea, 
	QMessageBox, QPushButton, QTableView)
title = 'Backlight management'
listname = 'addresses'
header = ['client', 'client_number', 'supplier_number',
    'namen', 'zusatz', 'anrede2', 'namen2', 'info_namen',
    'street', 'plz', 'ort', 'entfernung', 'homepage',
    'ust_nr', 'steuer_nr', 'handelsregister', 'handelsregister_nr', 'datum']
dataset = ['CUSTOMER', '029002', '', '','', '', '','', 'DIRE STREET 15', 
    '04711', 'CRAZY CITY', '0', '', '', '', '', '', '2019.03.22']
write_lock = {0 : True, 1 : True}
duty_fields = {0 : True, 1 : True, 3 : True, 8 : True, 9 : True, 10 : True}
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setWindowTitle("MDI demo")
        self.mdi = QMdiArea()
        self.setCentralWidget(self.mdi)
        self.mdi.tileSubWindows()
        self.listname = listname
        sub = Dataset(self, dataset, header)
        self.mdi.addSubWindow(sub)
        sub.show()
class Dataset(QLineEdit):
    def __init__(self, parent, dataset, header):
        super(Dataset, self).__init__()
        self.parent = parent
        self.old_dataset = self.dataset = dataset
        self.header = header
        self.mdi = parent.mdi
        self.listname = parent.listname
        self.write_lock = write_lock
        self.duty_fields = duty_fields
        self.error_sign = '<?>'
        self.installEventFilter(self)
        self.setFocusPolicy(Qt.StrongFocus)
        self.view = QTableView(self)
        self.width = self.columnWidth()
        if self.width < 500:
            self.width = 500
        self.bt1 = QPushButton('Save_close', self)
        self.bt1.clicked.connect(self.save_close)
        # GridLayout
        grid = QGridLayout()
        grid.addWidget(self.view, 0, 0)
        grid.addWidget(self.bt1, 1, 0)
        self.setLayout(grid)
        self.model = QStandardItemModel()
        # Load and check dataset
        self.VerificationCompulsoryEntryFields (self.createDataset())
        # Vertical header
        [self.model.setHeaderData(i, Qt.Vertical, column)
            for i, column in enumerate(header)]
        self.proxy = QSortFilterProxyModel(self)
        self.proxy.setSourceModel(self.model)
        self.view.setModel(self.proxy)
        self.view.horizontalHeader().setSectionResizeMode(
		    0, QHeaderView.Stretch)
    def sizeHint(self):
        # and the margins which include the frameWidth and the extra
        # margins that would be set via a stylesheet or something else
        margins = self.contentsMargins()
        # y
        height = round(self.fontMetrics().height() * 1.1)
        height += self.view.verticalHeader().length()
        height += self.view.horizontalHeader().height()
        height += self.view.horizontalScrollBar().height()
        height += margins.left() + margins.right()
        # x
        width = self.view.horizontalHeader().length()
        width += self.view.verticalHeader().width()
        width += self.view.verticalScrollBar().width()
        width += margins.left() + margins.right()
        if width < self.width:
            width = self.width
        return QSize(width, height)
    
    def columnWidth(self):
        md = dict([(len(value), value) for value in self.dataset])
        mv = md[max(md)]
        width = round(
            QLineEdit().fontMetrics().boundingRect(mv).width() * 1.1)
        if width < 500:
            width = 500
        return width
    def eventFilter(self, source, event):
        """
        View events and check for taskstype.
        """
        keyWork = False
        try:
            if event.type() == QEvent.KeyRelease:
                c = 1
                if event.key() == Qt.Key_Tab:
                    keyWork = 'key_tab'
                elif event.key() == Qt.Key_Up:
                    keyWork = 'key_up'
                    c = -1
                elif event.key() == Qt.Key_Down:
                    keyWork = 'key_down'
                if keyWork:
                    i = self.view.currentIndex().row() - c
                    self.checkItem(i)
                    #self.writeLockCheck(keyWork)
        except AttributeError:
            pass
        return super().eventFilter(source, event)
    def valueFormat(self, i):
        self.column_name = self.header[i].lower()
        #return SetValue(self)
    
    def checkItem(self, i):
        item = self.model.invisibleRootItem().child(i)
        self.value = item.text()
        #self.valueFormat(i)
        item.setText(self.value)
        item.setData(i, Qt.UserRole)
        try:
            self.duty_fields[i]
            if item.text() == '' or item.text() == self.error_sign:
                # item compulsory entry is not true text color is red
                if item.text() == '':
                    item.setText(self.error_sign)
                item.setData(QColor(255,0,0), Qt.ForegroundRole)
        except KeyError:
            pass
        try:
            self.write_lock[i]
            # item read-only, set flags
            item.setFlags( Qt.ItemIsSelectable |  Qt.ItemIsEnabled )
            # item read-only, text color is red
            item.setData(QColor(255,0,0), Qt.ForegroundRole)
        except KeyError:
            if item.text() != self.error_sign:
                # item compulsory entry is true, text color is white
                item.setData(QColor(255,255,255), Qt.ForegroundRole)
        item.data(Qt.UserRole)
        self.model.setItem(i, 0, item)
        return item
    
    def createDataset(self):
        [self.model.invisibleRootItem().appendRow(QStandardItem(value))
            for i, value in enumerate(self.dataset)]
        return self.checkDataset()
    
    def checkDataset(self):
        return [self.checkItem(i).text() for i in range(len(self.header))]
    def VerificationCompulsoryEntryFields (self, dataset):
        self.mdi.duty_error = False
        if set((self.error_sign,)) & set(dataset):
            self.mdi.duty_error = True
            for i, value in enumerate(dataset):
                if self.checkItem(i).text() == self.error_sign:
                    #item.setFocus()	# set focus to item, no function
                    #item.selectAll()	# no function
                    break
            work_info = 'Eingabefeld muss ausgefüllt werden!'
            self.mdi.work_info = work_info
            print(work_info)
            return
        self.dataset = dataset
        return True
    def updateDataset(self):
        # update model table
        self.parent.model.data = sorted(self.parent.model.data)
        self.parent.view.setModel(self.mdi.model)
        self.parent.model.layoutChanged.emit()
    def save_close(self):
        if self.VerificationCompulsoryEntryFields (self.checkDataset()):
            self.parent.model.data[self.parent.index] = self.dataset
            self.updateDataset()
def main():
    app = QApplication(sys.argv)
    ex = MainWindow()
    ex.show()
    sys.exit(app.exec_())
if __name__ == '__main__':
    main()