【问题标题】:Using a QCompleter in a QTableView with Qt and Python使用 Qt 和 Python 在 QTableView 中使用 QCompleter
【发布时间】:2020-08-13 00:26:20
【问题描述】:

我正在阅读how to make my QAbstractTableModel editable,它看起来很简单。

但是如何设置一个可编辑的单元格来使用 QCompleter?我以某种方式必须告诉 QTableView 使用 QLineEdit 小部件?我该怎么做?


编辑:嗯,我猜它与QTableView.setItemDelegateForColumn() 有一些关系,但我对delegates 或如何使用它们一无所知。


编辑:我尝试了 RobbieE 的解决方案,得到了一些可行的方法,但是当我按下 Enter 时,弹出组合框的几何形状错误并导致 Python 崩溃。

class CompleterDelegate(QtGui.QStyledItemDelegate):
    def __init__(self, parent=None, completerSetupFunction=None):
        super(CompleterDelegate, self).__init__(parent)
        self._completerSetupFunction = completerSetupFunction
    def createEditor(self, parent, option, index):
        return QtGui.QLineEdit(parent)
    def setEditorData(self, editor, index):
        super(CompleterDelegate, self).setEditorData(editor, index)
        self._completerSetupFunction(editor, index)

我的 _completerSetupFunction 看起来像这样:

def setupFunc(editor, index):
    completer = MyCompleter(editor)
    completer.setCompletionColumn(0)
    completer.setCompletionRole(QtCore.Qt.DisplayRole)
    completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)    
    editor.setCompleter(completer)
    completer.setModel(myAbstractItemModel)

【问题讨论】:

  • 如果您想创建自己的编辑器小部件,您必须使用option 参数中提供的数据设置位置和几何形状。

标签: python qt qabstracttablemodel qcompleter


【解决方案1】:

创建QStyledItemDelegate的子类

您需要做的就是重新实现setEditorData 函数,检查编辑器小部件是否为QLineEdit,然后设置完成者。

请原谅我不了解 Python,但这是在 C++ 中完成的方式。希望翻译成 Python 会很容易。

class MyDelegate : public QStyledItemDelegate{
     public:
         void setEditorData(QWidget *editor, QModelIndex const &index){
             
             // call the superclass' function so that the editor widget gets the correct data
             QStyledItemDelegate::setEditorData(editor, index);

             // Check that the editor passed in is a QLineEdit. 
             QLineEdit *lineEdit = qobject_cast<QLineEdit*>(editor);

             if (lineEdit != nullptr){

                 // add whatever completer is needed, making sure that the editor is the parent QObject so it gets deleted along with the editor
                 lineEdit.setComplete(new MyCompleter(editor));
             }
         }
}; 

【讨论】:

  • 谢谢。如果它不是 QLineEdit 怎么办? (或者这总是 QTableView 的默认设置?)
  • 该方法有效.. 除了 QTableView 的默认编辑器不是 QLineEdit,它只是一些匿名 QWidget。我可以覆盖createEditor(),但它有一些奇怪的副作用(其中一个在我按回车时崩溃:-(
  • 为编辑器创建的小部件类型取决于调用模型的data() 函数返回的类型,使用Qt::EditRole。如果您查看QItemEditorFactory 的文档,您将看到最常见数据类型的默认小部件。如果QVariant 是从QString 创建的,则QLineEdit 是默认值
  • 啊哈,我想通了。您不应该在 setEditorData 中应用完成者,而应该在创建编辑器的地方应用。
【解决方案2】:

根据 RobbieE 的建议,我将 QStyledItemDelegate 子类化。但是应用完成者的正确位置是在创建编辑器时,而不是 setEditorData。

class CompleterDelegate(QtGui.QStyledItemDelegate):
    def __init__(self, parent=None, completerSetupFunction=None):
        super(CompleterDelegate, self).__init__(parent)
        self._completerSetupFunction = completerSetupFunction
    def createEditor(self, parent, option, index):
        editor = QtGui.QLineEdit(parent)
        self._completerSetupFunction(editor, index)
        return editor

然后我使用一个 completerSetupFunction,它基本上看起来像这样:

def _completerSetupFunction(editor, index):
    print "completer setup: editor=%s, index=%s" % (editor, index)
    completer = QtGui.QCompleter(base_items, editor)
    completer.setCompletionColumn(0)
    completer.setCompletionRole(QtCore.Qt.EditRole)
    completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
    try:    
        editor.setCompleter(completer)            
    except:
        pass

这是complete example as a github gist

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-15
    • 2013-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多