表中的pyqt自动完成 [英] pyqt auto completion in a table

查看:38
本文介绍了表中的pyqt自动完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在表格中自动完成.到目前为止,我可以使整个表的列表相同.

但是,我需要每个单元格的动态列表.当我移动到单元格中的新位置时,如何更新列表?

 from PyQt5.QtCore import *从 PyQt5.QtGui 导入 *从 PyQt5.QtWidgets 导入 *导入系统类 mainWindow(QMainWindow):def __init__(self, parent = None):super(mainWindow, self).__init__(parent)self.initUI()定义 initUI(self):self.center_window = centerWindow(parent=self)self.setCentralWidget(self.center_window)类中心窗口(QWidget):def __init__(self, parent=None):super(centerWindow, self).__init__(parent)table = QTableWidget()table.setItemDelegate(TableItemCompleter())table.setRowCount(5)table.setColumnCount(1)vbox = QVBoxLayout(self)vbox.addWidget(表)self.setLayout(vbox)类 TableItemCompleter(QStyledItemDelegate):def __init__(self, parent = None):super(TableItemCompleter, self).__init__(parent)def createEditor(self, parent, styleOption, index):编辑器 = QLineEdit(父)完成_ls = ['aaa', 'bbb', 'ccc']autoComplete = QCompleter(completion_ls)editor.setCompleter(自动完成)返回编辑器如果 __name__ == '__main__':app = QApplication.instance()如果应用程序是无:app = QApplication(sys.argv)别的:print('QApplication 实例已经存在:%s' % str(app))ex = mainWindow()例如.show()sys.exit(app.exec_())

为了更清楚.我想添加如下内容,而不是在 TableItemCompleter 中添加 completion_ls 列表:

table.setItem(row, column) #添加我的新自动完成列表

解决方案

QCompleter 可以建立一个模型作为自动完成的来源,我们可以通过 QModelIndex> 通过 index.model() 提供方法 createEditor(self, parent, option, index) 的模型但问题是你只能取一列而不是想要什么.

然后我们必须将tablemodel转换为listmodel,然后我们必须过滤重复的元素,以便完成者显示唯一的元素,一种方法是通过代理,从QAbstractProxyModel继承的类,方案如下:

TableModel ---->ReadTable2ListProxyModel ---->重复过滤器代理模型

En la siguiente sección muestros las clases:

class ReadTable2ListProxyModel(QIdentityProxyModel):def columnCount(self, parent=QModelIndex()):返回 1def rowCount(self, parent=QModelIndex()):返回 self.sourceModel().rowCount() * self.sourceModel().columnCount()def mapFromSource(self, sourceIndex):如果 sourceIndex.isValid() 和 sourceIndex.column() == 0\和 sourceIndex.row() 

然后在委托中建立转换:

class TableItemCompleter(QStyledItemDelegate):def createEditor(self, parent, option, index):编辑器 = QLineEdit(父)完成者 = QCompleter(父)proxy1 = ReadTable2ListProxyModel(parent)proxy2 = DuplicateFilterProxyModel(parent)proxy1.setSourceModel(index.model())proxy2.setSourceModel(proxy1)completer.setModel(proxy2)editor.setCompleter(完成者)返回编辑器

在下面的

<小时>

如果您希望每个项目都有一个列表,可以通过 setData() 方法,并在委托中通过 QModelIndex 的方法 data() :

 from PyQt5.QtCore import *从 PyQt5.QtWidgets 导入 *随机导入类 TableItemCompleter(QStyledItemDelegate):def createEditor(self, parent, option, index):编辑器 = QLineEdit(父)completion_ls = index.data(Qt.UserRole) # 获取列表完成者 = QCompleter(completion_ls,父)editor.setCompleter(完成者)返回编辑器类小部件(QWidget):def __init__(self, *args, **kwargs):QWidget.__init__(self, *args, **kwargs)躺 = QHBoxLayout(self)tv = QTableWidget(3, 4, self)lay.addWidget(tv)l = [AA"、AB"、AC"、AD"、BA"、BB"、BC"]对于我在范围内(tv.rowCount()):对于范围内的 j(tv.columnCount()):it = QTableWidgetItem(f"{i},{j}")tv.setItem(i, j, it)it.setData(Qt.UserRole, random.sample(l, 3)) # 设置列表tv.setItemDelegate(TableItemCompleter(tv))如果 __name__ == '__main__':导入系统app = QApplication(sys.argv)w = 小部件()w.show()sys.exit(app.exec_())

I need auto completion in a table. So far, I could make it work that I get the same list for the entire table.

However, I need a dynamic list for each cell. How can I get update the list when I move to a new position in the cell?

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys


class mainWindow(QMainWindow):

    def __init__(self, parent = None):
        super(mainWindow, self).__init__(parent)

        self.initUI()


    def initUI(self):
        self.center_window = centerWindow(parent=self)
        self.setCentralWidget(self.center_window)


class centerWindow(QWidget):
    def __init__(self, parent=None):
        super(centerWindow, self).__init__(parent)

        table = QTableWidget()
        table.setItemDelegate(TableItemCompleter())
        table.setRowCount(5)
        table.setColumnCount(1)

        vbox = QVBoxLayout(self)
        vbox.addWidget(table)
        self.setLayout(vbox)


class TableItemCompleter(QStyledItemDelegate):
    def __init__(self, parent = None):
        super(TableItemCompleter, self).__init__(parent)

    def createEditor(self, parent, styleOption, index):
        editor = QLineEdit(parent)

        completion_ls = ['aaa', 'bbb', 'ccc']

        autoComplete = QCompleter(completion_ls)
        editor.setCompleter(autoComplete)
        return editor


if __name__ == '__main__':
    app = QApplication.instance()
    if app is None:
        app = QApplication(sys.argv)
    else:
        print('QApplication instance already exists: %s' % str(app))


    ex = mainWindow()
    ex.show()
    sys.exit(app.exec_())

To make it more clear. Instead of having the completion_ls list in the TableItemCompleter, I'd like to add something like this:

table.setItem(row, column) #add my new auto completion list

解决方案

QCompleter can be established a model that uses as a source for the autocomplete, we could pass the QModelIndex model that provides the method createEditor(self, parent, option, index) through index.model() but the problem is that you can only take a column and is not what is desired.

Then we must do a conversion of the tablemodel to a listmodel, and then we must filter the repeated elements so that the completer shows unique elements, one way to do them is through proxies, classes that inherit from QAbstractProxyModel, the scheme is as follows:

TableModel ----> ReadTable2ListProxyModel ----> DuplicateFilterProxyModel

En la siguiente sección muestros las clases:

class ReadTable2ListProxyModel(QIdentityProxyModel):
    def columnCount(self, parent=QModelIndex()):
        return 1

    def rowCount(self, parent=QModelIndex()):
        return self.sourceModel().rowCount() * self.sourceModel().columnCount()

    def mapFromSource(self, sourceIndex):
        if sourceIndex.isValid() and sourceIndex.column() == 0\
                and sourceIndex.row() < self.rowCount():
            r = sourceIndex.row()
            c = sourceIndex.column()
            row = sourceIndex.model().columnCount() * c + r
            return self.index(row, 0)
        return QModelIndex()

    def mapToSource(self, proxyIndex):
        r = proxyIndex.row() / self.sourceModel().columnCount()
        c = proxyIndex.row() % self.sourceModel().columnCount()
        return self.sourceModel().index(r, c)

    def index(self, row, column, parent=QModelIndex()):
        return self.createIndex(row, column)


class DuplicateFilterProxyModel(QSortFilterProxyModel):
    def setSourceModel(self, model):
        model.dataChanged.connect(lambda: self.invalidate())
        QSortFilterProxyModel.setSourceModel(self, model)

    def filterAcceptsRow(self, row, parent):
        value = self.sourceModel().index(row, self.filterKeyColumn())\
            .data(self.filterRole())
        if value is None:
            return False
        if row == 0:
            return True
        for i in reversed(range(0, row)):
            val = self.sourceModel().index(i, self.filterKeyColumn())\
                .data(self.filterRole())
            if val == value:
                return False
        return True

Then the conversion is established in the delegate:

class TableItemCompleter(QStyledItemDelegate):
    def createEditor(self, parent, option, index):
        editor = QLineEdit(parent)
        completer = QCompleter(parent)

        proxy1 = ReadTable2ListProxyModel(parent)
        proxy2 = DuplicateFilterProxyModel(parent)
        proxy1.setSourceModel(index.model())
        proxy2.setSourceModel(proxy1)

        completer.setModel(proxy2)
        editor.setCompleter(completer)
        return editor

In the following link you will find an example, and in the following image the operation is illustrated, in the first widget the table is observed, in the second the conversion to list and in the third the list eliminating duplicate elements.


If you want each item to have a list what can be done is to store the list in each item through a role that is not in use as Qt.UserRole through the setData() method, and in the delegate through the method data() of the QModelIndex:

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import random

class TableItemCompleter(QStyledItemDelegate):
    def createEditor(self, parent, option, index):
        editor = QLineEdit(parent)
        completion_ls = index.data(Qt.UserRole) # get list
        completer = QCompleter(completion_ls, parent)
        editor.setCompleter(completer)
        return editor

class Widget(QWidget):
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)
        lay = QHBoxLayout(self)
        tv = QTableWidget(3, 4, self)
        lay.addWidget(tv)
        l = ["AA", "AB", "AC", "AD", "BA", "BB", "BC"]
        for i in range(tv.rowCount()):
            for j in range(tv.columnCount()):
                it = QTableWidgetItem(f"{i},{j}")
                tv.setItem(i, j, it)
                it.setData(Qt.UserRole, random.sample(l, 3)) # set list
        tv.setItemDelegate(TableItemCompleter(tv))


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

这篇关于表中的pyqt自动完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆