Синхронизируйте редактируемый Gtk.TreeView с его ListStore - PullRequest
0 голосов
/ 09 июня 2018

Я создаю интерфейс в Gtk3 / Python3, использую Glade, показываю данные из ListStore в TreeView и позволяю пользователю редактировать значения в одном из столбцов.

Как уже говорилось, я 'м, используя glade, и в файле glade написано, какой столбец ListStore содержит данные для каждого GtkCellRenderer.Первое, что забавно, я не знаю, как получить эту информацию, и я ввожу избыточность, чтобы все работало.

Следующая более интересная проблема: когда отредактированная ячейка теряет фокус, но фокусируетсяостается в TreeView, мой обратный вызов для сигнала edited вызывается, и я могу сохранить отредактированное значение в ListStore.

Когда отредактированная ячейка теряет фокус, и фокус переходит к другому виджету (как вдалее бесполезная кнопка в примере), зарегистрированный обратный вызов не вызывается.Также, если окно теряет фокус, предыдущее значение восстанавливается.Последнее особенно непрактично в случае «focus-follow-mouse».

В чем дело?

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk


class TestWindow:

    def __init__(self, builder):
        import os.path
        path, name = os.path.split(__file__)
        builder.add_from_file(os.path.join(path, "treeedit.glade"))
        builder.connect_signals(self)
        self.window = builder.get_object("window1")
        self.window.connect("destroy", Gtk.main_quit)
        self.notes_list = builder.get_object("notes_list")
        self.notes_list.append(('a',))
        self.notes_list.append(('b',))
        self.notes_list.append(('c',))
        self.notes_list.append(('d',))

    def on_cell_edited(self, widget, path, text):
        self.notes_list[path][0] = text

    def show_all(self):
        self.window.show_all()


builder = Gtk.Builder()
win = TestWindow(builder)
win.show_all()
Gtk.main()

и это файл glade:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkListStore" id="notes_list">
    <columns>
      <!-- column-name content -->
      <column type="gchararray"/>
    </columns>
  </object>
  <object class="GtkDialog" id="window1">
    <property name="can_focus">False</property>
    <property name="type_hint">dialog</property>
    <child internal-child="vbox">
      <object class="GtkBox">
        <property name="orientation">vertical</property>
        <property name="spacing">2</property>
        <child>
          <object class="GtkButton">
            <property name="label" translatable="yes">button</property>
          </object>
        </child>
        <child>
          <object class="GtkFrame">
            <property name="visible">True</property>
            <child>
              <object class="GtkAlignment">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="left_padding">12</property>
                <child>
                  <object class="GtkTreeView" id="notes_tree">
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="hexpand">True</property>
                    <property name="vexpand">True</property>
                    <property name="model">notes_list</property>
                    <property name="headers_clickable">False</property>
                    <child internal-child="selection">
                      <object class="GtkTreeSelection"/>
                    </child>
                    <child>
                      <object class="GtkTreeViewColumn">
                        <property name="resizable">True</property>
                        <property name="title" translatable="yes">value</property>
                        <child>
                          <object class="GtkCellRendererText" id="prefs_cellrenderertext1">
                            <property name="editable">True</property>
                            <signal name="edited" handler="on_cell_edited" swapped="no"/>
                          </object>
                          <attributes>
                            <attribute name="text">0</attribute>
                          </attributes>
                        </child>
                      </object>
                    </child>
                  </object>
                </child>
              </object>
            </child>
            <child type="label">
              <object class="GtkLabel">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Notes</property>
              </object>
            </child>
          </object>
        </child>
      </object>
    </child>
  </object>
</interface>

Мой собственный ответ - это только частичный ответ, потому что, если мне нужно отредактировать несколько столбцов?на данный момент я прибегаю к записи нескольких обратных вызовов для сигнала editing-started, например:

def on_cell_editing_started_col0(self, *args):
    self.column = 0

def on_cell_editing_started_col1(self, *args):
    self.column = 1

, затем я использую значение self.column в обоих обратных вызовах для Gtk.CellRendererText edited сигнал и Gtk.TreeView set-focus-child сигнал.

1 Ответ

0 голосов
/ 09 июня 2018

Похоже, я могу зарегистрировать обратный вызов для сигнала set-focus-child для контейнера TreeView.Это вызывается, когда редактируемый дочерний элемент начинает редактироваться, и когда редактирование заканчивается.В обоих случаях обратный вызов получает два параметра, первым из которых является сам TreeView.

Когда начинается редактирование, вторым параметром является временный Gtk.Entry, с которым взаимодействует пользователь.Когда редактирование заканчивается, вторым параметром является None.

. Я мог бы использовать этот код, и я уверен, что не знаю, насколько надежным он может быть:

def on_focus_child(self, tree, entry):
    if entry is not None:
        self.last_entry = entry
    else:
        tv, path = tree.get_selection().get_selected()
        self.notes_list[path][0] = self.last_entry.get_text()
...