【问题标题】:Python - AutoComplete in an Editable Gtk.TreeView CellPython - 在可编辑的 Gtk.TreeView 单元格中自动完成
【发布时间】:2019-11-29 20:24:34
【问题描述】:

我最近在 QTable 中使用 QComboBox 编写 PyQt。默认情况下,QComboBox 具有自动完成功能。 我想尝试用 Gtk3 在 Python3 中重现这个。我遇到了这个例子:

Gtk.Entry in Gtk.TreeView (CellRenderer)

这似乎已成功地将自动完成添加到 Treeview 中的 ComboBox。该示例不完整,我希望有人能给我一个完整的工作示例。我不知道如何将 CellRendererAutoComplete 类“连接”到树视图中的一列。

我真正想要的是在可编辑的 TreeView 单元格中拥有 AutoCompletion(有或没有 ComboBox),但我过去在 Gtk 中从未遇到过这种情况。

谢谢。

这是一个代码示例:

# https://stackoverflow.com/questions/13756787/
# 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()

【问题讨论】:

  • 您想让您的代码正常工作吗?或者我可以重新设计您的代码以提供一个更简单的示例吗?换句话说,这是一个更大的项目的一部分,我需要维护结构来为您提供示例吗?
  • 一个更简单的例子会很棒!我只是从源代码中复制了代码,因为我只是处于初步阶段。谢谢。

标签: python-3.x autocomplete treeview gtk


【解决方案1】:

所以这里是一个使用 EntryCompletion 显示 CellRendererText 和 CellRendererCombo 的示例。

由于Treeview的复杂性,一个ListStore可以是Completion, Combo, and Entry后面的模型,另一个模型可以是Treeview后面,你应该对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,然后在文档中发现了这个小提示。

【讨论】:

  • 非常感谢Gtknerd。我认为您应该将您的句柄更改为 GtkGuru!这正是我想要的,我很感激你一定花了一些时间来写这篇文章。它比我预想的要复杂得多,而且超出了我有限的能力,但我从中学到了很多。再次感谢
  • 这是一个all the bells and whistles 的例子。我本来想提供一个最小的示例,但是到目前为止我在 Internet 上找到的所有其他示例都没有足够的信息,所以我想我会发布一个更完整的示例。可悲的是,这使这种方式更加复杂。试着把它分解成小块然后这样消化,或者去掉所有多余的,只使用你需要的。
猜你喜欢
  • 1970-01-01
  • 2013-02-10
  • 2021-10-01
  • 2012-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多