Python PyQt Tab Completion example
This is my OLD blog. I've copied this post over to my NEW blog at:
http://www.saltycrane.com/blog/2008/01/python-pyqt-tab-completion-example/
You should be redirected in 2 seconds.
Here is an example Python GUI that implements tab completion. It uses the open source Qt 4.3 toolkit and PyQt 4.3 Python bindings.
A list of words is presented in a list box. As the user types, the list is shortened to show possible matches. If the user presses TAB, the input text is "completed" to the longest possible string match. This may be a whole word or a common substring of multiple words.
This example consists of two basic elements:
MyLineEdit
is a subclass of theQLineEdit
class. It is used as an input box to enter text. I needed to subclassQLineEdit
because I needed to capture the TAB key press event for tab completion. (See this previous post.)-
QListView
andMyListModel
implement a list with a simple model/view architechture.MyListModel
is a subclass ofQAbstractListModel
. I implemented the requiredrowCount
anddata
methods as well as a method calledsetAllData
which replaces the entire existing data with a new list of data.
This example makes use of two SIGNAL
s:
- The
textChanged
signal is emitted each time the user types a letter inside theQLineEdit
box. It is connected to thetext_changed
method which updates the list of words in theQListView
.MyListModel
'ssetAllData
method is used to update the data. - The
tabPressed
signal is a custom signal I added to myQLineEdit
subclass. It is emitted each time the user presses the TAB key. This signal is connected thetab_pressed
method which completes the input to the longest matching substring of the available words.
import sys from PyQt4.QtCore import * from PyQt4.QtGui import * LIST_DATA = ['a', 'aardvark', 'aardvarks', 'aardwolf', 'aardwolves', 'abacus', 'babel', 'bach', 'cache', 'daggle', 'facet', 'kabob', 'kansas'] #################################################################### def main(): app = QApplication(sys.argv) w = MyWindow() w.show() sys.exit(app.exec_()) #################################################################### class MyWindow(QWidget): def __init__(self, *args): QWidget.__init__(self, *args) # create objects self.la = QLabel("Start typing to match items in list:") self.le = MyLineEdit() self.lm = MyListModel(LIST_DATA, self) self.lv = QListView() self.lv.setModel(self.lm) # layout layout = QVBoxLayout() layout.addWidget(self.la) layout.addWidget(self.le) layout.addWidget(self.lv) self.setLayout(layout) # connections self.connect(self.le, SIGNAL("textChanged(QString)"), self.text_changed) self.connect(self.le, SIGNAL("tabPressed"), self.tab_pressed) def text_changed(self): """ updates the list of possible completions each time a key is pressed """ pattern = str(self.le.text()) self.new_list = [item for item in LIST_DATA if item.find(pattern) == 0] self.lm.setAllData(self.new_list) def tab_pressed(self): """ completes the word to the longest matching string when the tab key is pressed """ # only one item in the completion list if len(self.new_list) == 1: newtext = self.new_list[0] + " " self.le.setText(newtext) # more than one remaining matches elif len(self.new_list) > 1: match = self.new_list.pop(0) for word in self.new_list: match = string_intersect(word, match) self.le.setText(match) #################################################################### class MyLineEdit(QLineEdit): def __init__(self, *args): QLineEdit.__init__(self, *args) def event(self, event): if (event.type()==QEvent.KeyPress) and (event.key()==Qt.Key_Tab): self.emit(SIGNAL("tabPressed")) return True return QLineEdit.event(self, event) #################################################################### class MyListModel(QAbstractListModel): def __init__(self, datain, parent=None, *args): """ datain: a list where each item is a row """ QAbstractTableModel.__init__(self, parent, *args) self.listdata = datain def rowCount(self, parent=QModelIndex()): return len(self.listdata) def data(self, index, role): if index.isValid() and role == Qt.DisplayRole: return QVariant(self.listdata[index.row()]) else: return QVariant() def setAllData(self, newdata): """ replace all data with new data """ self.listdata = newdata self.reset() #################################################################### def string_intersect(str1, str2): newlist = [] for i,j in zip(str1, str2): if i == j: newlist.append(i) else: break return ''.join(newlist) #################################################################### if __name__ == "__main__": main()
No comments:
Post a Comment