Python - 在可编辑的 Gtk.TreeView 单元格中自动完成
Python - AutoComplete in an Editable Gtk.TreeView Cell
我最近在用 QTable 中的 QComboBox 编写 PyQt 代码。默认情况下,QComboBox 具有自动完成功能。
我想尝试用 Gtk3 在 Python3 中重现它。我遇到了这个例子:
Gtk.Entry in Gtk.TreeView (CellRenderer)
似乎已成功将自动完成功能添加到 Treeview 中的组合框。该示例不完整,我希望有人能给我一个完整的工作示例。我不知道我如何 'connect' CellRendererAutoComplete class 到树视图中的列之一。
我真正想要的是在可编辑的 TreeView 单元格(有或没有 ComboBox)中有自动完成功能,但我过去在 Gtk 中从未遇到过这个。
谢谢。
这是一个代码示例:
#
# https://python-gtk-3-tutorial.readthedocs.io/en/latest/cellrenderers.html
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
#######################################################################
class CellRendererAutoComplete(Gtk.CellRendererText):
""" Text entry cell which accepts a Gtk.EntryCompletion object """
__gtype_name__ = 'CellRendererAutoComplete'
def __init__(self, completion):
self.completion = completion
Gtk.CellRendererText.__init__(self)
def do_start_editing(
self, event, treeview, path, background_area, cell_area, flags):
if not self.get_property('editable'):
return
entry = Gtk.Entry()
entry.set_completion(self.completion)
entry.connect('editing-done', self.editing_done, path)
entry.show()
entry.grab_focus()
return entry
def editing_done(self, entry, path):
self.emit('edited', path, entry.get_text())
#######################################################################
class CellRendererTextWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="CellRendererText Example")
self.set_default_size(200, 200)
self.liststore = Gtk.ListStore(str, str)
self.liststore.append(["Fedora", "http://fedoraproject.org/"])
self.liststore.append(["Slackware", "http://www.slackware.com/"])
self.liststore.append(["Sidux", "http://sidux.com/"])
treeview = Gtk.TreeView(model=self.liststore)
renderer_text = Gtk.CellRendererText()
column_text = Gtk.TreeViewColumn("Text", renderer_text, text=0)
treeview.append_column(column_text)
renderer_editabletext = Gtk.CellRendererText()
renderer_editabletext.set_property("editable", True)
########
# This is the problem area, I suppose, but I'm not sure
x = CellRendererAutoComplete()
renderer_editabletext.connect('on_edit',x(renderer_editabletext))
########
column_editabletext = Gtk.TreeViewColumn("Editable Text",renderer_editabletext, text=1)
treeview.append_column(column_editabletext)
renderer_editabletext.connect("edited", self.text_edited)
self.add(treeview)
def text_edited(self, widget, path, text):
self.liststore[path][1] = text
win = CellRendererTextWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()
下面是一个使用 EntryCompletion 显示 CellRendererText 和 CellRendererCombo 的示例。
由于Treeview的复杂性,一个ListStore可以是Completion, Combo, and Entry
后面的model,另一个是Treeview后面的model,大家应该很好掌握Gtk.Treeview理解这个例子。请注意,此示例仅使用一个 Liststore,并且 CellRendererText 和 CellRendererColumn 仅使用一个可编辑列。这使示例变得混乱,但它是我能想到的最简单的示例,因为我不知道此 Treeview 的预期用途。
#!/usr/bin/python
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class CellRendererTextWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="CellRendererText Example")
self.set_default_size(200, 200)
self.liststore = Gtk.ListStore(str, str)
self.liststore.append(["Fedora", "http://fedoraproject.org/"])
self.liststore.append(["Slackware", "http://www.slackware.com/"])
self.liststore.append(["Sidux", "http://sidux.com/"])
treeview = Gtk.TreeView(model=self.liststore)
self.completion = Gtk.EntryCompletion(model = self.liststore)
self.completion.set_text_column(1)
self.completion.connect('match-selected', self.renderer_match_selected)
renderer_text = Gtk.CellRendererText()
column_text = Gtk.TreeViewColumn("Text", renderer_text, text=0)
treeview.append_column(column_text)
######## CellRendererText with EntryCompletion example
renderer_text = Gtk.CellRendererText()
renderer_text.connect('editing-started', self.renderer_text_editing_started)
renderer_text.connect('edited', self.text_edited)
renderer_text.set_property("editable", True)
column_text_autocomplete = Gtk.TreeViewColumn("Editable Text", renderer_text, text=1)
treeview.append_column(column_text_autocomplete)
######## CellRendererCombo with EntryCompletion example
renderer_combo = Gtk.CellRendererCombo(model = self.liststore)
renderer_combo.set_property("text-column", 1)
renderer_combo.connect('editing-started', self.renderer_combo_editing_started)
renderer_combo.connect('changed', self.combo_changed)
renderer_combo.set_property("editable", True)
column_combo_autocomplete = Gtk.TreeViewColumn("Editable Combo", renderer_combo, text=1)
treeview.append_column(column_combo_autocomplete)
self.add(treeview)
def renderer_match_selected (self, completion, model, tree_iter):
''' beware ! the model and tree_iter passed in here are the model from the
EntryCompletion, which may or may not be the same as the model of the Treeview '''
text_match = model[tree_iter][1]
self.liststore[self.path][1] = text_match
def renderer_text_editing_started (self, renderer, editable, path):
''' since the editable widget gets created for every edit, we need to
connect the completion to every editable upon creation '''
editable.set_completion(self.completion)
self.path = path # save the path for later usage
def text_edited(self, widget, path, text):
self.liststore[path][1] = text
def renderer_combo_editing_started (self, renderer, combo, path):
''' since the editable widget gets created for every edit, we need to
connect the completion to every editable upon creation '''
editable = combo.get_child() # get the entry of the combobox
editable.set_completion(self.completion)
self.path = path # save the path for later usage
def combo_changed (self, combo, path, tree_iter):
''' the path is from the treeview and the tree_iter is from the model
of the combobox which may or may not be the same model as the treeview'''
combo_model = combo.get_property('model')
text = combo_model[tree_iter][1]
self.liststore[path][1] = text
win = CellRendererTextWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()
在官方docs中明确指出editing-started
的目的是添加一个EntryCompletion等。我也继承了Gtk.CellRendererText才发现那个小提示文档。
我最近在用 QTable 中的 QComboBox 编写 PyQt 代码。默认情况下,QComboBox 具有自动完成功能。 我想尝试用 Gtk3 在 Python3 中重现它。我遇到了这个例子:
Gtk.Entry in Gtk.TreeView (CellRenderer)
似乎已成功将自动完成功能添加到 Treeview 中的组合框。该示例不完整,我希望有人能给我一个完整的工作示例。我不知道我如何 'connect' CellRendererAutoComplete class 到树视图中的列之一。
我真正想要的是在可编辑的 TreeView 单元格(有或没有 ComboBox)中有自动完成功能,但我过去在 Gtk 中从未遇到过这个。
谢谢。
这是一个代码示例:
#
# https://python-gtk-3-tutorial.readthedocs.io/en/latest/cellrenderers.html
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
#######################################################################
class CellRendererAutoComplete(Gtk.CellRendererText):
""" Text entry cell which accepts a Gtk.EntryCompletion object """
__gtype_name__ = 'CellRendererAutoComplete'
def __init__(self, completion):
self.completion = completion
Gtk.CellRendererText.__init__(self)
def do_start_editing(
self, event, treeview, path, background_area, cell_area, flags):
if not self.get_property('editable'):
return
entry = Gtk.Entry()
entry.set_completion(self.completion)
entry.connect('editing-done', self.editing_done, path)
entry.show()
entry.grab_focus()
return entry
def editing_done(self, entry, path):
self.emit('edited', path, entry.get_text())
#######################################################################
class CellRendererTextWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="CellRendererText Example")
self.set_default_size(200, 200)
self.liststore = Gtk.ListStore(str, str)
self.liststore.append(["Fedora", "http://fedoraproject.org/"])
self.liststore.append(["Slackware", "http://www.slackware.com/"])
self.liststore.append(["Sidux", "http://sidux.com/"])
treeview = Gtk.TreeView(model=self.liststore)
renderer_text = Gtk.CellRendererText()
column_text = Gtk.TreeViewColumn("Text", renderer_text, text=0)
treeview.append_column(column_text)
renderer_editabletext = Gtk.CellRendererText()
renderer_editabletext.set_property("editable", True)
########
# This is the problem area, I suppose, but I'm not sure
x = CellRendererAutoComplete()
renderer_editabletext.connect('on_edit',x(renderer_editabletext))
########
column_editabletext = Gtk.TreeViewColumn("Editable Text",renderer_editabletext, text=1)
treeview.append_column(column_editabletext)
renderer_editabletext.connect("edited", self.text_edited)
self.add(treeview)
def text_edited(self, widget, path, text):
self.liststore[path][1] = text
win = CellRendererTextWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()
下面是一个使用 EntryCompletion 显示 CellRendererText 和 CellRendererCombo 的示例。
由于Treeview的复杂性,一个ListStore可以是Completion, Combo, and Entry
后面的model,另一个是Treeview后面的model,大家应该很好掌握Gtk.Treeview理解这个例子。请注意,此示例仅使用一个 Liststore,并且 CellRendererText 和 CellRendererColumn 仅使用一个可编辑列。这使示例变得混乱,但它是我能想到的最简单的示例,因为我不知道此 Treeview 的预期用途。
#!/usr/bin/python
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class CellRendererTextWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="CellRendererText Example")
self.set_default_size(200, 200)
self.liststore = Gtk.ListStore(str, str)
self.liststore.append(["Fedora", "http://fedoraproject.org/"])
self.liststore.append(["Slackware", "http://www.slackware.com/"])
self.liststore.append(["Sidux", "http://sidux.com/"])
treeview = Gtk.TreeView(model=self.liststore)
self.completion = Gtk.EntryCompletion(model = self.liststore)
self.completion.set_text_column(1)
self.completion.connect('match-selected', self.renderer_match_selected)
renderer_text = Gtk.CellRendererText()
column_text = Gtk.TreeViewColumn("Text", renderer_text, text=0)
treeview.append_column(column_text)
######## CellRendererText with EntryCompletion example
renderer_text = Gtk.CellRendererText()
renderer_text.connect('editing-started', self.renderer_text_editing_started)
renderer_text.connect('edited', self.text_edited)
renderer_text.set_property("editable", True)
column_text_autocomplete = Gtk.TreeViewColumn("Editable Text", renderer_text, text=1)
treeview.append_column(column_text_autocomplete)
######## CellRendererCombo with EntryCompletion example
renderer_combo = Gtk.CellRendererCombo(model = self.liststore)
renderer_combo.set_property("text-column", 1)
renderer_combo.connect('editing-started', self.renderer_combo_editing_started)
renderer_combo.connect('changed', self.combo_changed)
renderer_combo.set_property("editable", True)
column_combo_autocomplete = Gtk.TreeViewColumn("Editable Combo", renderer_combo, text=1)
treeview.append_column(column_combo_autocomplete)
self.add(treeview)
def renderer_match_selected (self, completion, model, tree_iter):
''' beware ! the model and tree_iter passed in here are the model from the
EntryCompletion, which may or may not be the same as the model of the Treeview '''
text_match = model[tree_iter][1]
self.liststore[self.path][1] = text_match
def renderer_text_editing_started (self, renderer, editable, path):
''' since the editable widget gets created for every edit, we need to
connect the completion to every editable upon creation '''
editable.set_completion(self.completion)
self.path = path # save the path for later usage
def text_edited(self, widget, path, text):
self.liststore[path][1] = text
def renderer_combo_editing_started (self, renderer, combo, path):
''' since the editable widget gets created for every edit, we need to
connect the completion to every editable upon creation '''
editable = combo.get_child() # get the entry of the combobox
editable.set_completion(self.completion)
self.path = path # save the path for later usage
def combo_changed (self, combo, path, tree_iter):
''' the path is from the treeview and the tree_iter is from the model
of the combobox which may or may not be the same model as the treeview'''
combo_model = combo.get_property('model')
text = combo_model[tree_iter][1]
self.liststore[path][1] = text
win = CellRendererTextWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()
在官方docs中明确指出editing-started
的目的是添加一个EntryCompletion等。我也继承了Gtk.CellRendererText才发现那个小提示文档。