我在Gtk3中翻译了TreeView gtk2工具提示 它几乎正在运行,但我有管理工具提示窗口坐标的问题。
我希望工具提示窗口位于鼠标附近并靠近它。而不是我的项目工具提示窗口位于屏幕的角落
我的代码是
#!/usr/bin/env python
# coding: utf-8
'''
warning data not update !!!!!!!!!!!!!
TreeViewTooltips.py
Provides TreeViewTooltips, a class which presents tooltips for cells,
columns and rows in a Gtk.TreeView.
------------------------------------------------------------
This file includes a demo. Just execute the file:
python TreeViewTooltips.py
------------------------------------------------------------
To use, first subclass TreeViewTooltips and implement the get_tooltip()
method; see below. Then add any number of Gtk.TreeVew widgets to a
TreeViewTooltips instance by calling the add_view() method. Overview
of the steps:
# 1. subclass TreeViewTooltips
class MyTooltips(TreeViewTooltips):
# 2. overriding get_tooltip()
def get_tooltip(...):
...
# 3. create an instance
mytips = MyTooltips()
# 4. Build up your Gtk.TreeView.
myview = Gtk.TreeView()
...# create columns, set the model, etc.
# 5. Add the view to the tooltips
mytips.add_view(myview)
How it works: the add_view() method connects the TreeView to the
"motion-notify" event with the callback set to a private method.
Whenever the mouse moves across the TreeView the callback will call
get_tooltip() with the following arguments:
get_tooltip(view, column, path)
where,
view: the Gtk.TreeView instance.
column: the Gtk.TreeViewColumn instance that the mouse is
currently over.
path: the path to the row that the mouse is currently over.
Based on whether or not column and path are checked for specific
values, get_tooltip can return tooltips for a cell, column, row or the
whole view:
Column Checked Path Checked Tooltip For...
Y Y cell
Y N column
N Y row
N N view
get_tooltip() should return None if no tooltip should be displayed.
Otherwise the return value will be coerced to a string (with the str()
builtin) and stripped; if non-empty, the result will be displayed as
the tooltip. By default, the tooltip popup window will be displayed
centered and just below the pointer and will remain shown until the
pointer leaves the cell (or column, or row, or view, depending on how
get_tooltip() is implemented).
'''
from gi.repository import Gtk
class TreeViewTooltips_gtk3:
"""tooltip atttach to Treeview in Gtk3
this window is moving to follow row of Treeview"""
def __init__(self):
self.win = Gtk.Window()
self.win.set_decorated(False)
self.win.set_default_size(-1, -1)
self.label = Gtk.Label()
self.win.add(self.label)
# by default, the tooltip is enabled
self.__enabled = True
def __show(self, tooltip, x, y):
"""in order to move the tooltip near row of Treeview"""
self.label.set_markup(tooltip)
w,h = self.win.get_preferred_width()
# move the window
self.win.move(*self.location(x,y,w,h))
# show it
self.win.show_all()
return self.win
def __leave_handler(self, view, event):
"""when the pointer leaves the view, hide the tooltip"""
self.win.hide()
def enable(self):
'Enable the tooltip'
self.__enabled = True
def disable(self):
'Disable the tooltip'
self.__enabled = False
def location(self, x, y, w, h):
'''Given the x,y coordinates of the pointer and the width and
height (w,h) demensions of the tooltip window, return the x, y
coordinates of the tooltip window.
The default location is to center the window on the pointer
and 4 pixels below it.
# en clair c'est un décalage de position de la fenetre qui s'ouvre qui donne l'info
'''
return x - w/2, y + 4
def tooltip_callback(self,treeview, x, y, keyboard_mode, tooltip):
""" in order to collect miscellaneous elemnt to build data with row of treeview"""
"""3eme règle implementer ça pour afficher un tooltip customisé en fonction des data du tree view"""
x, y = treeview.convert_widget_to_bin_window_coords(x, y)
if not self.__enabled :
"""if you don't want tooltip display just return False !!!!"""
return False
try:
path, column, cell_x, cell_y = treeview.get_path_at_pos(x, y)
iter = model.get_iter(path)
#print 'tooltip=',self.get_tooltip(column, self.cust_col,path)
treeview.set_tooltip_window(self.__show(self.get_tooltip(column, self.cust_col,path),x,y))
# necessary to return True in order to display window tooltip
print "path is valid :-)"
return True
except:
# to prevent case when path it's not valid
print "perhaps path it's not valid ????"
# not possible to display something
return False
def add_view(self, view):
"""add a Gtk.TreeView to the tooltip
check if view is instance of Gtk.TreeView
and build connector and tooltip enable"""
assert isinstance(view, Gtk.TreeView), \
('This handler should only be connected to '
'instances of Gtk.TreeView')
# first condition in gtk3
# set True the property "has-tooltip"
view.set_property("has-tooltip", True)
# second condition in gtk3
view.connect('query-tooltip',self.tooltip_callback)
# hide tooltip when mouse out of widget
view.connect("leave-notify-event", self.__leave_handler)
def get_tooltip(self, view, column, path):
"""in order to secure customized implementation in your projet"""
'See the module doc string for a description of this method'
raise NotImplemented, 'Subclass must implement get_tooltip()'
if __name__ == '__main__':
class DemoTips_Gtk3(TreeViewTooltips_gtk3):
"""demo play how to """
def __init__(self, customer_column):
"""
init class
customer_column is an instance of Gtk.TreeViewColumn and
is being used in the Gtk.TreeView to show customer names."""
self.cust_col = customer_column
# call base class init
TreeViewTooltips_gtk3.__init__(self)
def get_tooltip(self, column,cust_col,path):
"""By checking both column and path we have a cell-based tooltip"""
model = view.get_model()
customer = model[path][2]
if column is cust_col:
"""here there is lot of information on row"""
return '<big>%s %s</big>\n<i>%s</i>' % (customer.fname,
customer.lname,
customer.notes)
else:
"""here basic data only !!!!"""
return ('<big><u>Generic Column Tooltip</u></big>\n'
'Unless otherwise noted, all\n phone number is %s ') % customer.phone
# Here's our customer
class Customer:
def __init__(self, fname, lname, phone, notes):
self.fname = fname
self.lname = lname
self.phone = phone
self.notes = notes
# create a bunch of customers
customers = []
for fname, lname, phone, notes in [
('Joe', 'Schmoe', '555-1212', 'Likes to Morris dance.'),
('Jane', 'Doe', '555-2323',
'Wonders what the hell\nMorris dancing is.'),
('Phred', 'Phantastic', '900-555-1212', 'Dreams of Betty.'),
('Betty', 'Boop', '555-3434', 'Dreams in b&w.'),
('Red Sox', 'Fan', '555-4545',
"Still livin' 2004!\nEspecially after 2006.")]:
customers.append(Customer(fname, lname, phone, notes))
# Build our model and view
model = Gtk.ListStore(str, str, object)
for c in customers:
model.append(['%s %s' % (c.fname, c.lname), c.phone, c])
view = Gtk.TreeView(model)
# two columns, name and phone
cell = Gtk.CellRendererText()
cell.set_property('xpad', 20)
namecol = Gtk.TreeViewColumn('Customer Name', cell, text=0)
namecol.set_min_width(200)
view.append_column(namecol)
cell = Gtk.CellRendererText()
phonecol = Gtk.TreeViewColumn('Phone', cell, text=1)
view.append_column(phonecol)
# finally, connect the tooltip, specifying the name column as the
# column we want the tooltip to popup over.
tips = DemoTips_Gtk3(namecol)
tips.add_view(view)
# We're going to demonstrate enable/disable. First we need a
# callback function to connect to the toggled signal.
def toggle(button):
if button.get_active():
tips.disable()
else:
tips.enable()
# create a checkbutton and connect our handler
check = Gtk.CheckButton('Check to disable view tooltips')
check.connect('toggled', toggle)
check.set_tooltip_markup('This is a standard Gtk tooltip.\n'
'Compare me to the tooltips above.')
# create a VBox to pack the view and checkbutton
vbox = Gtk.VBox()
vbox.pack_start(view,False,False,2)
vbox.pack_start(check,False,False,2)
vbox.show_all()
# pack the vbox into a simple dialog and run it
dialog = Gtk.Dialog('TreeViewTooltips Demo')
close = dialog.add_button(Gtk.STOCK_CLOSE,Gtk.ResponseType.NONE)
# add a tooltip for the close button
close.set_tooltip_markup('Click to end the demo.')
dialog.set_default_size(400,400)
dialog.vbox.pack_start(vbox,False,False,2)
dialog.run()
为了将工具提示与TreeView的相对坐标放在一起,谁能给我一些元素? 谢谢你的提前 我很抱歉我的英文不好
答案 0 :(得分:0)
您正在使用本地坐标,因此需要参考对话框位置以获取根坐标。你的脚本的另一个问题是主窗口是一个对话框,因此在前台,工具提示出现在它下面(我已修复但后来删除了代码(oops)。它可以工作,只需更改普通窗口的对话框) 。总的来说,当需要根坐标时,所有窗口小部件都知道它的父窗口可以引用它。
请参阅下面的修改(但未清理)代码:
#!/usr/bin/env python
# coding: utf-8
from gi.repository import Gtk
class TreeViewTooltips_gtk3:
"""tooltip atttach to Treeview in Gtk3
this window is moving to follow row of Treeview"""
def __init__(self):
self.win = Gtk.Window()
self.win.set_decorated(False)
self.win.set_default_size(-1, -1)
self.label = Gtk.Label()
self.win.add(self.label)
# by default, the tooltip is enabled
self.__enabled = True
def __show(self, tooltip, x, y):
"""in order to move the tooltip near row of Treeview"""
self.label.set_markup(tooltip)
w,h = self.win.get_preferred_width()
# move the window
self.win.move(*self.location(x,y,w,h))
# show it
self.win.show_all()
return self.win
def __leave_handler(self, view, event):
"""when the pointer leaves the view, hide the tooltip"""
self.win.hide()
def enable(self):
'Enable the tooltip'
self.__enabled = True
def disable(self):
'Disable the tooltip'
self.__enabled = False
def location(self, x, y, w, h):
'''Given the x,y coordinates of the pointer and the width and
height (w,h) demensions of the tooltip window, return the x, y
coordinates of the tooltip window.
The default location is to center the window on the pointer
and 4 pixels below it.
# en clair c'est un décalage de position de la fenetre qui s'ouvre qui donne l'info
'''
return x - w/2, y + 4
def tooltip_callback(self,treeview, x, y, keyboard_mode, tooltip):
""" in order to collect miscellaneous elemnt to build data with row of treeview"""
"""3eme règle implementer ça pour afficher un tooltip customisé en fonction des data du tree view"""
root_x, root_y = self.dialog.get_position() #get the root coordinates
x, y = treeview.convert_widget_to_bin_window_coords(x, y)
if not self.__enabled :
"""if you don't want tooltip display just return False !!!!"""
return False
try:
path, column, cell_x, cell_y = treeview.get_path_at_pos(x, y)
iter = model.get_iter(path)
#print 'tooltip=',self.get_tooltip(column, self.cust_col,path)
#add the root coordinates to local coordinates
treeview.set_tooltip_window(self.__show(self.get_tooltip(column, self.cust_col,path),root_x+x,root_y+y))
# necessary to return True in order to display window tooltip
print("path is valid :-)")
return True
except:
# to prevent case when path it's not valid
print("perhaps path it's not valid ????")
# not possible to display something
return False
def add_view(self, view):
"""add a Gtk.TreeView to the tooltip
check if view is instance of Gtk.TreeView
and build connector and tooltip enable"""
assert isinstance(view, Gtk.TreeView), \
('This handler should only be connected to '
'instances of Gtk.TreeView')
# first condition in gtk3
# set True the property "has-tooltip"
view.set_property("has-tooltip", True)
# second condition in gtk3
view.connect('query-tooltip',self.tooltip_callback)
# hide tooltip when mouse out of widget
view.connect("leave-notify-event", self.__leave_handler)
def get_tooltip(self, view, column, path):
"""in order to secure customized implementation in your projet"""
'See the module doc string for a description of this method'
raise NotImplemented('Subclass must implement get_tooltip()')
if __name__ == '__main__':
class DemoTips_Gtk3(TreeViewTooltips_gtk3):
"""demo play how to """
def __init__(self, customer_column):
"""
init class
customer_column is an instance of Gtk.TreeViewColumn and
is being used in the Gtk.TreeView to show customer names."""
self.cust_col = customer_column
# call base class init
TreeViewTooltips_gtk3.__init__(self)
def get_tooltip(self, column,cust_col,path):
"""By checking both column and path we have a cell-based tooltip"""
model = view.get_model()
customer = model[path][2]
if column is cust_col:
"""here there is lot of information on row"""
return '<big>%s %s</big>\n<i>%s</i>' % (customer.fname,
customer.lname,
customer.notes)
else:
"""here basic data only !!!!"""
return ('<big><u>Generic Column Tooltip</u></big>\n'
'Unless otherwise noted, all\n phone number is %s ') % customer.phone
# Here's our customer
class Customer:
def __init__(self, fname, lname, phone, notes):
self.fname = fname
self.lname = lname
self.phone = phone
self.notes = notes
# create a bunch of customers
customers = []
for fname, lname, phone, notes in [
('Joe', 'Schmoe', '555-1212', 'Likes to Morris dance.'),
('Jane', 'Doe', '555-2323',
'Wonders what the hell\nMorris dancing is.'),
('Phred', 'Phantastic', '900-555-1212', 'Dreams of Betty.'),
('Betty', 'Boop', '555-3434', 'Dreams in b&w.'),
('Red Sox', 'Fan', '555-4545',
"Still livin' 2004!\nEspecially after 2006.")]:
customers.append(Customer(fname, lname, phone, notes))
# Build our model and view
model = Gtk.ListStore(str, str, object)
for c in customers:
model.append(['%s %s' % (c.fname, c.lname), c.phone, c])
view = Gtk.TreeView(model)
# two columns, name and phone
cell = Gtk.CellRendererText()
cell.set_property('xpad', 20)
namecol = Gtk.TreeViewColumn('Customer Name', cell, text=0)
namecol.set_min_width(200)
view.append_column(namecol)
cell = Gtk.CellRendererText()
phonecol = Gtk.TreeViewColumn('Phone', cell, text=1)
view.append_column(phonecol)
# finally, connect the tooltip, specifying the name column as the
# column we want the tooltip to popup over.
tips = DemoTips_Gtk3(namecol)
tips.add_view(view)
# We're going to demonstrate enable/disable. First we need a
# callback function to connect to the toggled signal.
def toggle(button):
if button.get_active():
tips.disable()
else:
tips.enable()
# create a checkbutton and connect our handler
check = Gtk.CheckButton('Check to disable view tooltips')
check.connect('toggled', toggle)
check.set_tooltip_markup('This is a standard Gtk tooltip.\n'
'Compare me to the tooltips above.')
# create a VBox to pack the view and checkbutton
vbox = Gtk.VBox()
vbox.pack_start(view,False,False,2)
vbox.pack_start(check,False,False,2)
vbox.show_all()
# pack the vbox into a simple dialog and run it
dialog = Gtk.Dialog('TreeViewTooltips Demo')
tips.dialog = dialog #give tips the main window reference
close = dialog.add_button(Gtk.STOCK_CLOSE,Gtk.ResponseType.NONE)
# add a tooltip for the close button
close.set_tooltip_markup('Click to end the demo.')
dialog.set_default_size(400,400)
dialog.vbox.pack_start(vbox,False,False,2)
dialog.run()