2011-03-07 15 views
6

¿Cómo puedo hacer que un widget gtk.Entry sea enfocable o editable dentro de un encabezado/título gtk.TreeViewColumn? He intentado esto:Widget de entrada PyGTK en el encabezado 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) 

Pero el widget de entrada en el encabezado de la columna no se puede editar ni enfocar. He intentado configurar "cliqueable" en True y False. Estoy usando pygtk 2.21.0-0ubuntu1 y libgtk 2.22.0-0ubuntu1 en Ubuntu 10.04. Cualquier ayuda sería muy apreciada.

EDIT:

El problema radica en cómo se muestra una cabecera GtkTreeViewColumn. El widget de encabezado se ubica dentro de un GtkAlignment cuyo padre es un GtkHBox cuyo padre es un GtkButton cuyo padre es finalmente el GtkTreeView. El GtkButton está interceptando y evitando que mi GtkEntry se enfoque y reciba la entrada del mouse.

Respuesta

11

Con el fin de hacer una enfocable GtkEntry dentro de un encabezado GtkTreeView tuviera que:

1) Encontrar la cabecera 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 

2) propagar la señal button-press-event de la cabecera GtkButton a la 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) propagar la (es decir, focus-in-event señal) de enfoque de la cabecera GtkButton a la 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 

Ejemplo:

# 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) 
0

A menos que esta no sea su respuesta, pero le sugiero que use el método estándar y común: usando treeview.set_search_column(COLUMN_INDEX), no se mostrará ninguna entrada por defecto (y limpiará la interfaz de usuario) pero cuando el usuario empiece a escribir (con treeview) se mostrará una entrada de entrada emergente, y la búsqueda y el filtrado serán realizados por GTK automáticamente.

Si persiste que la entrada de búsqueda debe estar siempre visible, elimine el encabezado treeview usando treeview.set_headers_visible(False), y agregue un HBox personalizado (que contenga la etiqueta y la entrada) encima de la vista de árbol.

+0

tengo que ser capaz de buscar en varias columnas. Además, no puedo usar la búsqueda/filtrado estándar de GTK porque los datos son un subconjunto recuperado de una base de datos, por lo que cuando se establece un filtro, vuelvo a consultar un subconjunto de los datos con el filtro. – cpburnz

Cuestiones relacionadas