8

gtk.Entryウィジェットをgtk.TreeViewColumnヘッダー/タイトル内でフォーカス可能または編集可能にするにはどうすればよいですか?私はこれを試しました:

# Create tree-view.
treeview = gtk.TreeView()

#...

# Create column.
renderer = gtk.CellRendererText()
column = gtk.TreeViewColumn(None, renderer, text=0)

# Set column header.
header = gtk.VBox()

title = gtk.Label("Column")
header.pack_start(title)

filter = gtk.Entry()
#...
header.pack_start(filter)

header.show_all()
column.set_widget(header)

# Add column
treeview.append_column(column)

ただし、列ヘッダーのエントリウィジェットは編集できず、フォーカスされません。'clickable'をとの両方に設定してみましTrueFalse。Ubuntu10.04でpygtk2.21.0-0ubuntu1とlibgtk2.22.0-0ubuntu1を使用しています。どんな助けでも大歓迎です。

編集:

GtkTreeViewColumnこの問題は、ヘッダーの表示方法に起因します。ヘッダーウィジェットは、GtkAlignmentその親がaであり、GtkHBoxその親がであり、GtkButtonその親が最終的にである内部に配置されGtkTreeViewます。これは、私が焦点を合わせてマウス入力を受け取るのGtkButtonを妨害して妨げています。GtkEntry

4

3 に答える 3

12

ヘッダーGtkEntry内でフォーカス可能にするために、私は次のことをしなければなりませんでした:GtkTreeView

1)ヘッダーを見つけますGtkButton

def find_closest_ancestor(widget, ancestor_class):
    if not isinstance(widget, gtk.Widget):
        raise TypeError("%r is not a gtk.Widget" % widget)
    ancestor = widget.get_parent()
    while ancestor is not None:
        if isinstance(ancestor, ancestor_class):
            break;
        ancestor = ancestor.get_parent() if hasattr(ancestor, 'get_parent') and callable(ancestor.get_parent) else None
    return ancestor

button-press-event2)信号をヘッダーからにGtkButton伝播しますGtkEntry

def propagate_button_press_event(parent, event, *data):
    parent_alloc = parent.get_allocation()
    x = parent_alloc.x + int(event.x)
    y = parent_alloc.y + int(event.y)
    children = parent.get_children()
    print "Propagating event:%r" % event
    print "- from parent:%r" % parent
    while children:
        for child in children:
            child_alloc = child.get_allocation()
            if child_alloc.x <= x <= child_alloc.x + child_alloc.width and child_alloc.y <= y <= child_alloc.y + child_alloc.height:
                print "- to child:%r" % child
                if child.get_property('can-focus'):
                    event.send_event = True
                    child.grab_focus()
                    child.emit('button-press-event', event, *data)
                    return True
                else:
                    children = child.get_children() if hasattr(child, 'get_children') and callable(child.get_children) else None
                    break;
        else:
            children = None
    return False

3)フォーカス(つまりfocus-in-event信号)をヘッダーからGtkButtonに伝達しGtkEntryます。

def propagate_focus_in_event(parent, event, *data):
    print 'focus-in', parent, event
    child = parent.get_child()
    if child.get_property('can-focus'):
        child.grab_focus()
    else:
        if not child.child_focus(gtk.DIR_TAB_FORWARD):
            parent.get_toplevel().child_focus(gtk.DIR_TAB_FORWARD)
    return True

例:

# Fix style glitches
_gtk_styles = """
    # Use the default GtkEntry style for GtkEntry widgets in treeview headers.
    widget "*.treeview-header-entry" style "entry" 
"""
gtk.rc_parse_string(_gtk_styles)

# Columns
_columns = [
    (0, "Title"),
    (1, "Description")
    # etc.
]

# Create tree-view.
items_view = gtk.TreeView(self.items_store)
items_view.show()

# Setup treeview columns.
renderer = gtk.CellRendererText()
for column in _columns:
    column_index, column_title, column_filter = column
    column_view = gtk.TreeViewColumn(None, renderer, text=column_index)
    column_view.set_clickable(True)

    column_widget = gtk.VBox()
    column_widget.show()

    column_align = gtk.Alignment(0, 0, 0, 0)
    column_align.show()
    column_widget.pack_start(column_align)
    column_label = gtk.Label(column_title)
    column_label.show()
    column_align.add(column_label)

    column_entry = gtk.Entry()
    column_entry.set_name('treeview-header-entry')
    column_entry.show()
    column_widget.pack_start(column_entry)

    column_view.set_widget(column_widget)
    items_view.append_column(column_view)

# Setup column headers.
columns = items_view.get_columns()
for column in columns:
    column_widget = column.get_widget()
    column_header = find_closest_ancestor(column_widget, gtk.Button)
    if column_header:
        column_header.connect('focus-in-event', propagate_focus_in_event)
        column_header.connect('button-press-event', propagate_button_press_event)
        column_header.set_focus_on_click(False)
于 2011-03-09T18:16:59.943 に答える
4

この質問が出されてからAPIが進化したので、更新された回答を投稿しようと思いました。(私は同様の問題に対処しているときにこれに遭遇しましたが、私の場合、エントリではなく列ヘッダーに2つのボタンを配置しようとしていました。)

まず、いくつかの背景。質問の編集で述べたように、この問題はTreeViewColumnの構造に起因します。列のヘッダーはボタンであり、あなたがそうするとset_widget、そのウィジェットはボタンの子孫になります。(列をクリック可能に設定しない限り、ヘッダーがボタンのように応答しないため、これは簡単に見落とされる可能性があります。また、誰もがすでにこれを知っていると思われるため、ドキュメントは役に立ちません。)この問題のさらなる原因は次のとおりです。 Buttonsがイベントを収集する方法。イベントに応答するほとんどのウィジェットとは異なり、ボタンにはGdk.Window階層内に独自のスポットがありません。代わりに、実現時に特別なイベントウィンドウを作成します。このウィンドウにアクセスする方法はボタン固有です:(get_event_windowより一般的なget_windowおよびget_parent_window)。このイベントウィンドウは、ボタンの上に見えないように配置され、ボタンの子孫にトリクルダウンする前にイベントを収集します。したがって、列ヘッダーに配置するウィジェットは、対話性に必要なイベントを受け取りません。

受け入れられた解決策は、この障害を回避する1つの方法であり、当時は価値のある答えでした。ただし、今ではもっと簡単な方法があります。(これは、使用されている言語バインディングとは関係なく、GTK +の問題であることに注意してください。個人的には、C ++バインディングを使用していました。また、これがコアGTK +の動作であり、そうではないことを確認するために、CでGTK+ソースファイルを調べました。バインディングのアーティファクト。)

1)ヘッダーボタンを見つけます。

問題のTreeViewColumnの場合column、ボタンを取得するためのAPIは次のようになります。

header_button = column.get_button()

このget_buttonメソッドはバージョン3.0で追加され、この質問が行われてから約6か月後にタグが付けられました。とても近い。

2)ボタンからエントリにイベントを伝播します。

このステップを単純化するには、さらに4年(バージョン3.18)かかりました。重要な開発はset_pass_through、イベントを通過させるようにイベントウィンドウに指示できることでした。ドキュメントに記載されているように、「Webの用語では、これは「ポインタイベント:なし」と呼ばれます。」

def pass_through_event_window(button, event):
    if not isinstance(button, gtk.Button):
        raise TypeError("%r is not a gtk.Button" % button)
    event_window = button.get_event_window()
    event_window.set_pass_through(True)

残りのトリックはタイミングの1つです。ボタンが実現されるまでイベントウィンドウは作成されないため、ボタンのrealize信号への接続は正常です。

header_button.connect('realize', pass_through_event_window)

そしてそれだけです(ステップ3はありません)。これで、イベントはエントリまたは列ヘッダーに配置したウィジェットに伝播されます。

構文を台無しにした場合はお詫びします。私はC++バインディングから翻訳しています。エラーが発生した場合は、Pythonの第一人者に修正を依頼します。

于 2019-04-09T04:01:57.980 に答える
0

これがあなたの答えでない限り、私はあなたが標準的で一般的な方法を使用することをお勧めします:を使用するtreeview.set_search_column(COLUMN_INDEX)と、デフォルトではエントリは表示されません(そしてUIをよりきれいにします)が、ユーザーが入力を開始すると(そのツリービューに焦点を合わせて)ポップアップ入力エントリが表示され、検索とフィルタリングはGTK自体によって自動的に行われます。

検索エントリが常に表示されるようにする場合は、を使用してツリービューヘッダーを削除し、ツリービューtreeview.set_headers_visible(False)の上にカスタムHBox(ラベルとエントリを含む)を追加します。

于 2011-03-09T07:01:12.003 に答える