PySide中的QComboBox自动补全无法工作,但在PyQt4中可以
我有一个组合框,里面用了一种自定义的自动补全功能,在PyQt4中运行得很好,但在PySide中却不行。
我确认新的自动补全功能已经替换了QComboBox自带的那个,因为现在没有内联补全了。但是在PySide中运行时,自动补全的下拉列表没有出现,选项也没有过滤出来。
我还尝试确保所有的文本都是str
类型或者都是unicode
类型,以避免PyQt API 1中使用QString和PySide中使用Python unicode类型之间的差异。改变文本类型对PyQt和PySide的表现没有影响(PyQt依然正常工作,而PySide却不行)。
这是我的代码:
from PySide import QtCore
from PySide import QtGui
#from PyQt4 import QtCore
#from PyQt4 import QtGui
class AdvComboBox(QtGui.QComboBox):
def __init__(self, parent=None):
super(AdvComboBox, self).__init__(parent)
self.setFocusPolicy(QtCore.Qt.StrongFocus)
self.setEditable(True)
# add a filter model to filter matching items
self.pFilterModel = QtGui.QSortFilterProxyModel(self)
self.pFilterModel.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.pFilterModel.setSourceModel(self.model())
# add a completer, which uses the filter model
self.completer = QtGui.QCompleter(self.pFilterModel, self)
# always show all (filtered) completions
self.completer.setCompletionMode(QtGui.QCompleter.UnfilteredPopupCompletion)
self.setCompleter(self.completer)
# connect signals
def filter(text):
print "Edited: ", text, "type: ", type(text)
self.pFilterModel.setFilterFixedString(str(text))
self.lineEdit().textEdited[unicode].connect(filter)
self.completer.activated.connect(self.on_completer_activated)
# on selection of an item from the completer, select the corresponding item from combobox
def on_completer_activated(self, text):
print "activated"
if text:
print "text: ", text
index = self.findText(str(text))
print "index: ", index
self.setCurrentIndex(index)
# on model change, update the models of the filter and completer as well
def setModel(self, model):
super(AdvComboBox, self).setModel(model)
self.pFilterModel.setSourceModel(model)
self.completer.setModel(self.pFilterModel)
# on model column change, update the model column of the filter and completer as well
def setModelColumn(self, column):
self.completer.setCompletionColumn(column)
self.pFilterModel.setFilterKeyColumn(column)
super(AdvComboBox, self).setModelColumn(column)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
combo = AdvComboBox()
names = ['bob', 'fred', 'bobby', 'frederick', 'charles', 'charlie', 'rob']
# fill the standard model of the combobox
combo.addItems(names)
combo.setModelColumn(0)
combo.resize(300, 40)
combo.show()
sys.exit(app.exec_())
1 个回答
2
我在写问题的时候自己搞明白了...
看起来虽然PySide QCompleter 的文档提到可以用一个模型和父级来初始化 QCompleter,但实际上这个方法并没有奏效。
解决办法是,在初始化完成后再设置 completer 的模型。
以下是可以正常工作的代码:
from PySide import QtCore
from PySide import QtGui
class AdvComboBox(QtGui.QComboBox):
def __init__(self, parent=None):
super(AdvComboBox, self).__init__(parent)
self.setFocusPolicy(QtCore.Qt.StrongFocus)
self.setEditable(True)
# add a filter model to filter matching items
self.pFilterModel = QtGui.QSortFilterProxyModel(self)
self.pFilterModel.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.pFilterModel.setSourceModel(self.model())
# add a completer
self.completer = QtGui.QCompleter(self)
#Set the model that the QCompleter uses
# - in PySide doing this as a separate step worked better
self.completer.setModel(self.pFilterModel)
# always show all (filtered) completions
self.completer.setCompletionMode(QtGui.QCompleter.UnfilteredPopupCompletion)
self.setCompleter(self.completer)
# connect signals
def filter(text):
print "Edited: ", text, "type: ", type(text)
self.pFilterModel.setFilterFixedString(str(text))
self.lineEdit().textEdited[unicode].connect(filter)
self.completer.activated.connect(self.on_completer_activated)
# on selection of an item from the completer, select the corresponding item from combobox
def on_completer_activated(self, text):
print "activated"
if text:
print "text: ", text
index = self.findText(str(text))
print "index: ", index
self.setCurrentIndex(index)
# on model change, update the models of the filter and completer as well
def setModel(self, model):
super(AdvComboBox, self).setModel(model)
self.pFilterModel.setSourceModel(model)
self.completer.setModel(self.pFilterModel)
# on model column change, update the model column of the filter and completer as well
def setModelColumn(self, column):
self.completer.setCompletionColumn(column)
self.pFilterModel.setFilterKeyColumn(column)
super(AdvComboBox, self).setModelColumn(column)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
combo = AdvComboBox()
names = ['bob', 'fred', 'bobby', 'frederick', 'charles', 'charlie', 'rob']
# fill the standard model of the combobox
combo.addItems(names)
combo.setModelColumn(0)
combo.resize(300, 40)
combo.show()
sys.exit(app.exec_())