Gtk.TreeView显示数据的能力比较强大。通常与Gtk.ListStore或Gtk.TreeStore连在一起使用。提供很多显示和操纵数据的方法:
Gtk.TreeView是Gtk.Container的直接子类
方法修饰词 | 方法名及参数 |
---|---|
static | new () |
static | new_with_model (model) |
append_column (column) | |
collapse_all () | |
collapse_row (path) | |
columns_autosize () | |
convert_bin_window_to_tree_coords (bx, by) | |
convert_bin_window_to_widget_coords (bx, by) | |
convert_tree_to_bin_window_coords (tx, ty) | |
convert_tree_to_widget_coords (tx, ty) | |
convert_widget_to_bin_window_coords (wx, wy) | |
convert_widget_to_tree_coords (wx, wy) | |
create_row_drag_icon (path) | |
enable_model_drag_dest (targets, actions) | |
enable_model_drag_source (start_button_mask, targets, actions) | |
expand_all () | |
expand_row (path, open_all) | |
expand_to_path (path) | |
get_activate_on_single_click () | |
get_background_area (path, column) | |
get_bin_window () | |
get_cell_area (path, column) | |
get_column (n) | |
get_columns () | |
get_cursor () | |
get_dest_row_at_pos (drag_x, drag_y) | |
get_drag_dest_row () | |
get_enable_search () | |
get_enable_tree_lines () | |
get_expander_column () | |
get_fixed_height_mode () | |
get_grid_lines () | |
get_hadjustment () | |
get_headers_clickable () | |
get_headers_visible () | |
get_hover_expand () | |
get_hover_selection () | |
get_level_indentation () | |
get_model () | |
get_n_columns () | |
get_path_at_pos (x, y) | |
get_reorderable () | |
get_rubber_banding () | |
get_rules_hint () | |
get_search_column () | |
get_search_entry () | |
get_selection () | |
get_show_expanders () | |
get_tooltip_column () | |
get_tooltip_context (x, y, keyboard_tip) | |
get_vadjustment () | |
get_visible_range () | |
get_visible_rect () | |
insert_column (column, position) | |
insert_column_with_attributes (position, title, cell, **kwargs) | |
insert_column_with_data_func (position, title, cell, func, *data) | |
is_blank_at_pos (x, y) | |
is_rubber_banding_active () | |
map_expanded_rows (func, *data) | |
move_column_after (column, base_column) | |
remove_column (column) | |
row_activated (path, column) | |
row_expanded (path) | |
scroll_to_cell (path, column, use_align, row_align, col_align) | |
scroll_to_point (tree_x, tree_y) | |
set_activate_on_single_click (single) | |
set_column_drag_function (func, *user_data) | |
set_cursor (path, focus_column, start_editing) | |
set_cursor_on_cell (path, focus_column, focus_cell, start_editing) | |
set_destroy_count_func (func, *data) | |
set_drag_dest_row (path, pos) | |
set_enable_search (enable_search) | |
set_enable_tree_lines (enabled) | |
set_expander_column (column) | |
set_fixed_height_mode (enable) | |
set_grid_lines (grid_lines) | |
set_hadjustment (adjustment) | |
set_headers_clickable (setting) | |
set_headers_visible (headers_visible) | |
set_hover_expand (expand) | |
set_hover_selection (hover) | |
set_level_indentation (indentation) | |
set_model (model) | |
set_reorderable (reorderable) | |
set_row_separator_func (func, *data) | |
set_rubber_banding (enable) | |
set_rules_hint (setting) | |
set_search_column (column) | |
set_search_entry (entry) | |
set_search_equal_func (search_equal_func, *search_user_data) | |
set_search_position_func (func, *data) | |
set_show_expanders (enabled) | |
set_tooltip_cell (tooltip, path, column, cell) | |
set_tooltip_column (column) | |
set_tooltip_row (tooltip, path) | |
set_vadjustment (adjustment) | |
unset_rows_drag_dest () | |
unset_rows_drag_source () |
do_columns_changed () |
do_cursor_changed () |
do_expand_collapse_cursor_row (logical, expand, open_all) |
do_move_cursor (step, count) |
do_row_activated (path, column) |
do_row_collapsed (iter, path) |
do_row_expanded (iter, path) |
do_select_all () |
do_select_cursor_parent () |
do_select_cursor_row (start_editing) |
do_start_interactive_search () |
do_test_collapse_row (iter, path) |
do_test_expand_row (iter, path) |
do_toggle_cursor_row () |
do_unselect_all () |
Name | Type | Flags | Short Description |
---|---|---|---|
activate-on-single-click | bool | r/w/en | Activate row on a single click |
enable-grid-lines | Gtk.TreeViewGridLines | r/w/en | Whether grid lines should be drawn in the tree view |
enable-search | bool | r/w/en | View allows user to search through columns interactively |
enable-tree-lines | bool | r/w/en | Whether tree lines should be drawn in the tree view |
expander-column | Gtk.TreeViewColumn | r/w | Set the column for the expander column |
fixed-height-mode | bool | r/w/en | Speeds up Gtk.TreeView by assuming that all rows have the same height |
headers-clickable | bool | r/w/en | Column headers respond to click events |
headers-visible | bool | r/w/en | Show the column header buttons |
hover-expand | bool | r/w/en | Whether rows should be expanded/collapsed when the pointer moves over them |
hover-selection | bool | r/w/en | Whether the selection should follow the pointer |
level-indentation | int | r/w/en | Extra indentation for each level |
model | Gtk.TreeModel | r/w | The model for the tree view |
reorderable | bool | r/w/en | View is reorderable |
rubber-banding | bool | r/w/en | Whether to enable selection of multiple items by dragging the mouse pointer |
rules-hint | bool | d/r/w/en | Set a hint to the theme engine to draw rows in alternating colors deprecated |
search-column | int | r/w/en | Model column to search through during interactive search |
show-expanders | bool | r/w/en | View has expanders |
tooltip-column | int | r/w/en | The column in the model containing the tooltip texts for the rows |
Name | Short Description |
---|---|
columns-changed | The number of columns of the treeview has changed. |
cursor-changed | The position of the cursor (focused cell) has changed. |
expand-collapse-cursor-row | |
move-cursor | The Gtk.TreeView ::move-cursor signal is a keybinding signal which gets emitted when the user presses one of the cursor keys. |
row-activated | The “row-activated” signal is emitted when the method Gtk.TreeView.row_activated() is called, when the user double clicks a treeview row with the “activate-on-single-click” property set to False, or when the user single clicks a row when the “activate-on-single-click” property set to True. |
row-collapsed | The given row has been collapsed (child nodes are hidden). |
row-expanded | The given row has been expanded (child nodes are shown). |
select-all | |
select-cursor-parent | |
select-cursor-row | |
start-interactive-search | |
test-collapse-row | The given row is about to be collapsed (hide its children nodes). |
test-expand-row | The given row is about to be expanded (show its children nodes). |
toggle-cursor-row | |
unselect-all |
每个Gtk.TreeView具有相关联的Gtk.TreeModel,其中包含TreeView显示的数据。每个Gtk.TreeModel可以由一个或以上的Gtk.TreeView使用。
虽然理论上可以实现自己的模型,通常使用Gtk.ListStore或Gtk.TreeStore模型类。 Gtk.ListStore包含数据的简单行,每行没有孩子,而Gtk.TreeStore包含的数据行,每行可有子行。
当构建一个模型,你必须为模型认为每列指定数据类型。
store = Gtk.ListStore(str, str, float)
创建了包含三列的Gtk.ListStore模型,两个string 列,一个float列
使用append方法往模型里面添加数据
treeiter = store.append(["The Art of Computer Programming", "Donald E. Knuth", 25.46])
方法返回一个Gtk.TreeIter实例,指向新插入一行的位置。可以使用Gtk.TreeModel.get_iter(path)方法获取Gtk.TreeIter实例。
一旦数据插入,可以通过 TreeIter和列索引获取或者修改数据
print(store[treeiter][2]) # Prints value of third column
store[treeiter][2] = 42.15
与Python的list一样,你可以使用len()来获得每行里面的数据个数和使用切片来获取或设置值
# Print number of rows
print(len(store))
# Print all but first column
print(store[treeiter][1:])
# Print last column
print(store[treeiter][-1])
# Set first two columns
store[treeiter][:2] = ["Donald Ervin Knuth", 41.99]
获取所有行内容
for row in store:
# Print values of all columns
print(row[:])
请记住,如果你使用Gtk.TreeStore,上面的代码将只迭代顶层的行,但没有节点的孩子。遍历所有的行和它的孩子,可使用print_tree_store方法
def print_tree_store(store):
rootiter = store.get_iter_first()
print_rows(store, rootiter, "")
def print_rows(store, treeiter, indent):
while treeiter != None:
print(indent + str(store[treeiter][:]))
if store.iter_has_child(treeiter):
childiter = store.iter_children(treeiter)
print_rows(store, childiter, indent + "\t")
treeiter = store.iter_next(treeiter)
获取某行内容,使用TreePath
# Get path pointing to 6th row in list store
path = Gtk.TreePath(5)
treeiter = liststore.get_iter(path)
# Get value at 2nd column
value = liststore.get_value(treeiter, 1)
获取某行某列内容
# Get path pointing to 5th child of 3rd row in tree store
path = Gtk.TreePath([2, 4])
treeiter = treestore.get_iter(path)
# Get value at 2nd column
value = treestore.get_value(treeiter, 1)
Gtk.TreePath的实例可以像列表被访问, len(treepath)返回项目的深度。
treepath[i]返回第i层孩子的索引
方法修饰词 | 方法名及参数 |
---|---|
filter_new (root) | |
foreach (func, *user_data) | |
get (treeiter, *columns) | |
get_column_type (index_) | |
get_flags () | |
get_iter (path) | |
get_iter_first () | |
get_iter_from_string (path_string) | |
get_n_columns () | |
get_path (iter) | |
get_string_from_iter (iter) | |
get_value (iter, column) | |
iter_children (parent) | |
iter_has_child (iter) | |
iter_n_children (iter) | |
iter_next (iter) | |
iter_nth_child (parent, n) | |
iter_parent (child) | |
iter_previous (iter) | |
ref_node (iter) | |
row_changed (path, iter) | |
row_deleted (path) | |
row_has_child_toggled (path, iter) | |
row_inserted (path, iter) | |
rows_reordered (path, iter, new_order) | |
set_row (treeiter, row) | |
sort_new_with_model () | |
unref_node (iter) |
do_get_column_type (index_) |
do_get_flags () |
do_get_iter (path) |
do_get_n_columns () |
do_get_path (iter) |
do_get_value (iter, column) |
do_iter_children (parent) |
do_iter_has_child (iter) |
do_iter_n_children (iter) |
do_iter_next (iter) |
do_iter_nth_child (parent, n) |
do_iter_parent (child) |
do_iter_previous (iter) |
do_ref_node (iter) |
do_row_changed (path, iter) |
do_row_deleted (path) |
do_row_has_child_toggled (path, iter) |
do_row_inserted (path, iter) |
do_unref_node (iter) |
Name | Short Description |
---|---|
row-changed | This signal is emitted when a row in the model has changed. |
row-deleted | This signal is emitted when a row has been deleted. |
row-has-child-toggled | This signal is emitted when a row has gotten the first child row or lost its last child row. |
row-inserted | This signal is emitted when a new row has been inserted in the model. |
rows-reordered | This signal is emitted when the children of a node in the Gtk.TreeModel have been reordered. |
方法修饰词 | 方法名及参数 |
---|---|
static | new (types) |
append (row=None) | |
clear () | |
insert (position, row=None) | |
insert_after (sibling, row=None) | |
insert_before (sibling, row=None) | |
insert_with_valuesv (position, columns, values) | |
iter_is_valid (iter) | |
move_after (iter, position) | |
move_before (iter, position) | |
prepend (row=None) | |
remove (iter) | |
reorder (new_order) | |
set (iter, columns, values) | |
set_column_types (types) | |
set_value (iter, column, value) | |
swap (a, b) |
方法修饰词 | 方法名及参数 |
---|---|
static | new (types) |
append (parent, row=None) | |
clear () | |
insert (parent, position, row=None) | |
insert_after (parent, sibling) | |
insert_before (parent, sibling, row=None) | |
insert_with_values (parent, position, columns, values) | |
is_ancestor (iter, descendant) | |
iter_depth (iter) | |
iter_is_valid (iter) | |
move_after (iter, position) | |
move_before (iter, position) | |
prepend (parent, row=None) | |
remove (iter) | |
set (iter, columns, values) | |
set_column_types (types) | |
set_value (iter, column, value) | |
swap (a, b) |
方法修饰词 | 方法名及参数 |
---|---|
static | new () |
static | new_first () |
static | new_from_indices (indices) |
static | new_from_string (path) |
append_index (index_) | |
compare (b) | |
copy () | |
down () | |
free () | |
get_depth () | |
get_indices () | |
is_ancestor (descendant) | |
is_descendant (ancestor) | |
next () | |
prepend_index (index_) | |
prev () | |
to_string () | |
up () |
方法修饰词 | 方法名及参数 |
---|---|
static | new () |
static | new_with_area (area) |
add_attribute (cell_renderer, attribute, column) | |
cell_get_position (cell_renderer) | |
cell_get_size (cell_area) | |
cell_is_visible () | |
cell_set_cell_data (tree_model, iter, is_expander, is_expanded) | |
clear () | |
clear_attributes (cell_renderer) | |
clicked () | |
focus_cell (cell) | |
get_alignment () | |
get_button () | |
get_clickable () | |
get_expand () | |
get_fixed_width () | |
get_max_width () | |
get_min_width () | |
get_reorderable () | |
get_resizable () | |
get_sizing () | |
get_sort_column_id () | |
get_sort_indicator () | |
get_sort_order () | |
get_spacing () | |
get_title () | |
get_tree_view () | |
get_visible () | |
get_widget () | |
get_width () | |
get_x_offset () | |
pack_end (cell, expand) | |
pack_start (cell, expand) | |
queue_resize () | |
set_alignment (xalign) | |
set_attributes (cell_renderer, **attributes) | |
set_cell_data_func (cell_renderer, func, *func_data) | |
set_clickable (clickable) | |
set_expand (expand) | |
set_fixed_width (fixed_width) | |
set_max_width (max_width) | |
set_min_width (min_width) | |
set_reorderable (reorderable) | |
set_resizable (resizable) | |
set_sizing (type) | |
set_sort_column_id (sort_column_id) | |
set_sort_indicator (setting) | |
set_sort_order (order) | |
set_spacing (spacing) | |
set_title (title) | |
set_visible (visible) | |
set_widget (widget) |
Treeview和TreeModel绑定,在Treeview的构造方法中指定模型
tree = Gtk.TreeView(store)
或者使用Gtk.TreeView.set_model()方法
tree.set_model(store)
一旦Gtk.TreeView小部件有一个模型,它需要知道如何显示模型。为此,它使用数据列和单元格渲染器来显示数据。
单元渲染器用于绘制树模型中的数据。有许多Gtk.CellRenderer类用来展示不同类型的数据,例如Gtk.CellRendererText,Gtk.CellRendererPixbuf和Gtk.CellRendererToggle单元格渲染器。此外,它比较容易自定义。
一个Gtk.TreeViewColumn是Gtk.TreeView中用来组织列的对象。它需要知道列的名称,使用什么类型的单元格渲染器,从模型行中的哪一列检索数据。
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Title", renderer, text=0)
tree.append_column(column)
一列显示多个数据
column = Gtk.TreeViewColumn("Title and Author")
title = Gtk.CellRendererText()
author = Gtk.CellRendererText()
column.pack_start(title, True)
column.pack_start(author, True)
column.add_attribute(title, "text", 0)
column.add_attribute(author, "text", 1)
tree.append_column(column)
选择
select = tree.get_selection()
select.connect("changed", on_tree_selection_changed)
def on_tree_selection_changed(selection):
model, treeiter = selection.get_selected()
if treeiter != None:
print("You selected", model[treeiter][0])
可以设置多行选择模式
Gtk.TreeSelection.set_mode(Gtk.SelectionMode.MULTIPLE)
多行选择模式下Gtk.TreeSelection.get_selected()不起作用,使用Gtk.TreeSelection.get_selected_rows()方法代替
点击列头排序
model = Gtk.ListStore(str)
model.append(["Benjamin"])
model.append(["Charles"])
model.append(["alfred"])
model.append(["Alfred"])
model.append(["David"])
model.append(["charles"])
model.append(["david"])
model.append(["benjamin"])
treeView = Gtk.TreeView(model)
cellRenderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Title", renderer, text=0)#text为model中的第1列数据
column.set_sort_column_id(0)
自定义排序方法
def compare(model, row1, row2, user_data):
sort_column, _ = model.get_sort_column_id()
value1 = model.get_value(row1, sort_column)
value2 = model.get_value(row2, sort_column)
if value1 < value2:
return -1
elif value1 == value2:
return 0
else:
return 1
设置排序方法。Gtk.TreeSortable.set_sort_func().
model.set_sort_func(0, compare, None)
过滤需要用到Gtk.TreeModelFilter类
先定义一个实例
filter = model.filter_new()
设置过滤方法
filter.set_visible_func(filter_func, data=None)
#!/usr/bin/env python3
# section 075
# -*- Mode: Python; py-indent-offset: 4 -*-
# vim: tabstop=4 shiftwidth=4 expandtab
#
# Copyright (C) 2010 Red Hat, Inc., John (J5) Palmieri
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
TITLE = "List Store"
DESCRIPTION = """
The GtkListStore is used to store data in list form, to be used later on by a
GtkTreeView to display it. This demo builds a simple GtkListStore and displays
it. See the Stock Browser demo for a more advanced example.
"""
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject, GLib
class Bug:
def __init__(self, is_fixed, number, severity, description):
self.is_fixed = is_fixed
self.number = number
self.severity = severity
self.description = description
# initial data we use to fill in the store
data = [Bug(False, 60482, "Normal", "scrollable notebooks and hidden tabs"),
Bug(False, 60620, "Critical", "gdk_window_clear_area (gdkwindow-win32.c) is not thread-safe"),
Bug(False, 50214, "Major", "Xft support does not clean up correctly"),
Bug(True, 52877, "Major", "GtkFileSelection needs a refresh method. "),
Bug(False, 56070, "Normal", "Can't click button after setting in sensitive"),
Bug(True, 56355, "Normal", "GtkLabel - Not all changes propagate correctly"),
Bug(False, 50055, "Normal", "Rework width/height computations for TreeView"),
Bug(False, 58278, "Normal", "gtk_dialog_set_response_sensitive () doesn't work"),
Bug(False, 55767, "Normal", "Getters for all setters"),
Bug(False, 56925, "Normal", "Gtkcalender size"),
Bug(False, 56221, "Normal", "Selectable label needs right-click copy menu"),
Bug(True, 50939, "Normal", "Add shift clicking to GtkTextView"),
Bug(False, 6112, "Enhancement", "netscape-like collapsable toolbars"),
Bug(False, 1, "Normal", "First bug :=)")]
class ListStoreApp:
(COLUMN_FIXED,
COLUMN_NUMBER,
COLUMN_SEVERITY,
COLUMN_DESCRIPTION,
COLUMN_PULSE,
COLUMN_ICON,
COLUMN_ACTIVE,
COLUMN_SENSITIVE,
NUM_COLUMNS) = range(9)
def __init__(self):
self.window = Gtk.Window()
self.window.set_title('Gtk.ListStore Demo')
self.window.connect('destroy', Gtk.main_quit)
vbox = Gtk.VBox(spacing=8)
self.window.add(vbox)
label = Gtk.Label(
label='This is the bug list (note: not based on real data, it would be nice to have a nice ODBC interface to bugzilla or so, though).')
vbox.pack_start(label, False, False, 0)
sw = Gtk.ScrolledWindow()
sw.set_shadow_type(Gtk.ShadowType.ETCHED_IN)
sw.set_policy(Gtk.PolicyType.NEVER,
Gtk.PolicyType.AUTOMATIC)
vbox.pack_start(sw, True, True, 0)
self.create_model()
treeview = Gtk.TreeView(model=self.model)
treeview.set_rules_hint(True)
treeview.set_search_column(self.COLUMN_DESCRIPTION)
sw.add(treeview)
self.add_columns(treeview)
self.window.set_default_size(280, 250)
self.window.show_all()
self.window.connect('delete-event', self.window_closed)
self.timeout = GLib.timeout_add(80, self.spinner_timeout)
def window_closed(self, window, event):
if self.timeout != 0:
GLib.source_remove(self.timeout)
def spinner_timeout(self):
if self.model is None:
return False
iter_ = self.model.get_iter_first()
pulse = self.model.get(iter_, self.COLUMN_PULSE)[0]
if pulse == 999999999:
pulse = 0
else:
pulse += 1
self.model.set_value(iter_, self.COLUMN_PULSE, pulse)
self.model.set_value(iter_, self.COLUMN_ACTIVE, True)
return True
def create_model(self):
self.model = Gtk.ListStore(bool,
GObject.TYPE_INT,
str,
str,
GObject.TYPE_INT,
str,
bool,
bool)
for row, bug in enumerate(data):
if row == 1 or row == 3:
icon_name = 'battery-caution-charging-symbolic'
else:
icon_name = ''
if row == 3:
is_sensitive = False
else:
is_sensitive = True
self.model.append([bug.is_fixed,
bug.number,
bug.severity,
bug.description,
0,
icon_name,
False,
is_sensitive])
def add_columns(self, treeview):
model = treeview.get_model()
# column for is_fixed toggle
renderer = Gtk.CellRendererToggle()
renderer.connect('toggled', self.is_fixed_toggled, model)
column = Gtk.TreeViewColumn("Fixed?", renderer,
active=self.COLUMN_FIXED)
column.set_fixed_width(50)
column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
treeview.append_column(column)
# column for severities
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Severity", renderer,
text=self.COLUMN_SEVERITY)
column.set_sort_column_id(self.COLUMN_SEVERITY)
treeview.append_column(column)
# column for description
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Description", renderer,
text=self.COLUMN_DESCRIPTION)
column.set_sort_column_id(self.COLUMN_DESCRIPTION)
treeview.append_column(column)
# column for spinner
renderer = Gtk.CellRendererSpinner()
column = Gtk.TreeViewColumn("Spinning", renderer,
pulse=self.COLUMN_PULSE,
active=self.COLUMN_ACTIVE)
column.set_sort_column_id(self.COLUMN_PULSE)
treeview.append_column(column)
# column for symbolic icon
renderer = Gtk.CellRendererPixbuf()
renderer.props.follow_state = True
column = Gtk.TreeViewColumn("Symbolic icon", renderer,
icon_name=self.COLUMN_ICON,
sensitive=self.COLUMN_SENSITIVE)
column.set_sort_column_id(self.COLUMN_ICON)
treeview.append_column(column)
def is_fixed_toggled(self, cell, path_str, model):
# get toggled iter
iter_ = model.get_iter(path_str)
is_fixed = model.get_value(iter_, self.COLUMN_FIXED)
# do something with value
is_fixed ^= 1
model.set_value(iter_, self.COLUMN_FIXED, is_fixed)
def main():
ListStoreApp()
Gtk.main()
if __name__ == '__main__':
main()
代码解析
代码
#!/usr/bin/env python3
# Created by xiaosanyu at 16/6/15
# section 076
TITLE = "Tree Store"
DESCRIPTION = """
The GtkTreeStore is used to store data in tree form, to be
used later on by a GtkTreeView to display it. This demo builds
a simple GtkTreeStore and displays it. If you're new to the
GtkTreeView widgets and associates, look into the GtkListStore
example first.
"""
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
(
HOLIDAY_NAME_COLUMN,
ALEX_COLUMN,
HAVOC_COLUMN,
TIM_COLUMN,
OWEN_COLUMN,
DAVE_COLUMN,
VISIBLE_COLUMN,
WORLD_COLUMN,
) = range(8)
# tree data
january = [
["New Years Day", True, True, True, True, False, True],
["Presidential Inauguration", False, True, False, True, False, False],
["Martin Luther King Jr. day", False, True, False, True, False, False],
]
february = [
["Presidents' Day", False, True, False, True, False, False],
["Groundhog Day", False, False, False, False, False, False],
["Valentine's Day", False, False, False, False, True, True],
]
march = [
["National Tree Planting Day", False, False, False, False, False, False],
["St Patrick's Day", False, False, False, False, False, True],
]
april = [
["April Fools' Day", False, False, False, False, False, True],
["Army Day", False, False, False, False, False, False],
["Earth Day", False, False, False, False, False, True],
["Administrative Professionals' Day", False, False, False, False, False, False],
]
may = [
["Nurses' Day", False, False, False, False, False, False],
["National Day of Prayer", False, False, False, False, False, False],
["Mothers' Day", False, False, False, False, False, True],
["Armed Forces Day", False, False, False, False, False, False],
["Memorial Day", True, True, True, True, False, True],
]
june = [
["June Fathers' Day", False, False, False, False, False, True],
["Juneteenth (Liberation of Slaves)", False, False, False, False, False, False],
["Flag Day", False, True, False, True, False, False],
]
july = [
["Parents' Day", False, False, False, False, False, True],
["Independence Day", False, True, False, True, False, False],
]
august = [
["Air Force Day", False, False, False, False, False, False],
["Coast Guard Day", False, False, False, False, False, False],
["Friendship Day", False, False, False, False, False, False],
]
september = [
["Grandparents' Day", False, False, False, False, False, True],
["Citizenship Day or Constitution Day", False, False, False, False, False, False],
["Labor Day", True, True, True, True, False, True],
]
october = [
["National Children's Day", False, False, False, False, False, False],
["Bosses' Day", False, False, False, False, False, False],
["Sweetest Day", False, False, False, False, False, False],
["Mother-in-Law's Day", False, False, False, False, False, False],
["Navy Day", False, False, False, False, False, False],
["Columbus Day", False, True, False, True, False, False],
["Halloween", False, False, False, False, False, True],
]
november = [
["Marine Corps Day", False, False, False, False, False, False],
["Veterans' Day", True, True, True, True, False, True],
["Thanksgiving", False, True, False, True, False, False],
]
december = [
["Pearl Harbor Remembrance Day", False, False, False, False, False, False],
["Christmas", True, True, True, True, False, True],
["Kwanzaa", False, False, False, False, False, False],
]
toplevel = [
["January", False, False, False, False, False, False, january],
["February", False, False, False, False, False, False, february],
["March", False, False, False, False, False, False, march],
["April", False, False, False, False, False, False, april],
["May", False, False, False, False, False, False, may],
["June", False, False, False, False, False, False, june],
["July", False, False, False, False, False, False, july],
["August", False, False, False, False, False, False, august],
["September", False, False, False, False, False, False, september],
["October", False, False, False, False, False, False, october],
["November", False, False, False, False, False, False, november],
["December", False, False, False, False, False, False, december],
]
class TreeViewFilterWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Tree Store")
self.set_default_size(650, 400)
vbox = Gtk.VBox(spacing=8)
vbox.set_border_width(8)
self.add(vbox)
vbox.pack_start(Gtk.Label("Jonathan's Holiday Card Planning Sheet"), False, False, 0)
sw = Gtk.ScrolledWindow()
sw.set_shadow_type(Gtk.ShadowType.ETCHED_IN)
sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
vbox.pack_start(sw, True, True, 0)
# create model
model = self.create_model()
# create tree view
treeview = Gtk.TreeView.new_with_model(model)
treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE)
self.add_columns(treeview)
sw.add(treeview)
# expand all rows after the treeview widget has been realized
treeview.connect("realize", Gtk.TreeView.expand_all)
@staticmethod
def create_model():
# create tree store
model = Gtk.TreeStore(str, bool, bool, bool, bool, bool, bool, bool)
# add data to the tree store
for month in toplevel:
holiday = month[-1]
iter = model.append(None)
model.set_row(iter, (month[0], False, False, False, False, False, False, False))
# add children
for child in holiday:
child_iter = model.append(iter)
model.set_row(child_iter, (child[0], child[1], child[2], child[3], child[4], child[5], True, child[6]))
return model
def add_columns(self, treeview):
model = treeview.get_model()
# column for holiday names
renderer = Gtk.CellRendererText()
renderer.xalign = 0
treeview.insert_column_with_attributes(
position=-1,
title="Holiday",
cell=renderer,
text=HOLIDAY_NAME_COLUMN)
column = treeview.get_column(HOLIDAY_NAME_COLUMN)
column.set_clickable(True)
# alex column
renderer = Gtk.CellRendererToggle()
renderer.xalign = 0
renderer.column = ALEX_COLUMN
renderer.connect("toggled", self.item_toggled, model)
treeview.insert_column_with_attributes(
position=-1,
title="Alex",
cell=renderer,
active=ALEX_COLUMN,
visible=VISIBLE_COLUMN,
activatable=WORLD_COLUMN)
column = treeview.get_column(ALEX_COLUMN)
column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
column.set_fixed_width(50)
column.set_clickable(True)
# havoc column
renderer = Gtk.CellRendererToggle()
renderer.xalign = 0
renderer.column = HAVOC_COLUMN
renderer.connect("toggled", self.item_toggled, model)
treeview.insert_column_with_attributes(
position=-1,
title="Havoc",
cell=renderer,
active=HAVOC_COLUMN,
visible=VISIBLE_COLUMN)
column = treeview.get_column(HAVOC_COLUMN)
column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
column.set_fixed_width(50)
column.set_clickable(True)
# tim column
renderer = Gtk.CellRendererToggle()
renderer.xalign = 0
renderer.column = TIM_COLUMN
renderer.connect("toggled", self.item_toggled, model)
treeview.insert_column_with_attributes(
position=-1,
title="Tim",
cell=renderer,
active=TIM_COLUMN,
visible=VISIBLE_COLUMN,
activatable=WORLD_COLUMN)
column = treeview.get_column(TIM_COLUMN)
column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
column.set_fixed_width(50)
column.set_clickable(True)
# owen column
renderer = Gtk.CellRendererToggle()
renderer.xalign = 0
renderer.column = OWEN_COLUMN
renderer.connect("toggled", self.item_toggled, model)
treeview.insert_column_with_attributes(
position=-1,
title="Owen",
cell=renderer,
active=OWEN_COLUMN,
visible=VISIBLE_COLUMN)
column = treeview.get_column(OWEN_COLUMN)
column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
column.set_fixed_width(50)
column.set_clickable(True)
# dave column
renderer = Gtk.CellRendererToggle()
renderer.xalign = 0
renderer.column = DAVE_COLUMN
renderer.connect("toggled", self.item_toggled, model)
treeview.insert_column_with_attributes(
position=-1,
title="Dave",
cell=renderer,
active=DAVE_COLUMN,
visible=VISIBLE_COLUMN)
column = treeview.get_column(DAVE_COLUMN)
column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
column.set_fixed_width(50)
column.set_clickable(True)
@staticmethod
def item_toggled(cell, path_str, model):
path = Gtk.TreePath.new_from_string(path_str)
column = cell.column
# get toggled iter
iter = model.get_iter(path)
toggle_item = model.get_value(iter, column)
# toggle the value
toggle_item = not toggle_item
# set new value
model.set_value(iter, column, toggle_item)
def main():
win = TreeViewFilterWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
if __name__ == "__main__":
main()
#!/usr/bin/env python3
# Created by xiaosanyu at 16/6/15
# section 077
TITLE = "Treeview Filter"
DESCRIPTION = ""
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
# list of tuples for each software, containing the software name, initial release, and main programming languages used
software_list = [("Firefox", 2002, "C++"),
("Eclipse", 2004, "Java"),
("Pitivi", 2004, "Python"),
("Netbeans", 1996, "Java"),
("Chrome", 2008, "C++"),
("Filezilla", 2001, "C++"),
("Bazaar", 2005, "Python"),
("Git", 2005, "C"),
("Linux Kernel", 1991, "C"),
("GCC", 1987, "C"),
("Frostwire", 2004, "Java")]
class TreeViewFilterWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Treeview Filter Demo")
self.set_border_width(10)
# Setting up the self.grid in which the elements are to be positionned
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.software_liststore = Gtk.ListStore(str, int, str)
for software_ref in software_list:
self.software_liststore.append(list(software_ref))
self.current_filter_language = None
# Creating the filter, feeding it with the liststore model
self.language_filter = self.software_liststore.filter_new()
# setting the filter function, note that we're not using the
self.language_filter.set_visible_func(self.language_filter_func)
# creating the treeview, making it use the filter as a model, and adding the columns
self.treeview = Gtk.TreeView.new_with_model(self.language_filter)
for i, column_title in enumerate(["Software", "Release Year", "Programming Language"]):
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn(column_title, renderer, text=i)
self.treeview.append_column(column)
# creating buttons to filter by programming language, and setting up their events
self.buttons = list()
for prog_language in ["Java", "C", "C++", "Python", "None"]:
button = Gtk.Button(prog_language)
self.buttons.append(button)
button.connect("clicked", self.on_selection_button_clicked)
# setting up the layout, putting the treeview in a scrollwindow, and the buttons in a row
self.scrollable_treelist = Gtk.ScrolledWindow()
self.scrollable_treelist.set_vexpand(True)
self.grid.attach(self.scrollable_treelist, 0, 0, 8, 10)
self.grid.attach_next_to(self.buttons[0], self.scrollable_treelist, Gtk.PositionType.BOTTOM, 1, 1)
for i, button in enumerate(self.buttons[1:]):
self.grid.attach_next_to(button, self.buttons[i], Gtk.PositionType.RIGHT, 1, 1)
self.scrollable_treelist.add(self.treeview)
def language_filter_func(self, model, iter, data):
"""Tests if the language in the row is the one in the filter"""
if self.current_filter_language is None or self.current_filter_language == "None":
return True
else:
return model[iter][2] == self.current_filter_language
def on_selection_button_clicked(self, widget):
"""Called on any of the button clicks"""
# we set the current language filter to the button's label
self.current_filter_language = widget.get_label()
print("%s language selected!" % self.current_filter_language)
# we update the filter, which updates in turn the view
self.language_filter.refilter()
def main():
win = TreeViewFilterWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
if __name__ == "__main__":
main()
代码:
#!/usr/bin/env python3
# section 078
TITLE = "File List (GenericTreeModel)"
DESCRIPTION = """
This is a file list demo which makes use of the GenericTreeModel python
implementation of the Gtk.TreeModel interface. This demo shows what methods
need to be overridden to provide a valid TreeModel to a TreeView.
"""
import os
import stat
import time
import pygtkcompat
pygtkcompat.enable()
pygtkcompat.enable_gtk('3.0')
import gtk
folderxpm = [
"17 16 7 1",
" c #000000",
". c #808000",
"X c yellow",
"o c #808080",
"O c #c0c0c0",
"+ c white",
"@ c None",
"@@@@@@@@@@@@@@@@@",
"@@@@@@@@@@@@@@@@@",
"@@+XXXX.@@@@@@@@@",
"@+OOOOOO.@@@@@@@@",
"@+OXOXOXOXOXOXO. ",
"@+XOXOXOXOXOXOX. ",
"@+OXOXOXOXOXOXO. ",
"@+XOXOXOXOXOXOX. ",
"@+OXOXOXOXOXOXO. ",
"@+XOXOXOXOXOXOX. ",
"@+OXOXOXOXOXOXO. ",
"@+XOXOXOXOXOXOX. ",
"@+OOOOOOOOOOOOO. ",
"@ ",
"@@@@@@@@@@@@@@@@@",
"@@@@@@@@@@@@@@@@@"
]
folderpb = gtk.gdk.pixbuf_new_from_xpm_data(folderxpm)
filexpm = [
"12 12 3 1",
" c #000000",
". c #ffff04",
"X c #b2c0dc",
"X XXX",
"X ...... XXX",
"X ...... X",
"X . ... X",
"X ........ X",
"X . .... X",
"X ........ X",
"X . .. X",
"X ........ X",
"X . .. X",
"X ........ X",
"X X"
]
filepb = gtk.gdk.pixbuf_new_from_xpm_data(filexpm)
class FileListModel(gtk.GenericTreeModel):
__gtype_name__ = 'DemoFileListModel'
column_types = (gtk.gdk.Pixbuf, str, int, str, str)
column_names = ['Name', 'Size', 'Mode', 'Last Changed']
def __init__(self, dname=None):
gtk.GenericTreeModel.__init__(self)
self._sort_column_id = 0
self._sort_order = gtk.SORT_ASCENDING
if not dname:
self.dirname = os.path.expanduser('~')
else:
self.dirname = os.path.abspath(dname)
self.files = ['..'] + [f for f in os.listdir(self.dirname)]
return
def get_pathname(self, path):
filename = self.files[path[0]]
return os.path.join(self.dirname, filename)
def is_folder(self, path):
filename = self.files[path[0]]
pathname = os.path.join(self.dirname, filename)
filestat = os.stat(pathname)
if stat.S_ISDIR(filestat.st_mode):
return True
return False
def get_column_names(self):
return self.column_names[:]
#
# GenericTreeModel Implementation
#
def on_get_flags(self):
return 0 # gtk.TREE_MODEL_ITERS_PERSIST
def on_get_n_columns(self):
return len(self.column_types)
def on_get_column_type(self, n):
return self.column_types[n]
def on_get_iter(self, path):
return self.files[path[0]]
def on_get_path(self, rowref):
return self.files.index(rowref)
def on_get_value(self, rowref, column):
fname = os.path.join(self.dirname, rowref)
try:
filestat = os.stat(fname)
except OSError:
return None
mode = filestat.st_mode
if column is 0:
if stat.S_ISDIR(mode):
return folderpb
else:
return filepb
elif column is 1:
return rowref
elif column is 2:
return filestat.st_size
elif column is 3:
return oct(stat.S_IMODE(mode))
return time.ctime(filestat.st_mtime)
def on_iter_next(self, rowref):
try:
i = self.files.index(rowref) + 1
return self.files[i]
except IndexError:
return None
def on_iter_children(self, rowref):
if rowref:
return None
return self.files[0]
def on_iter_has_child(self, rowref):
return False
def on_iter_n_children(self, rowref):
if rowref:
return 0
return len(self.files)
def on_iter_nth_child(self, rowref, n):
if rowref:
return None
try:
return self.files[n]
except IndexError:
return None
def on_iter_parent(child):
return None
class GenericTreeModelExample:
def delete_event(self, widget, event, data=None):
gtk.main_quit()
return False
def __init__(self):
# Create a new window
self.window = gtk.Window(type=gtk.WINDOW_TOPLEVEL)
self.window.set_size_request(300, 200)
self.window.connect("delete_event", self.delete_event)
self.listmodel = FileListModel()
# create the TreeView
self.treeview = gtk.TreeView()
self.tvcolumns = []
# create the TreeViewColumns to display the data
for n, name in enumerate(self.listmodel.get_column_names()):
if n == 0:
cellpb = gtk.CellRendererPixbuf()
col = gtk.TreeViewColumn(name, cellpb, pixbuf=0)
cell = gtk.CellRendererText()
col.pack_start(cell, False)
col.add_attribute(cell, 'text', 1)
else:
cell = gtk.CellRendererText()
col = gtk.TreeViewColumn(name, cell, text=n + 1)
if n == 1:
cell.set_property('xalign', 1.0)
self.treeview.append_column(col)
self.treeview.connect('row-activated', self.open_file)
self.scrolledwindow = gtk.ScrolledWindow()
self.scrolledwindow.add(self.treeview)
self.window.add(self.scrolledwindow)
self.treeview.set_model(self.listmodel)
self.window.set_title(self.listmodel.dirname)
self.window.show_all()
def open_file(self, treeview, path, column):
model = treeview.get_model()
if model.is_folder(path):
pathname = model.get_pathname(path)
new_model = FileListModel(pathname)
self.window.set_title(new_model.dirname)
treeview.set_model(new_model)
return
def main():
demo = GenericTreeModelExample()
gtk.main()
if __name__ == "__main__":
main()
#!/usr/bin/env python3
# section 079
TITLE = "File Tree (GenericTreeModel)"
DESCRIPTION = """
This is a file list demo which makes use of the GenericTreeModel python
implementation of the Gtk.TreeModel interface. This demo shows what methods
need to be overridden to provide a valid TreeModel to a TreeView.
"""
import os
import stat
import time
from collections import OrderedDict
import pygtkcompat
pygtkcompat.enable_gtk('3.0')
import gtk
folderxpm = [
"17 16 7 1",
" c #000000",
". c #808000",
"X c yellow",
"o c #808080",
"O c #c0c0c0",
"+ c white",
"@ c None",
"@@@@@@@@@@@@@@@@@",
"@@@@@@@@@@@@@@@@@",
"@@+XXXX.@@@@@@@@@",
"@+OOOOOO.@@@@@@@@",
"@+OXOXOXOXOXOXO. ",
"@+XOXOXOXOXOXOX. ",
"@+OXOXOXOXOXOXO. ",
"@+XOXOXOXOXOXOX. ",
"@+OXOXOXOXOXOXO. ",
"@+XOXOXOXOXOXOX. ",
"@+OXOXOXOXOXOXO. ",
"@+XOXOXOXOXOXOX. ",
"@+OOOOOOOOOOOOO. ",
"@ ",
"@@@@@@@@@@@@@@@@@",
"@@@@@@@@@@@@@@@@@"
]
folderpb = gtk.gdk.pixbuf_new_from_xpm_data(folderxpm)
filexpm = [
"12 12 3 1",
" c #000000",
". c #ffff04",
"X c #b2c0dc",
"X XXX",
"X ...... XXX",
"X ...... X",
"X . ... X",
"X ........ X",
"X . .... X",
"X ........ X",
"X . .. X",
"X ........ X",
"X . .. X",
"X ........ X",
"X X"
]
filepb = gtk.gdk.pixbuf_new_from_xpm_data(filexpm)
class FileTreeModel(gtk.GenericTreeModel):
__gtype_name__ = 'DemoFileTreeModel'
column_types = (gtk.gdk.Pixbuf, str, int, str, str)
column_names = ['Name', 'Size', 'Mode', 'Last Changed']
def __init__(self, dname=None):
gtk.GenericTreeModel.__init__(self)
if not dname:
self.dirname = os.path.expanduser('~')
else:
self.dirname = os.path.abspath(dname)
self.files = self.build_file_dict(self.dirname)
return
def build_file_dict(self, dirname):
"""
:Returns:
A dictionary containing the files in the given dirname keyed by filename.
If the child filename is a sub-directory, the dict value is a dict.
Otherwise it will be None.
"""
d = OrderedDict()
for fname in os.listdir(dirname):
try:
filestat = os.stat(os.path.join(dirname, fname))
except OSError:
d[fname] = None
else:
d[fname] = OrderedDict() if stat.S_ISDIR(filestat.st_mode) else None
return d
def get_node_from_treepath(self, path):
"""
:Returns:
The node stored at the given tree path in local storage.
"""
# TreePaths are a series of integer indices so just iterate through them
# and index values by each integer since we are using an OrderedDict
if path is None:
path = []
node = self.files
for index in path:
node = list(node.values())[index]
return node
def get_node_from_filepath(self, filepath):
"""
:Returns:
The node stored at the given file path in local storage.
"""
if not filepath:
return self.files
node = self.files
for key in filepath.split(os.path.sep):
node = node[key]
return node
def get_column_names(self):
return self.column_names[:]
#
# GenericTreeModel Implementation
#
def on_get_flags(self):
return 0
def on_get_n_columns(self):
return len(self.column_types)
def on_get_column_type(self, n):
return self.column_types[n]
def on_get_path(self, relpath):
path = []
node = self.files
for key in relpath.split(os.path.sep):
path.append(list(node.keys()).index(key))
node = node[key]
return path
def on_get_value(self, relpath, column):
fname = os.path.join(self.dirname, relpath)
try:
filestat = os.stat(fname)
except OSError:
return None
mode = filestat.st_mode
if column is 0:
if stat.S_ISDIR(mode):
return folderpb
else:
return filepb
elif column is 1:
return os.path.basename(relpath)
elif column is 2:
return filestat.st_size
elif column is 3:
return oct(stat.S_IMODE(mode))
return time.ctime(filestat.st_mtime)
def on_get_iter(self, path):
filepath = ''
value = self.files
for index in path:
filepath = os.path.join(filepath, list(value.keys())[index])
value = list(value.values())[index]
return filepath
def on_iter_next(self, filepath):
parent_path, child_path = os.path.split(filepath)
parent = self.get_node_from_filepath(parent_path)
# Index of filepath within its parents child list
sibling_names = list(parent.keys())
index = sibling_names.index(child_path)
try:
return os.path.join(parent_path, sibling_names[index + 1])
except IndexError:
return None
def on_iter_children(self, filepath):
if filepath:
children = list(self.get_node_from_filepath(filepath).keys())
if children:
return os.path.join(filepath, children[0])
elif self.files:
return list(self.files.keys())[0]
return None
def on_iter_has_child(self, filepath):
return bool(self.get_node_from_filepath(filepath))
def on_iter_n_children(self, filepath):
return len(self.get_node_from_filepath(filepath))
def on_iter_nth_child(self, filepath, n):
try:
child = list(self.get_node_from_filepath(filepath).keys())[n]
if filepath:
return os.path.join(filepath, child)
else:
return child
except IndexError:
return None
def on_iter_parent(self, filepath):
return os.path.dirname(filepath)
def on_ref_node(self, filepath):
value = self.get_node_from_filepath(filepath)
if value is not None:
value.update(self.build_file_dict(os.path.join(self.dirname, filepath)))
def on_unref_node(self, filepath):
pass
class GenericTreeModelExample:
def delete_event(self, widget, event, data=None):
gtk.main_quit()
return False
def __init__(self):
# Create a new window
self.window = gtk.Window(type=gtk.WINDOW_TOPLEVEL)
self.window.set_size_request(300, 200)
self.window.connect("delete_event", self.delete_event)
self.listmodel = FileTreeModel()
# create the TreeView
self.treeview = gtk.TreeView()
# create the TreeViewColumns to display the data
column_names = self.listmodel.get_column_names()
self.tvcolumn = [None] * len(column_names)
cellpb = gtk.CellRendererPixbuf()
self.tvcolumn[0] = gtk.TreeViewColumn(column_names[0],
cellpb, pixbuf=0)
cell = gtk.CellRendererText()
self.tvcolumn[0].pack_start(cell, False)
self.tvcolumn[0].add_attribute(cell, 'text', 1)
self.treeview.append_column(self.tvcolumn[0])
for n in range(1, len(column_names)):
cell = gtk.CellRendererText()
if n == 1:
cell.set_property('xalign', 1.0)
self.tvcolumn[n] = gtk.TreeViewColumn(column_names[n],
cell, text=n + 1)
self.treeview.append_column(self.tvcolumn[n])
self.scrolledwindow = gtk.ScrolledWindow()
self.scrolledwindow.add(self.treeview)
self.window.add(self.scrolledwindow)
self.treeview.set_model(self.listmodel)
self.window.set_title(self.listmodel.dirname)
self.window.show_all()
def main():
demo = GenericTreeModelExample()
gtk.main()
if __name__ == "__main__":
main()
#!/usr/bin/env python3
# section 080
# -*- Mode: Python; py-indent-offset: 4 -*-
# pygobject - Python bindings for the GObject library
# Copyright (C) 2014 Simon Feltman
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, see .
TITLE = "Tree Model with Large Data"
DESCRIPTION = """
Implementation of the Gtk.TreeModel interface to create a custom model.
The demo uses a fake data store (it is not backed by a Python list) and is for
the purpose of showing how to override the TreeModel interfaces virtual methods.
"""
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import GObject
from gi.repository import GLib
from gi.repository import Gtk
class Model(GObject.Object, Gtk.TreeModel):
columns_types = (str, str)
item_count = 100000
item_data = 'abcdefghijklmnopqrstuvwxyz'
def __init__(self):
super(Model, self).__init__()
def do_get_flags(self):
return Gtk.TreeModelFlags.LIST_ONLY
def do_get_n_columns(self):
return len(self.columns_types)
def do_get_column_type(self, n):
return self.columns_types[n]
def do_get_iter(self, path):
# Return False and an empty iter when out of range
index = path.get_indices()[0]
if index < 0 or index >= self.item_count:
return False, None
it = Gtk.TreeIter()
it.user_data = index
return True, it
def do_get_path(self, it):
return Gtk.TreePath([it.user_data])
def do_get_value(self, it, column):
if column == 0:
return str(it.user_data)
elif column == 1:
return self.item_data
def do_iter_next(self, it):
# Return False if there is not a next item
next = it.user_data + 1
if next >= self.item_count:
return False
# Set the iters data and return True
it.user_data = next
return True
def do_iter_previous(self, it):
prev = it.user_data - 1
if prev < 0:
return False
it.user_data = prev
return True
def do_iter_children(self, parent):
# If parent is None return the first item
if parent is None:
it = Gtk.TreeIter()
it.user_data = 0
return True, it
return False, None
def do_iter_has_child(self, it):
return it is None
def do_iter_n_children(self, it):
# If iter is None, return the number of top level nodes
if it is None:
return self.item_count
return 0
def do_iter_nth_child(self, parent, n):
if parent is not None or n >= self.item_count:
return False, None
elif parent is None:
# If parent is None, return the nth iter
it = Gtk.TreeIter()
it.user_data = n
return True, it
def do_iter_parent(self, child):
return False, None
def main():
model = Model()
# Use fixed-height-mode to get better model load and display performance.
view = Gtk.TreeView(fixed_height_mode=True, headers_visible=False)
column = Gtk.TreeViewColumn()
column.props.sizing = Gtk.TreeViewColumnSizing.FIXED
renderer1 = Gtk.CellRendererText()
renderer2 = Gtk.CellRendererText()
column.pack_start(renderer1, expand=True)
column.pack_start(renderer2, expand=True)
column.add_attribute(renderer1, 'text', 0)
column.add_attribute(renderer2, 'text', 1)
view.append_column(column)
scrolled = Gtk.ScrolledWindow()
scrolled.add(view)
window = Gtk.Window(title=TITLE)
window.set_size_request(480, 640)
window.add(scrolled)
window.show_all()
GLib.timeout_add(10, lambda *args: view.set_model(model))
return window
if __name__ == "__main__":
window = main()
window.connect('destroy', Gtk.main_quit)
Gtk.main()
代码下载地址:http://download.csdn.net/detail/a87b01c14/9594728