Как ограничить самую правую ширину Gtk.TreeViewColumn внутри Gtk.ScrolledWindow?

Я не могу предотвратить расширение правого столбца a.

Как настоящийGtk.TreeViewможет отображать большее количество строк, что обычно несколько превышает высоту экрана, он встроен в файл . Это требуется . Без этого добавление пустой сетки справа от древовидной структуры, расширяющейся по горизонтали, решило бы проблему. Основываясь на этой идее, я попробовал обходной путь, который создает еще одну трудность (см. ниже).

Я построил минимальный рабочий пример из примера из https://python-gtk-3-tutorial.readthedocs.io/en/latest/treeview.html#filtering , без фильтрации и кнопок; и столбцы имеют ширину не менее 80 пикселей (это работает), а их содержимое центрировано по горизонтали. Эта последняя деталь делает видимым горизонтальное расширение самого правого столбца. В исходном примере он тоже расширяется, но, поскольку все выровнено по левому краю, этого не видно. Мне бы хотелось, чтобы содержимое столбцов было центрировано, а правый край не расширялся.

Этот пример минимален, но содержит некоторые полезные функции: вы найдете интерактивные заголовки столбцов, которые будут отображать некоторую информацию о выбранном столбце в консоли; кнопка удаления (отлично работает, удаляет выбранные строки) и кнопка вставки, которая позволяет вставлять новые строки из выделения (например, из выбранных строк из электронной таблицы, но нет ничего, чтобы проверить правильность данных, если вы вставляете что-то, что делает не конвертировать в int, он просто рухнет).

Обходной путь

Обходной путь, который я пробовал, состоит в том, чтобы собрать как древовидную структуру, так и горизонтально расширяющуюся пустую правую сетку справа от нее внутри сетки, которая будет помещена в файл . Это работает, но вызывает другие тонкие проблемы: в некоторых ситуациях древовидное представление не обновляется (это происходит через некоторое время), но ничто не мешает основному циклу обновить представление (например, в фоновом режиме нет другой обработки). Чтобы поэкспериментировать с этим обходным путем: закомментируйте и раскомментируйте строки, как описано в приведенном ниже коде; запустить программу черезpython script.py(если вам нужно установить pygobject в venv, см. здесь ), обратите внимание, что самый правый столбец больше не расширяется вправо, выберите 3 первых строки и нажмите «удалить», затем в электронной таблице выберите 3 строки фиктивных целые числа, как показано ниже, а затем нажмите «вставить». Прокрутите вниз до последних строк: в большинстве случаев вы увидите , что 3 вставленные строки не отображаются, даже если можно прокрутить последнюю строку. Возможно, через какое-то время появится один из них, затем другой... (или просто выберите строку, и они появятся). Как ни странно, это происходит, если вы только что удалили столько строк, сколько хотите вставить после удаления (3 удалены, 3 вставлены или 4 удалены, 4 вставлены и т. д.).

Пример выбора таблицы:

Вопрос

Итак, я бы предпочел избежать обходного пути (боюсь, я могу найти другие ситуации, вызывающие плохое обновление дерева), которые я не мог исправить (например, установкаself.scrollable_treelist.set_propagate_natural_height(True)оказался бесполезным, может быть, я не правильно его использую?) и только прикрепляю само дерево прямо вGtk.ScrolledWindow. Тогда как предотвратить расширение самого правого столбца?

(Я пытался использовать достаточное количество сеттеров и свойств средств визуализации ячеек, древовидного представления, столбцов древовидного представления, прокручиваемого окна, но безрезультатно. Некоторые из них все еще находятся в приведенном ниже коде.)

Однако любое решение, использующее и исправляющее обходной путь, описанный выше, будет принято.

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

Исходный код

      import gi

try:
    gi.require_version('Gtk', '3.0')
except ValueError:
    raise
else:
    from gi.repository import Gtk, Gdk

# ints to feed the store
data_list = [(i, 2 * i, 3 * i, 4 * i, 5 * i) for i in range(40)]


class AppWindow(Gtk.Window):
    def __init__(self):
        super().__init__(title="Treeview Columns Size Demo")
        self.set_border_width(10)

        # Setting up the self.grid in which the elements are to be positioned
        self.grid = Gtk.Grid()
        self.grid.set_column_homogeneous(True)
        self.grid.set_row_homogeneous(True)
        self.add(self.grid)

        # Creating the ListStore model
        self.store = Gtk.ListStore(int, int, int, int, int)
        for data_ref in data_list:
            self.store.append(list(data_ref))

        # creating the treeview and adding the columns
        self.treeview = Gtk.TreeView(model=self.store)
        rend = Gtk.CellRendererText()
        rend.set_alignment(0.5, 0.5)
        for i, column_title in enumerate([f'n×{p}' for p in [1, 2, 3, 4, 5]]):
            column = Gtk.TreeViewColumn(column_title, rend, text=i)
            column.set_min_width(80)
            # column.set_max_width(80)
            # column.set_fixed_width(80)
            # column.set_sizing(Gtk.TreeViewColumnSizing(1))
            column.set_alignment(0.5)
            column.set_clickable(True)
            column.connect('clicked', self.on_column_clicked)
            self.treeview.append_column(column)

        self.treeview.set_hexpand(False)
        self.treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE)

        # Put the treeview in a scrolled window
        self.scrollable_treelist = Gtk.ScrolledWindow()
        self.scrollable_treelist.set_vexpand(True)
        self.grid.attach(self.scrollable_treelist, 0, 0, 8, 10)

        self.scrollable_treelist.add(self.treeview)
        # WORKAROUND
        # Alternatively, embed the treeview inside a grid containing an
        # empty grid to the right of the treeview
        # To try it: comment out the previous line; uncomment next lines
        # scrolled_grid = Gtk.Grid()
        # empty_grid = Gtk.Grid()
        # empty_grid.set_hexpand(True)
        # scrolled_grid.attach(self.treeview, 0, 0, 8, 10)
        # scrolled_grid.attach_next_to(empty_grid, self.treeview,
        #                              Gtk.PositionType.RIGHT, 1, 1)
        # self.scrollable_treelist.add(scrolled_grid)
        # self.scrollable_treelist.set_propagate_natural_height(True)

        # Buttons
        self.remove_button = Gtk.Button(label='Remove')
        self.remove_button.connect('clicked', self.on_remove_clicked)
        self.paste_button = Gtk.Button(label='Paste')
        self.paste_button.connect('clicked', self.on_paste_clicked)

        self.grid.attach_next_to(self.remove_button, self.scrollable_treelist,
                                 Gtk.PositionType.TOP, 1, 1)

        self.grid.attach_next_to(self.paste_button, self.remove_button,
                                 Gtk.PositionType.RIGHT, 1, 1)

        self.set_default_size(800, 500)
        self.show_all()

        # Clipboard (to insert several rows)
        self.clip = Gtk.Clipboard.get(Gdk.SELECTION_PRIMARY)
        self.clip2 = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)

    def on_column_clicked(self, col):
        print(f'col.get_sizing()={col.get_sizing()}')
        print(f'col.get_expand()={col.get_expand()}')
        print(f'col.get_width()={col.get_width()}')
        print(f'col.get_min_width()={col.get_min_width()}')
        print(f'col.get_max_width()={col.get_max_width()}')
        print(f'col.get_fixed_width()={col.get_fixed_width()}')

    def on_remove_clicked(self, widget):
        model, paths = self.treeview.get_selection().get_selected_rows()
        refs = []
        for path in paths:
            refs.append(Gtk.TreeRowReference.new(model, path))
        for ref in refs:
            path = ref.get_path()
            treeiter = model.get_iter(path)
            model.remove(treeiter)
        # print(f'AFTER REMOVAL, REMAINING ROWS={[str(r[0]) for r in model]}')

    def on_paste_clicked(self, widget):
        text = self.clip.wait_for_text()
        if text is None:
            text = self.clip2.wait_for_text()
        if text is not None:
            lines = text.split('\n')  # separate the lines
            lines = [tuple(L.split('\t')) for L in lines]  # convert to tuples
            print(f'PASTE LINES={lines}')
            for line in lines:
                if len(line) == 5:
                    line = tuple(int(value) for value in line)
                    self.store.append(line)


win = AppWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

0 ответов

Другие вопросы по тегам