如何在自定义 CellRenderer 上检测鼠标位置
How to detect mouse position on custom CellRenderer
一段时间以来,我一直在努力检测自定义 Gtk.CellRenderer
上的鼠标坐标。
我一直在阅读一些不错的文档,例如:
但我仍然不确定该怎么做。我已经尝试了很多事情,例如尝试使用 __gsignals__
连接信号或尝试使用虚拟方法。
我需要这样做,因为我正在构建评级小部件。 raiting 小部件包含的开头如下:★★★★★
我希望当用户将鼠标悬停在上面时,相对 x
位置会修改启动数。
我还想连接一个 clicked
信号以保存用户选择的启动次数。
下面是我当前的工作代码。非常感谢对此的任何帮助!
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('PangoCairo', '1.0')
from gi.repository import Gtk, Gdk, cairo, Pango, PangoCairo, GObject
class CellRendererRating(Gtk.CellRenderer):
""" Cellrenderer to display ratings from 0 to 5: ★★★★★, ★★★☆☆, etc """
__gproperties__ = {
'rating': ( int, # type
"integer prop", # nick
"A property that contains an integer", # blurb
0, # min
5, # max
0, # default
GObject.PARAM_READWRITE # flags
),
}
def __init__(self):
super().__init__()
self.font_size=15
self.font="Sans Bold {}".format(self.font_size)
self.rating = 0
def activate(event, widget, path, background_area, cell_area, flags):
print(path)
def do_set_property(self, pspec, value):
setattr(self, pspec.name, value)
def do_get_property(self, pspec):
return getattr(self, pspec.name)
def do_get_size(self, widget, cell_area):
return (0, 0, self.font_size*5, self.font_size+5)
def do_start_editing(event, widget, path, background_area, cell_area, flags):
print('called')
def do_render(self, cr, treeview, background_area, cell_area, flags):
cr.translate (0, 0)
layout = PangoCairo.create_layout(cr)
#layout.set_font_description(FONT_CELLRATING_DESCRIPTION)
if 'GTK_CELL_RENDERER_FOCUSED' in str(flags) and self.rating < 5:
for i in range(5):
if i < self.rating:
layout.set_text("★", -1)
else:
layout.set_text("☆", -1)
cr.save()
PangoCairo.update_layout (cr, layout)
cr.move_to (cell_area.x+i*(self.font_size+1), cell_area.y)
PangoCairo.show_layout (cr, layout)
cr.restore()
else:
for i in range(self.rating):
layout.set_text("★", -1)
cr.save()
PangoCairo.update_layout (cr, layout)
cr.move_to (cell_area.x+i*(self.font_size+1), cell_area.y)
PangoCairo.show_layout (cr, layout)
cr.restore()
GObject.type_register(CellRendererRating)
if __name__ == '__main__':
class Window(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.connect('destroy', self.on_quit)
liststore = Gtk.ListStore(int)
for i in range(6):
liststore.append([i])
treeview = Gtk.TreeView(liststore)
treeviewcolumn = Gtk.TreeViewColumn("Rating")
treeviewcolumn.set_resizable(True)
cellrenderer = CellRendererRating()
treeviewcolumn.pack_start(cellrenderer, True)
treeviewcolumn.add_attribute(cellrenderer, 'rating', 0)
treeview.append_column(treeviewcolumn)
self.add(treeview)
self.show_all()
def on_quit(self, widget, data=None):
Gtk.main_quit()
w = Window()
Gtk.main()
可以通过以下方式获取光标在 CellRenderer
上的位置:
def do_render(self, cr, treeview, background_area, cell_area, flags):
mouse_x, mouse_y = treeview.get_pointer()
cell_render_x = mouse_x - cell_area.x
cell_render_y = mouse_y - cell_area.y
但这可能不是您问题的最佳解决方案,因为已经有一个 Rating-CellRenderer
完全符合您的要求,即 RB.CellRendererRating
。我建议使用它们的实现,既可以按原样使用,也可以作为自定义版本的基础。
RB.CellRendererRating.new()
Create a cell renderer that will display some pixbufs for representing the rating of a song. It is also able to update the rating.
一段时间以来,我一直在努力检测自定义 Gtk.CellRenderer
上的鼠标坐标。
我一直在阅读一些不错的文档,例如:
但我仍然不确定该怎么做。我已经尝试了很多事情,例如尝试使用 __gsignals__
连接信号或尝试使用虚拟方法。
我需要这样做,因为我正在构建评级小部件。 raiting 小部件包含的开头如下:★★★★★
我希望当用户将鼠标悬停在上面时,相对 x
位置会修改启动数。
我还想连接一个 clicked
信号以保存用户选择的启动次数。
下面是我当前的工作代码。非常感谢对此的任何帮助!
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('PangoCairo', '1.0')
from gi.repository import Gtk, Gdk, cairo, Pango, PangoCairo, GObject
class CellRendererRating(Gtk.CellRenderer):
""" Cellrenderer to display ratings from 0 to 5: ★★★★★, ★★★☆☆, etc """
__gproperties__ = {
'rating': ( int, # type
"integer prop", # nick
"A property that contains an integer", # blurb
0, # min
5, # max
0, # default
GObject.PARAM_READWRITE # flags
),
}
def __init__(self):
super().__init__()
self.font_size=15
self.font="Sans Bold {}".format(self.font_size)
self.rating = 0
def activate(event, widget, path, background_area, cell_area, flags):
print(path)
def do_set_property(self, pspec, value):
setattr(self, pspec.name, value)
def do_get_property(self, pspec):
return getattr(self, pspec.name)
def do_get_size(self, widget, cell_area):
return (0, 0, self.font_size*5, self.font_size+5)
def do_start_editing(event, widget, path, background_area, cell_area, flags):
print('called')
def do_render(self, cr, treeview, background_area, cell_area, flags):
cr.translate (0, 0)
layout = PangoCairo.create_layout(cr)
#layout.set_font_description(FONT_CELLRATING_DESCRIPTION)
if 'GTK_CELL_RENDERER_FOCUSED' in str(flags) and self.rating < 5:
for i in range(5):
if i < self.rating:
layout.set_text("★", -1)
else:
layout.set_text("☆", -1)
cr.save()
PangoCairo.update_layout (cr, layout)
cr.move_to (cell_area.x+i*(self.font_size+1), cell_area.y)
PangoCairo.show_layout (cr, layout)
cr.restore()
else:
for i in range(self.rating):
layout.set_text("★", -1)
cr.save()
PangoCairo.update_layout (cr, layout)
cr.move_to (cell_area.x+i*(self.font_size+1), cell_area.y)
PangoCairo.show_layout (cr, layout)
cr.restore()
GObject.type_register(CellRendererRating)
if __name__ == '__main__':
class Window(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.connect('destroy', self.on_quit)
liststore = Gtk.ListStore(int)
for i in range(6):
liststore.append([i])
treeview = Gtk.TreeView(liststore)
treeviewcolumn = Gtk.TreeViewColumn("Rating")
treeviewcolumn.set_resizable(True)
cellrenderer = CellRendererRating()
treeviewcolumn.pack_start(cellrenderer, True)
treeviewcolumn.add_attribute(cellrenderer, 'rating', 0)
treeview.append_column(treeviewcolumn)
self.add(treeview)
self.show_all()
def on_quit(self, widget, data=None):
Gtk.main_quit()
w = Window()
Gtk.main()
可以通过以下方式获取光标在 CellRenderer
上的位置:
def do_render(self, cr, treeview, background_area, cell_area, flags):
mouse_x, mouse_y = treeview.get_pointer()
cell_render_x = mouse_x - cell_area.x
cell_render_y = mouse_y - cell_area.y
但这可能不是您问题的最佳解决方案,因为已经有一个 Rating-CellRenderer
完全符合您的要求,即 RB.CellRendererRating
。我建议使用它们的实现,既可以按原样使用,也可以作为自定义版本的基础。
RB.CellRendererRating.new()
Create a cell renderer that will display some pixbufs for representing the rating of a song. It is also able to update the rating.