如何在gtk3 python中管理绝对坐标窗口

时间:2016-05-25 08:29:00

标签: python-2.7 gtk3

我在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&amp;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的相对坐标放在一起,谁能给我一些元素? 谢谢你的提前 我很抱歉我的英文不好

1 个答案:

答案 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&amp;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()