PyGobject(二十)布局容器之ComboBox

  • GtkComboBox
    • 继承关系
    • Methods
    • Virtual Methods
    • Properties
    • Signals
    • 例子
  • 附录
    • GtkSensitivityType

Gtk.ComboBox

继承关系

Gtk.ComboBox组合框,用多个待选择项来填充其内容。

Gtk.ComboBox是Gtk.Bin的直接子类
PyGobject(二十)布局容器之ComboBox_第1张图片
这里写图片描述

Methods

方法修饰词 方法名及参数
static new ()
static new_with_area (area)
static new_with_area_and_entry (area)
static new_with_entry ()
static new_with_model (model)
static new_with_model_and_entry (model)
get_active ()
get_active_id ()
get_active_iter ()
get_add_tearoffs ()
get_button_sensitivity ()
get_column_span_column ()
get_entry_text_column ()
get_focus_on_click ()
get_has_entry ()
get_id_column ()
get_model ()
get_popup_accessible ()
get_popup_fixed_width ()
get_row_span_column ()
get_title ()
get_wrap_width ()
popdown ()
popup ()
popup_for_device (device)
set_active (index_)
set_active_id (active_id)
set_active_iter (iter)
set_add_tearoffs (add_tearoffs)
set_button_sensitivity (sensitivity)
set_column_span_column (column_span)
set_entry_text_column (text_column)
set_focus_on_click (focus_on_click)
set_id_column (id_column)
set_model (model)
set_popup_fixed_width (fixed)
set_row_separator_func (func, *data)
set_row_span_column (row_span)
set_title (title)
set_wrap_width (width)

Virtual Methods

do_changed ()
do_format_entry_text (path)

Properties

Name Type Flags Short Description
active int r/w/en 当前选中项的索引
active-id str r/w/en 当前选中项的文本内容
add-tearoffs bool d/r/w/en Whether dropdowns should have a tearoff menu item deprecated
button-sensitivity Gtk.SensitivityType r/w/en 当model为空时,下拉菜单是否可点击。默认不可点击
cell-area Gtk.CellArea r/w/co The Gtk.CellArea used to layout cells
column-span-column int r/w/en TreeModel column containing the column span values
entry-text-column int r/w/en 如果Gtk.ComboBox创建的时候has-entry属性True,指定model中哪一列显示在entry的文本中
has-entry bool r/w/co ComboBox 是否带有Gtk.Entry
has-frame bool r/w/en 是否在孩子的外围显示一个Frame
id-column int r/w/en 指定显示model中的哪一列
model Gtk.TreeModel r/w/en ComboBox的数据源model
popup-fixed-width bool r/w/en Whether the popup’s width should be a fixed width matching the allocated width of the combo box
popup-shown bool r Whether the combo’s dropdown is shown
row-span-column int r/w/en TreeModel column containing the row span values
tearoff-title str d/r/w/en A title that may be displayed by the window manager when the popup is torn-off deprecated
wrap-width int r/w/en Wrap width for laying out the items in a grid

Signals

Name Short Description
changed 选中项改变时发送此信号.
format-entry-text For combo boxes that are created with an entry (See Gtk.ComboBox :has-entry).
move-active The ::move-active signal is a keybinding signal which gets emitted to move the active selection.
popdown The ::popdown signal is a keybinding signal which gets emitted to popdown the combo box list.
popup The ::popup signal is a keybinding signal which gets emitted to popup the combo box list.

例子

PyGobject(二十)布局容器之ComboBox_第2张图片
代码:

#!/usr/bin/env python3
# Created by xiaosanyu at 16/6/15
# section 021
TITLE = "ComboBox"
DESCRIPTION = """
A Gtk.ComboBox is a widget that allows the user to choose from a list of valid choices
"""
import gi

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


class ComboBoxWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title="ComboBox Example")

        self.set_border_width(10)

        name_store = Gtk.ListStore(int, str)
        name_store.append([1, "Billy Bob"])
        name_store.append([11, "Billy Bob Junior"])
        name_store.append([12, "Sue Bob"])
        name_store.append([2, "Joey Jojo"])
        name_store.append([3, "Rob McRoberts"])
        name_store.append([31, "Xavier McRoberts"])

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)

        name_combo = Gtk.ComboBox.new_with_model_and_entry(name_store)
        name_combo.connect("changed", self.on_name_combo_changed)
        name_combo.set_entry_text_column(1)
        vbox.pack_start(name_combo, False, False, 0)

        country_store = Gtk.ListStore(str)
        countries = ["Austria", "Brazil", "Belgium", "France", "Germany",
                     "Switzerland", "United Kingdom", "United States of America",
                     "Uruguay"]
        for country in countries:
            country_store.append([country])

        country_combo = Gtk.ComboBox.new_with_model(country_store)
        country_combo.connect("changed", self.on_country_combo_changed)
        renderer_text = Gtk.CellRendererText()
        country_combo.pack_start(renderer_text, True)
        country_combo.add_attribute(renderer_text, "text", 0)
        vbox.pack_start(country_combo, False, False, True)

        currencies = ["Euro", "US Dollars", "British Pound", "Japanese Yen",
                      "Russian Ruble", "Mexican peso", "Swiss franc"]
        currency_combo = Gtk.ComboBoxText()
        currency_combo.set_entry_text_column(0)
        currency_combo.connect("changed", self.on_currency_combo_changed)
        for currency in currencies:
            currency_combo.append_text(currency)

        vbox.pack_start(currency_combo, False, False, 0)

        self.add(vbox)

    @staticmethod
    def on_name_combo_changed(combo):
        tree_iter = combo.get_active_iter()
        if tree_iter is not None:
            model = combo.get_model()
            row_id, name = model[tree_iter][:2]
            print("Selected: ID=%d, name=%s" % (row_id, name))
        else:
            entry = combo.get_child()
            print("Entered: %s" % entry.get_text())

    @staticmethod
    def on_country_combo_changed(combo):
        tree_iter = combo.get_active_iter()
        if tree_iter is not None:
            model = combo.get_model()
            country = model[tree_iter][0]
            print("Selected: country=%s" % country)

    @staticmethod
    def on_currency_combo_changed(combo):
        text = combo.get_active_text()
        if text is not None:
            print("Selected: currency=%s" % text)


def main():
    win = ComboBoxWindow()
    win.connect("delete-event", Gtk.main_quit)
    win.show_all()
    Gtk.main()


if __name__ == "__main__":
    main()

代码解析:

name_store = Gtk.ListStore(int, str)
name_store.append([1, "Billy Bob"])
name_store.append([11, "Billy Bob Junior"])
name_store.append([12, "Sue Bob"])
name_store.append([2, "Joey Jojo"])
name_store.append([3, "Rob McRoberts"])
name_store.append([31, "Xavier McRoberts"])

创建第一个Gtk.ListStore,第一列为int类型,第二列为str类型
然后插入6行数据

name_combo = Gtk.ComboBox.new_with_model_and_entry(name_store)

使用前面创建的Gtk.ListStore作为数据源(model)来创建一个Gtk.ComboBox,并且它带有一个可供输入内容的Gtk.Entry

name_combo.connect("changed",self.on_name_combo_changed)

绑定”changed”信号到on_name_combo_changed()方法

@staticmethod
def on_name_combo_changed(combo):
    tree_iter = combo.get_active_iter()
    if tree_iter is not None:
        model = combo.get_model()
        row_id, name = model[tree_iter][:2]
        print("Selected: ID=%d, name=%s" % (row_id, name))
    else:
        entry = combo.get_child()
        print("Entered: %s" % entry.get_text())

当entry中的内容有改变时,执行此方法,如果是选择ComboBox中的内容则combo.get_active_iter()不为None,如果是手动输入内容则为None。

name_combo.set_entry_text_column(1)

设置Entry里面内容来自model中的第2列


country_store = Gtk.ListStore(str)
countries = ["Austria", "Brazil", "Belgium", "France", "Germany","Switzerland", "United Kingdom", "United States of America","Uruguay"]
for country in countries:
    country_store.append([country])

创建第二个Gtk.ListStore,只有一列,为str类型
填充数据

country_combo = Gtk.ComboBox.new_with_model(country_store)

使用前面的ListStore作为model来创建第二个Gtk.ComboBox

country_combo.connect("changed",self.on_country_combo_changed)

绑定”changed”信号到self.on_country_combo_changed()方法

创建一个CellRendererText用来显示文本信息,将CellRendererText添加到ComboBox容器中,设置CellRendererText,其中的text使用model中的第1列来填充

renderer_text = Gtk.CellRendererText()
country_combo.pack_start(renderer_text, True)
country_combo.add_attribute(renderer_text, "text", 0)



如果ComboBox只有一个str列,则可以使用它的子类ComboBoxText来简化创建过程

currencies = ["Euro", "US Dollars", "British Pound", "Japanese Yen","Russian Ruble", "Mexican peso", "Swiss franc"]
currency_combo = Gtk.ComboBoxText()
currency_combo.set_entry_text_column(0)
currency_combo.connect("changed", self.on_currency_combo_changed)
for currency in currencies:
    currency_combo.append_text(currency)

PyGobject(二十)布局容器之ComboBox_第3张图片
代码:

#!/usr/bin/env python3
# section 022
TITLE = "Combo boxes"
DESCRIPTION = """
The ComboBox widget allows to select one option out of a list.
The ComboBoxEntry additionally allows the user to enter a value
that is not in the list of options.

How the options are displayed is controlled by cell renderers.
 """

import gi

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

(PIXBUF_COL, TEXT_COL) = range(2)


class MaskEntry(Gtk.Entry):
    __gtype_name__ = 'MaskEntry'

    def __init__(self, mask=None):
        self.mask = mask
        super(MaskEntry, self).__init__()

        self.connect('changed', self.changed_cb)

        self.error_color = Gdk.RGBA()
        self.error_color.red = 1.0
        self.error_color.green = 0.9
        self.error_color_blue = 0.9
        self.error_color.alpha = 1.0

        # workaround since override_color doesn't accept None yet
        style_ctx = self.get_style_context()
        self.normal_color = style_ctx.get_color(0)

    def set_background(self):
        if self.mask:
            if not GLib.regex_match_simple(self.mask,
                                           self.get_text(), 0, 0):
                self.override_color(0, self.error_color)
                return

        self.override_color(0, self.normal_color)

    def changed_cb(self, entry):
        self.set_background()


class ComboboxApp:
    def __init__(self, demoapp):
        self.demoapp = demoapp

        self.window = Gtk.Window()
        self.window.set_title('Combo boxes')
        self.window.set_border_width(10)
        self.window.connect('destroy', lambda w: Gtk.main_quit())

        vbox = Gtk.VBox(homogeneous=False, spacing=2)
        self.window.add(vbox)

        frame = Gtk.Frame(label='Some stock icons')
        vbox.pack_start(frame, False, False, 0)

        box = Gtk.VBox(homogeneous=False, spacing=0)
        box.set_border_width(5)
        frame.add(box)

        model = self.create_stock_icon_store()
        combo = Gtk.ComboBox(model=model)
        box.add(combo)

        renderer = Gtk.CellRendererPixbuf()
        combo.pack_start(renderer, False)

        # FIXME: override set_attributes
        combo.add_attribute(renderer, 'pixbuf', PIXBUF_COL)
        combo.set_cell_data_func(renderer, self.set_sensitive, None)

        renderer = Gtk.CellRendererText()
        combo.pack_start(renderer, True)
        combo.add_attribute(renderer, 'text', TEXT_COL)
        combo.set_cell_data_func(renderer, self.set_sensitive, None)

        combo.set_row_separator_func(self.is_separator, None)
        combo.set_active(0)

        # a combobox demonstrating trees
        frame = Gtk.Frame(label='Where are we ?')
        vbox.pack_start(frame, False, False, 0)

        box = Gtk.VBox(homogeneous=False, spacing=0)
        box.set_border_width(5)
        frame.add(box)

        model = self.create_capital_store()
        combo = Gtk.ComboBox(model=model)
        box.add(combo)

        renderer = Gtk.CellRendererText()
        combo.pack_start(renderer, True)
        combo.add_attribute(renderer, 'text', 0)
        combo.set_cell_data_func(renderer, self.is_capital_sensistive, None)

        # FIXME: make new_from_indices work
        #        make constructor take list or string of indices
        path = Gtk.TreePath.new_from_string('0:8')
        treeiter = model.get_iter(path)
        combo.set_active_iter(treeiter)

        # A GtkComboBoxEntry with validation.

        frame = Gtk.Frame(label='Editable')
        vbox.pack_start(frame, False, False, 0)

        box = Gtk.VBox(homogeneous=False, spacing=0)
        box.set_border_width(5)
        frame.add(box)

        combo = Gtk.ComboBoxText.new_with_entry()
        self.fill_combo_entry(combo)
        box.add(combo)

        entry = MaskEntry(mask='^([0-9]*|One|Two|2\302\275|Three)$')

        combo.get_child().destroy() 
        combo.add(entry)

        # A combobox with string IDs

        frame = Gtk.Frame(label='String IDs')
        vbox.pack_start(frame, False, False, 0)

        box = Gtk.VBox(homogeneous=False, spacing=0)
        box.set_border_width(5)
        frame.add(box)

        # FIXME: model is not setup when constructing Gtk.ComboBoxText()
        #        so we call new() - Gtk should fix this to setup the model
        #        in __init__, not in the constructor
        combo = Gtk.ComboBoxText.new()
        combo.append('never', 'Not visible')
        combo.append('when-active', 'Visible when active')
        combo.append('always', 'Always visible')
        box.add(combo)

        entry = Gtk.Entry()

        combo.bind_property('active-id',
                            entry, 'text',
                            GObject.BindingFlags.BIDIRECTIONAL)

        box.add(entry)
        self.window.show_all()

    def strip_underscore(self, s):
        return s.replace('_', '')

    def create_stock_icon_store(self):
        stock_id = (Gtk.STOCK_DIALOG_WARNING,
                    Gtk.STOCK_STOP,
                    Gtk.STOCK_NEW,
                    Gtk.STOCK_CLEAR,
                    None,
                    Gtk.STOCK_OPEN)

        cellview = Gtk.CellView()
        store = Gtk.ListStore(GdkPixbuf.Pixbuf, str)

        for id in stock_id:
            if id is not None:
                pixbuf = cellview.render_icon(id, Gtk.IconSize.BUTTON, None)
                item = Gtk.stock_lookup(id)
                label = self.strip_underscore(item.label)
                store.append((pixbuf, label))
            else:
                store.append((None, 'separator'))

        return store

    def set_sensitive(self, cell_layout, cell, tree_model, treeiter, data):
        """
        A GtkCellLayoutDataFunc that demonstrates how one can control
        sensitivity of rows. This particular function does nothing
        useful and just makes the second row insensitive.
        """

        path = tree_model.get_path(treeiter)
        indices = path.get_indices()

        sensitive = not (indices[0] == 1)

        cell.set_property('sensitive', sensitive)

    def is_separator(self, model, treeiter, data):
        """
        A GtkTreeViewRowSeparatorFunc that demonstrates how rows can be
        rendered as separators. This particular function does nothing
        useful and just turns the fourth row into a separator.
        """

        path = model.get_path(treeiter)

        indices = path.get_indices()
        result = (indices[0] == 4)

        return result

    def create_capital_store(self):
        capitals = (
            {'group': 'A - B', 'capital': None},
            {'group': None, 'capital': 'Albany'},
            {'group': None, 'capital': 'Annapolis'},
            {'group': None, 'capital': 'Atlanta'},
            {'group': None, 'capital': 'Augusta'},
            {'group': None, 'capital': 'Austin'},
            {'group': None, 'capital': 'Baton Rouge'},
            {'group': None, 'capital': 'Bismarck'},
            {'group': None, 'capital': 'Boise'},
            {'group': None, 'capital': 'Boston'},
            {'group': 'C - D', 'capital': None},
            {'group': None, 'capital': 'Carson City'},
            {'group': None, 'capital': 'Charleston'},
            {'group': None, 'capital': 'Cheyeene'},
            {'group': None, 'capital': 'Columbia'},
            {'group': None, 'capital': 'Columbus'},
            {'group': None, 'capital': 'Concord'},
            {'group': None, 'capital': 'Denver'},
            {'group': None, 'capital': 'Des Moines'},
            {'group': None, 'capital': 'Dover'},
            {'group': 'E - J', 'capital': None},
            {'group': None, 'capital': 'Frankfort'},
            {'group': None, 'capital': 'Harrisburg'},
            {'group': None, 'capital': 'Hartford'},
            {'group': None, 'capital': 'Helena'},
            {'group': None, 'capital': 'Honolulu'},
            {'group': None, 'capital': 'Indianapolis'},
            {'group': None, 'capital': 'Jackson'},
            {'group': None, 'capital': 'Jefferson City'},
            {'group': None, 'capital': 'Juneau'},
            {'group': 'K - O', 'capital': None},
            {'group': None, 'capital': 'Lansing'},
            {'group': None, 'capital': 'Lincon'},
            {'group': None, 'capital': 'Little Rock'},
            {'group': None, 'capital': 'Madison'},
            {'group': None, 'capital': 'Montgomery'},
            {'group': None, 'capital': 'Montpelier'},
            {'group': None, 'capital': 'Nashville'},
            {'group': None, 'capital': 'Oklahoma City'},
            {'group': None, 'capital': 'Olympia'},
            {'group': 'P - S', 'capital': None},
            {'group': None, 'capital': 'Phoenix'},
            {'group': None, 'capital': 'Pierre'},
            {'group': None, 'capital': 'Providence'},
            {'group': None, 'capital': 'Raleigh'},
            {'group': None, 'capital': 'Richmond'},
            {'group': None, 'capital': 'Sacramento'},
            {'group': None, 'capital': 'Salem'},
            {'group': None, 'capital': 'Salt Lake City'},
            {'group': None, 'capital': 'Santa Fe'},
            {'group': None, 'capital': 'Springfield'},
            {'group': None, 'capital': 'St. Paul'},
            {'group': 'T - Z', 'capital': None},
            {'group': None, 'capital': 'Tallahassee'},
            {'group': None, 'capital': 'Topeka'},
            {'group': None, 'capital': 'Trenton'}
        )

        parent = None

        store = Gtk.TreeStore(str)

        for item in capitals:
            if item['group']:
                parent = store.append(None, (item['group'],))
            elif item['capital']:
                store.append(parent, (item['capital'],))

        return store

    def is_capital_sensistive(self, cell_layout, cell, tree_model, treeiter, data):
        sensitive = not tree_model.iter_has_child(treeiter)
        cell.set_property('sensitive', sensitive)

    def fill_combo_entry(self, entry):
        entry.append_text('One')
        entry.append_text('Two')
        entry.append_text('2\302\275')
        entry.append_text('Three')


def main(demoapp=None):
    ComboboxApp(demoapp)
    Gtk.main()


if __name__ == '__main__':
    main()

代码解析:
创建第一个ListStore,第一列为图片,第二列为文本

model = self.create_stock_icon_store()

def create_stock_icon_store(self):
    stock_id = (Gtk.STOCK_DIALOG_WARNING,
                    Gtk.STOCK_STOP,
                    Gtk.STOCK_NEW,
                    Gtk.STOCK_CLEAR,
                    None,
                    Gtk.STOCK_OPEN)

    cellview = Gtk.CellView()
    store = Gtk.ListStore(GdkPixbuf.Pixbuf, str)

    for id in stock_id:
        if id is not None:
            pixbuf = cellview.render_icon(id, Gtk.IconSize.BUTTON, None)
            item = Gtk.stock_lookup(id)
            label = self.strip_underscore(item.label)
            store.append((pixbuf, label))
        else:
            store.append((None, 'separator'))
    return store

使用这个model创建第一个ComboBox

combo = Gtk.ComboBox(model=model)

创建CellRendererPixbuf,作为ComboBox的第一列

renderer = Gtk.CellRendererPixbuf()
combo.pack_start(renderer, False)
combo.add_attribute(renderer, 'pixbuf', PIXBUF_COL)

创建CellRendererText,作为ComboBox的第二列

renderer = Gtk.CellRendererText()
combo.pack_start(renderer, True)
combo.add_attribute(renderer, 'text', TEXT_COL)

给每个单元格添加一个方法。如果是第二行(索引号为1)的单元格,则这个单元格不激活,不可点击

combo.set_cell_data_func(renderer, self.set_sensitive, None)

 def set_sensitive(self, cell_layout, cell, tree_model, treeiter, data):
    path = tree_model.get_path(treeiter)
    indices = path.get_indices()

    sensitive = not (indices[0] == 1)

    cell.set_property('sensitive', sensitive)

设置行分割函数。如果是第五行(索引号为4),则添加分隔线

combo.set_row_separator_func(self.is_separator, None)
def is_separator(self, model, treeiter, data):
    path = model.get_path(treeiter)
    indices = path.get_indices()
    result = (indices[0] == 4)

    return result

选中第1行

combo.set_active(0)



用所给列表,创建第二个ListStore,只有一个str列,但是分层次

model = self.create_capital_store()

parent = None
store = Gtk.TreeStore(str)
for item in capitals:
    if item['group']:
        parent = store.append(None, (item['group'],))
    elif item['capital']:
        store.append(parent, (item['capital'],))
return store

以所给model创建第二个ComboBox

combo = Gtk.ComboBox(model=model)
renderer = Gtk.CellRendererText()
combo.pack_start(renderer, True)
combo.add_attribute(renderer, 'text', 0)

给每列数据添加方法,如果该列没有子项,则不可点击

combo.set_cell_data_func(renderer,self.is_capital_sensistive, None)

def is_capital_sensistive(self, cell_layout, cell, tree_model, treeiter, data):
    sensitive = not tree_model.iter_has_child(treeiter)
    cell.set_property('sensitive', sensitive)

选中第1到9行

path = Gtk.TreePath.new_from_string('0:8')
treeiter = model.get_iter(path)
combo.set_active_iter(treeiter)



创建第三个ComboBox,带有一个输入框

combo = Gtk.ComboBoxText.new_with_entry()

填充数据

self.fill_combo_entry(combo)
def fill_combo_entry(self, entry):
    entry.append_text('One')
    entry.append_text('Two')
    entry.append_text('2\302\275')
    entry.append_text('Three')

移除ComboBoxText自带的entry,使用自定义的entry代替.自定义entry功能就是检测输入内容,如果不是给定的几个值文字显示为红色,如果是,显示为正常黑色。

entry = MaskEntry(mask='^([0-9]*|One|Two|2\302\275|Three)$')
Gtk.Container.remove(combo, combo.get_child())
combo.add(entry)



创建第四个ComboBox

combo = Gtk.ComboBoxText.new()
combo.append('never', 'Not visible')
combo.append('when-active', 'Visible when active')
combo.append('always', 'Always visible')

创建一个entry

entry = Gtk.Entry()

将ComboBox的’active-id’属性和entry的’text’绑定起来。
‘active-id’属性就是ComboBox当前选中行的内容,
这句话的意思就是将ComboBox当前选中行的内容填充到entry中

combo.bind_property('active-id',
                            entry, 'text',
                            GObject.BindingFlags.BIDIRECTIONAL)

附录

Gtk.SensitivityType

class Gtk.SensitivityType
Bases: GObject.GEnum
当model为空时,下拉框是否可点击

AUTO = 0

自动,有数据可点击,没数据不可点击

ON = 1

可点击

OFF = 2

不可点击




代码下载地址:http://download.csdn.net/detail/a87b01c14/9594728

你可能感兴趣的:(PyGObject,PyGobject详解)