2017-02-08 50 views
3

我有一个GtkTreeView具有两列文本类型(例如G_TYPE_STRING),我使用GtkCellRendererText来呈现列。如何将悬停效果添加到GtkTreeView单元格

是否有任何为什么我可以在鼠标进入并离开特定单元格时作出反应,然后悬停或突出显示单元格。

例如,我想在鼠标输入时在单元格渲染器中为文本添加下划线,以便提供一个视觉线索,指出可以单击该单元格以执行操作。

回答

1

有相当来完成任务的几种方法。下面有几个例子,用水平线分隔。


最简单的,而且在某些方面是最好的,选择是简单地将鼠标光标更改为GtkTreeView内的手指(一样指向一个链接,当你在浏览器中看到鼠标光标)。

比方说GtkTreeView *view是我们感兴趣的观点。后你叫gtk_widget_show_all(window);,您可以拨打

GdkWindow *win = gtk_tree_view_get_bin_window(GTK_TREE_VIEW(view)); 
GdkDisplay *disp = gdk_window_get_display(win); 
gdk_window_set_cursor(win, gdk_cursor_new_from_name(disp, "pointer")); 

这样,鼠标指针会在视图中的所有行的手指,不包括标题行。

GDK3文档中列出了您可以使用的一组游标名称(而不是上面的"pointer"here

缺点是,如果在树视图或分隔行中有空行,那么鼠标指针仍然看起来像一个手指。


您可以通过应用程序特定的CSS悬停颜色覆盖悬停颜色,说

GtkTreeView:hover { 
    color: #ff0000; 
} 

与例如

GtkCssProvider *css_provider; 
css_provider = gtk_css_provider_new(); 
if (gtk_css_provider_load_from_data(css_provider, 
      "GtkTreeView:hover {\n" 
      " color: #ff0000;\n" 
      "}\n" 
      "", -1, NULL)) 
    gtk_style_context_add_provider_for_screen(gdk_screen_get_default(), 
       GTK_STYLE_PROVIDER(css_provider), 
       GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); 
g_object_unref(css_provider); 

创建主窗口后。 (当然,您可以在CSS片段中包含所有特定于应用程序的CSS覆盖。)

但是,至少在gtk + 3.18.9上,渲染器似乎不支持此处的text-decorationfont CSS属性。 (如果你想知道,GtkCssProvider似乎不支持cursor属性。)

此外,由于这基本上覆盖了用户主题,并且Gtk +用户可能会使用一些可能的主题,以这种方式改变颜色在所有主题中都不太可能看起来不错。


如果您GtkTreeView *view;由可点击的行,你不需要任何东西的选择(也就是你没有一个单独的按钮或东西,导致被应用到所有选择的动作在GtkTreeView行),然后就可以简单地设置选择跟随鼠标光标:

gtk_tree_view_set_hover_selection(view, TRUE); 

这导致选择将光标悬停在该行,并且因此也突出显示。你可能也想选择限制在一排在一个时间:

gtk_tree_selection_set_mode(gtk_tree_view_get_selection(view), 
          GTK_SELECTION_SINGLE); 

由于Herbalist already mentioned,您可以创建自定义GtkCellRendererText衍生物,它改变了PangoUnderline underline属性取决于被呈现的文本单元是也prelit(鼠标悬停)或不:

#include <gtk/gtk.h> 

#define CUSTOM_TYPE_CELL_RENDERER_TEXT   (custom_cell_renderer_text_get_type()) 
#define CUSTOM_CELL_RENDERER_TEXT(obj)   (G_TYPE_CHECK_INSTANCE_CAST((obj), CUSTOM_TYPE_CELL_RENDERER_TEXT, CustomCellRendererText)) 
#define CUSTOM_CELL_RENDERER_TEXT_CLASS(cls)  (G_TYPE_CHECK_CLASS_CAST((cls), CUSTOM_TYPE_CELL_RENDERER_TEXT, CustomCellRendererTextClass)) 
#define CUSTOM_IS_CELL_RENDERER_TEXT(obj)  (G_TYPE_CHECK_INSTANCE_TYPE((obj), CUSTOM_TYPE_CELL_RENDERER_TEXT)) 
#define CUSTOM_IS_CELL_RENDERER_TEXT_CLASS(cls) (G_TYPE_CHECK_CLASS_TYPE((cls), CUSTOM_TYPE_CELL_RENDERER_TEXT)) 
#define CUSTOM_CELL_RENDERER_TEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), CUSTOM_TYPE_CELL_RENDERER_TEXT, CustomCellRendererTextClass)) 

GType custom_cell_renderer_text_get_type(void) G_GNUC_CONST; 

typedef struct { 
    GtkCellRendererText renderer; 
} CustomCellRendererText; 

typedef struct { 
    GtkCellRendererTextClass parent_class; 
} CustomCellRendererTextClass; 

G_DEFINE_TYPE(CustomCellRendererText, custom_cell_renderer_text, GTK_TYPE_CELL_RENDERER_TEXT); 

void custom_cell_renderer_text_render(GtkCellRenderer *cell, 
             cairo_t *cr, 
             GtkWidget *widget, 
             const GdkRectangle *backarea, 
             const GdkRectangle *cellarea, 
             GtkCellRendererState state) 
{ 
    if (state & GTK_CELL_RENDERER_PRELIT) { 
     const PangoUnderline prelit = PANGO_UNDERLINE_SINGLE; 
     PangoUnderline curr; 
     g_object_get(cell, "underline", &curr, NULL); 
     g_object_set(cell, "underline", prelit, NULL); 
     ((GtkCellRendererClass *)custom_cell_renderer_text_parent_class)->render(cell, cr, widget, backarea, cellarea, state); 
     g_object_set(cell, "underline", curr, NULL); 
    } else 
     ((GtkCellRendererClass *)custom_cell_renderer_text_parent_class)->render(cell, cr, widget, backarea, cellarea, state); 
} 

void custom_cell_renderer_text_class_init(CustomCellRendererTextClass *cls) 
{ 
    ((GtkCellRendererClass *)cls)->render = custom_cell_renderer_text_render; 
    return; 
} 

void custom_cell_renderer_text_init(CustomCellRendererText *renderer) 
{ 
    return; 
} 

GtkCellRenderer *custom_cell_renderer_text_new(void) 
{ 
    return g_object_new(CUSTOM_TYPE_CELL_RENDERER_TEXT, NULL); 
} 

如果再更换您gtk_cell_render_text_new()custom_cell_render_text_new()(和改变GtkCellRenderText *CustomCellRenderText *)在GtkTreeVi ew代码,您在GtkTreeView中悬停的行将变为下划线。

请注意,您将鼠标悬停在该行中的所有单元格将被突出显示,而不仅仅是细胞/列鼠标悬停。这是因为在GtkTreeView中,行(或索引)是被操纵的单位(而不是特定列上的特定单元格)。

如果您仅对GtkTreeView中的某些列使用上述渲染器,则即使将鼠标悬停在该行的某个其他列上,这些列中的文本也会加下划线。

另请注意,如果您不希望所有行都显示可点击性,则可以在数据模型中添加第三列 - 名称"sensitive",类型G_TYPE_BOOLEAN,用于gboolean类型;值TRUE如果行是可点击,FALSE如果行是不可点击 - 在custom_cell_renderer_text_render()if子句更改为

const GtkStateFlags flags = gtk_cell_renderer_get_state(cell, widget, state); 
    if ((state & GTK_CELL_RENDERER_PRELIT) && 
     !(flags & GTK_STATE_FLAG_INSENSITIVE)) { 

GTK +会使行与TRUE正常,和行与FALSE作为分隔符或禁用的文本,因为模型中的列名自动与具有相同名称的GtkCellRenderer属性关联。

+0

@lanoxx:什么是你的意图与非功能编辑的示例代码?所显示的代码经过测试可以正常工作,并且您的更改没有提供功能差异,那么它们的目的是什么? (我发现编辑尝试*可疑*,说实话,所以我想请在这里澄清一下。) –

+0

为搞砸代码清单道歉。我试图重新格式化它,以避免必须左右滚动。在我看来,这将使代码列表更加可读。使用两种'G_DECLARE_FINAL_TYPE'或'的G_DECLARE_DERIVABLE_TYPE'也使上市更短,因为你不需要在上面定义的6个宏,并根据您使用这两个宏,你可以省略一些'结构的'声明。 – lanoxx

+0

顺便说一句。我不认为这除了是必要的:**(并更改GtkCellRenderText *至* CustomCellRenderText)在GtkTreeView代码,**,因为自定义渲染器的新功能实际上返回一个'GtkCellRenderer'实例。 – lanoxx

2

如果存在PRELIT标志,您可以自定义CellRendererText并设置下划线属性。

我只知道在Python:

class My_CellRendererText(Gtk.CellRendererText): 
def __init__(self): 
    super().__init__() 

def do_render(self, cr, widget, background_area, cell_area, flags): 
    self.props.underline = ((flags & Gtk.CellRendererState.PRELIT) != 0) 
    return Gtk.CellRendererText.do_render(self, cr, widget, background_area, cell_area, flags) 

GObject.type_register(My_CellRendererText) 
相关问题