PyQt4:避免将项目添加到 QComboBox()
PyQt4: Avoid adding the items to the QComboBox()
在下面的可执行源代码中,您可以看到我正在使用 QCompleter
- 结合 QComboBox()
。
以下情况:假设您要键入当前列表中不存在的任何随机字母,然后按 Enter 键。您连续多次执行此过程。现在点击QComboBox()
,你会看到乱输入的字符在QComboBox()
中。我不想要那个。我怎样才能防止这种情况发生?为什么?我只想处理列表中的数据。用户键入几个字母,即他要查找的词。但是当用户按 Enter 时,我不想在 QComboBox()
中出现新词。
# -*- coding: cp1252 -*-
import sys
from PyQt4.QtCore import Qt, QVariant, SIGNAL, QEvent
from PyQt4.QtGui import QApplication, QStandardItemModel, QStandardItem, QTreeView, QComboBox, QDialog, \
QVBoxLayout, QPushButton, QAbstractItemView, QCompleter, QSortFilterProxyModel, \
QKeyEvent
class MyCustomDialog(QDialog):
def __init__(self, app=None, parent=None):
QDialog.__init__(self, parent)
self.app = app
# Second, we need our QTreeView() and
# the settings
self.init_tree_view()
# Create an empty model for the TreeViews' data
_standard_item_model = QStandardItemModel(0,2)
# Add some textual items
self.food_list = [
["0", 'Cookie dough'],
["1", 'Hummus'],
["2", 'Spaghetti'],
["3", 'Dal makhani'],
["6", 'Blolonese'],
["4", 'Hachfleisch'],
["3", 'Nudeln'],
["666", 'Flösch'],
["4", 'Chocolate whipped cream']
]
# Now its time to populate data
self.populate(model=_standard_item_model)
# Apply the model to the list view
self.set_tree_view_model(_standard_item_model)
# QComboBox() will be created
self.combo_box = QComboBox(self)
self.init_complete(model=_standard_item_model)
# layout is a defined QVBoxLayout()
layout = QVBoxLayout(self)
layout.addWidget(self.combo_box)
self.setLayout(layout)
def init_tree_view(self):
self.tree_view = QTreeView()
self.tree_view.setRootIsDecorated(False)
self.tree_view.setWordWrap(True)
self.tree_view.setAlternatingRowColors(True)
self.tree_view.setSelectionMode(QTreeView.ExtendedSelection)
self.tree_view.header().hide()
self.tree_me = QTreeView()
self.tree_me.setRootIsDecorated(False)
self.tree_me.setWordWrap(True)
self.tree_me.setAlternatingRowColors(True)
self.tree_me.setSelectionMode(QTreeView.ExtendedSelection)
self.tree_me.header().hide()
def init_complete(self, model=None):
# add a completer, which uses the filter model
# add a filter model to filter matching items
filterModel = QSortFilterProxyModel(self.combo_box)
filterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
filterModel.setSourceModel(model)
filterModel.setFilterKeyColumn(0)
completer = QCompleter(self.combo_box)
# Set the model that the QCompleter uses
# on model column change, update the model
# column of the filter and completer as well
completer.setModel(filterModel)
completer.setCompletionColumn(0)
completer.popup().installEventFilter(self)
completer.popup().selectionModel().selectionChanged.connect(lambda new_index:
self.get_id_tree_view(new_index=new_index))
# always show all (filtered) completions
completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
completer.setPopup( self.tree_me )
self.tree_me.setColumnHidden(1, True)
self.combo_box.setEditable(True)
self.combo_box.setCompleter(completer)
# on model column change, update the model
# column of the filter and completer as well
self.combo_box.setModel(model)
self.combo_box.setView(self.tree_view)
# on model column change, update the model column of
# the filter and completer as well
self.combo_box.setModelColumn(0)
self.tree_view.resizeColumnToContents(0)
self.tree_view.setColumnHidden(1, True)
if self.combo_box.isEditable():
self.app.connect(self.combo_box.lineEdit(), SIGNAL('textEdited(QString)'), filterModel.setFilterFixedString)
def set_tree_view_model(self, model):
self.tree_view.setModel(model)
def generator_header_data(self, list_header):
for header_data in list_header:
yield header_data
def set_header_data(self, list_header_data=None, model=None):
count_column = 0
for header_data in self.generator_header_data(list_header_data):
model.setHeaderData(count_column, Qt.Horizontal, header_data)
count_column +=1
def get_id_tree_view(self, new_index=None):
try:
if not new_index is None:
index = new_index.indexes()[1].data()#.toPyObject()
if isinstance(index, QVariant):
print "get_id_tree_view, index", index.toString()
except IndexError as InErr:
pass#print "InErr", InErr
def populate_data_item(self, item_list=None, model=None):
count_items = len(item_list)
if count_items == 2:
item_first, item_second = item_list
two_columns_item = [QStandardItem(item_second), QStandardItem(str(item_first))]
model.appendRow(two_columns_item)
def populate(self, model=None):
for single_list in self.food_list:
self.populate_data_item(item_list=single_list, model=model)
def main():
app = QApplication(sys.argv)
window = MyCustomDialog(app=app)
window.resize(300, 50)
window.show()
try:
sip.setdestroyonexit(False)
except:
# missing in older versions
pass
sys.exit(app.exec_())
if __name__ == "__main__":
main()
http://doc.qt.io/qt-4.8/qcombobox.html#details
When the user enters a new string in an editable combobox, the widget may or may not insert it, and it can insert it in several locations. The default policy is is AtBottom but you can change this using setInsertPolicy().
http://doc.qt.io/qt-4.8/qcombobox.html#insertPolicy-prop
void setInsertPolicy(InsertPolicy policy)
QComboBox::NoInsert - The string will not be inserted into the combobox.
在下面的可执行源代码中,您可以看到我正在使用 QCompleter
- 结合 QComboBox()
。
以下情况:假设您要键入当前列表中不存在的任何随机字母,然后按 Enter 键。您连续多次执行此过程。现在点击QComboBox()
,你会看到乱输入的字符在QComboBox()
中。我不想要那个。我怎样才能防止这种情况发生?为什么?我只想处理列表中的数据。用户键入几个字母,即他要查找的词。但是当用户按 Enter 时,我不想在 QComboBox()
中出现新词。
# -*- coding: cp1252 -*-
import sys
from PyQt4.QtCore import Qt, QVariant, SIGNAL, QEvent
from PyQt4.QtGui import QApplication, QStandardItemModel, QStandardItem, QTreeView, QComboBox, QDialog, \
QVBoxLayout, QPushButton, QAbstractItemView, QCompleter, QSortFilterProxyModel, \
QKeyEvent
class MyCustomDialog(QDialog):
def __init__(self, app=None, parent=None):
QDialog.__init__(self, parent)
self.app = app
# Second, we need our QTreeView() and
# the settings
self.init_tree_view()
# Create an empty model for the TreeViews' data
_standard_item_model = QStandardItemModel(0,2)
# Add some textual items
self.food_list = [
["0", 'Cookie dough'],
["1", 'Hummus'],
["2", 'Spaghetti'],
["3", 'Dal makhani'],
["6", 'Blolonese'],
["4", 'Hachfleisch'],
["3", 'Nudeln'],
["666", 'Flösch'],
["4", 'Chocolate whipped cream']
]
# Now its time to populate data
self.populate(model=_standard_item_model)
# Apply the model to the list view
self.set_tree_view_model(_standard_item_model)
# QComboBox() will be created
self.combo_box = QComboBox(self)
self.init_complete(model=_standard_item_model)
# layout is a defined QVBoxLayout()
layout = QVBoxLayout(self)
layout.addWidget(self.combo_box)
self.setLayout(layout)
def init_tree_view(self):
self.tree_view = QTreeView()
self.tree_view.setRootIsDecorated(False)
self.tree_view.setWordWrap(True)
self.tree_view.setAlternatingRowColors(True)
self.tree_view.setSelectionMode(QTreeView.ExtendedSelection)
self.tree_view.header().hide()
self.tree_me = QTreeView()
self.tree_me.setRootIsDecorated(False)
self.tree_me.setWordWrap(True)
self.tree_me.setAlternatingRowColors(True)
self.tree_me.setSelectionMode(QTreeView.ExtendedSelection)
self.tree_me.header().hide()
def init_complete(self, model=None):
# add a completer, which uses the filter model
# add a filter model to filter matching items
filterModel = QSortFilterProxyModel(self.combo_box)
filterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
filterModel.setSourceModel(model)
filterModel.setFilterKeyColumn(0)
completer = QCompleter(self.combo_box)
# Set the model that the QCompleter uses
# on model column change, update the model
# column of the filter and completer as well
completer.setModel(filterModel)
completer.setCompletionColumn(0)
completer.popup().installEventFilter(self)
completer.popup().selectionModel().selectionChanged.connect(lambda new_index:
self.get_id_tree_view(new_index=new_index))
# always show all (filtered) completions
completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
completer.setPopup( self.tree_me )
self.tree_me.setColumnHidden(1, True)
self.combo_box.setEditable(True)
self.combo_box.setCompleter(completer)
# on model column change, update the model
# column of the filter and completer as well
self.combo_box.setModel(model)
self.combo_box.setView(self.tree_view)
# on model column change, update the model column of
# the filter and completer as well
self.combo_box.setModelColumn(0)
self.tree_view.resizeColumnToContents(0)
self.tree_view.setColumnHidden(1, True)
if self.combo_box.isEditable():
self.app.connect(self.combo_box.lineEdit(), SIGNAL('textEdited(QString)'), filterModel.setFilterFixedString)
def set_tree_view_model(self, model):
self.tree_view.setModel(model)
def generator_header_data(self, list_header):
for header_data in list_header:
yield header_data
def set_header_data(self, list_header_data=None, model=None):
count_column = 0
for header_data in self.generator_header_data(list_header_data):
model.setHeaderData(count_column, Qt.Horizontal, header_data)
count_column +=1
def get_id_tree_view(self, new_index=None):
try:
if not new_index is None:
index = new_index.indexes()[1].data()#.toPyObject()
if isinstance(index, QVariant):
print "get_id_tree_view, index", index.toString()
except IndexError as InErr:
pass#print "InErr", InErr
def populate_data_item(self, item_list=None, model=None):
count_items = len(item_list)
if count_items == 2:
item_first, item_second = item_list
two_columns_item = [QStandardItem(item_second), QStandardItem(str(item_first))]
model.appendRow(two_columns_item)
def populate(self, model=None):
for single_list in self.food_list:
self.populate_data_item(item_list=single_list, model=model)
def main():
app = QApplication(sys.argv)
window = MyCustomDialog(app=app)
window.resize(300, 50)
window.show()
try:
sip.setdestroyonexit(False)
except:
# missing in older versions
pass
sys.exit(app.exec_())
if __name__ == "__main__":
main()
http://doc.qt.io/qt-4.8/qcombobox.html#details
When the user enters a new string in an editable combobox, the widget may or may not insert it, and it can insert it in several locations. The default policy is is AtBottom but you can change this using setInsertPolicy().
http://doc.qt.io/qt-4.8/qcombobox.html#insertPolicy-prop
void setInsertPolicy(InsertPolicy policy)
QComboBox::NoInsert - The string will not be inserted into the combobox.