如何在Gtk IconView的单元格中找到光标位置?

时间:2013-10-17 19:12:10

标签: python gtk

pic

我正在尝试做的是找出我是否在Gtk Iconview中点击了一个单元格的特定位置(图片上的蓝框)

在我目前的调查期间,如果可能的话,我发现我可以通过以下两种方法之一获得光标位置:

方法1:添加POINTER_MOTION_MASK,以便您可以检测IconView上当前光标的位置

 self.iconview.add_events(Gdk.EventMask.POINTER_MOTION_MASK)
 self.iconview.connect("motion-notify-event", self.on_pointer_motion)

因此,当前光标位置和单元格可以找到:

 def on_pointer_motion(self, widget, event):
    path= self.get_path_at_pos(event.x, event.y)

方法2:连接到“按钮按事件”

 self.iconview.connect("button-press-event", self.on_mouse_click)

 def on_mouse_click(self, widget, event):
    path= self.get_path_at_pos(event.x, event.y)

我需要的是确定event.x和event.y是否可以绑定到单元格内的特定区域,如图中的蓝色所示。

我查看了GtkCellAreaGtkCellAreaBoxGtkIconView的非官方参考资料,但我没有看到明显的事件/函数来帮助解决这个问题。

任何人都可以在正确的方向上给我任何指示来解决这个问题吗?

我正在使用Python 2.7& GTK + 3.2作为我的开发环境,但我的目标是python 3+以及GTK + 3.2之后的所有GTK版本

1 个答案:

答案 0 :(得分:0)

这很容易。

以下是Playlist.py,来自我的一个开源PyGObject项目。 连接GtkIconVIew的button-press-event信号,并检查事件类型。iconview.get_path_at_pos(...)将返回path。路径可能是None或选定单元格的位置,具体取决于光标位置。 该项目可在此处找到https://github.com/LiuLang/babystory

# Copyright (C) 2013 LiuLang <gsushzhsosgsu@gmail.com>

# Use of this source code is governed by GPLv3 license that can be found
# in http://www.gnu.org/licenses/gpl-3.0.html

from gi.repository import GdkPixbuf
from gi.repository import Gdk
from gi.repository import Gtk
import json
import random

from babystory.Cache import Cache
from babystory import Config
from babystory import Net
from babystory import Utils
from babystory import Widgets

_ = Config._
TITLE, SIZE, DURATION, URL, CATEGORY = list(range(5))


def song_row_to_dict(song_row):
    song = {
            'Title': song_row[TITLE],
            'Size': song_row[SIZE],
            'Duration': song_row[DURATION],
            'Url': song_row[URL],
            'Category': song_row[CATEGORY],
            }
    return song

class Playlist(Gtk.Box):
    def __init__(self, app):
        self.app = app
        super().__init__()

        self.curr_playing = None
        self.prev_playing = None
        self.next_playing = None

        self.control_box = Gtk.Box()
        self.pack_start(self.control_box, False, False, 0)

        paned = Gtk.Paned()
        self.pack_start(paned, True, True, 0)

        left_window = Gtk.ScrolledWindow()
        paned.add1(left_window)
        paned.child_set_property(left_window, 'resize', True)

        # icon, id, title, 
        self.left_liststore = Gtk.ListStore(GdkPixbuf.Pixbuf, int, str)
        self.left_iconview = Gtk.IconView(model=self.left_liststore)
        self.left_iconview.set_pixbuf_column(0)
        self.left_iconview.set_text_column(2)
        self.left_iconview.props.item_width = 130
        if Gtk.MINOR_VERSION > 6:
            self.left_iconview.props.activate_on_single_click = True
        self.left_iconview.connect('button-press-event',
                self.on_left_iconview_button_pressed)
        left_window.add(self.left_iconview)

        self.left_menu = Gtk.Menu()
        self.left_menu_cache = Gtk.MenuItem(_('Cache'))
        self.left_menu_cache.connect('activate',
                self.on_left_menu_cache_activated)
        self.left_menu.append(self.left_menu_cache)
        sep = Gtk.SeparatorMenuItem()
        self.left_menu.append(sep)
        self.left_menu_delete = Gtk.MenuItem(_('Delete'))
        self.left_menu_delete.connect('activate',
                self.on_left_menu_delete_activated)
        self.left_menu.append(self.left_menu_delete)

        self.right_window = Gtk.ScrolledWindow()
        paned.add2(self.right_window)
        paned.child_set_property(self.right_window, 'resize', True)

        # title, size, duration, url, category
        self.right_liststore = Gtk.ListStore(str, str, str, str, str)
        self.right_treeview = Gtk.TreeView(model=self.right_liststore)
        self.right_treeview.props.headers_visible = False
        self.right_window.add(self.right_treeview)
        self.right_treeview.connect('row_activated',
                self.on_right_treeview_row_activated)

        title_cell = Gtk.CellRendererText()
        title_col = Widgets.ExpandedTreeViewColumn(_('Title'), title_cell,
                text=TITLE)
        self.right_treeview.append_column(title_col)

        size_cell = Gtk.CellRendererText()
        size_col = Gtk.TreeViewColumn(_('Size'), size_cell, text=SIZE)
        self.right_treeview.append_column(size_col)

        duration_cell = Gtk.CellRendererText()
        duration_col = Gtk.TreeViewColumn(_('Duration'), duration_cell,
                text=DURATION)
        self.right_treeview.append_column(duration_col)

    def after_init(self):
        self.playlist = Config.load_playlist()
        self.left_liststore.append([self.app.theme['default-icon'], -1,
            'All Categories'])
        for cat_id in self.playlist:
            self.show_category(cat_id)

    # signal handlers starts
    def do_destroy(self):
        Config.dump_playlist(self.playlist)

    def on_left_iconview_button_pressed(self, iconview, event):
        if event.type != Gdk.EventType.BUTTON_PRESS:
            return False
        path = iconview.get_path_at_pos(event.x, event.y)
        if path is None:
            iconview.unselect_all()

        if event.button == Gdk.BUTTON_PRIMARY:
            if path is not None:
                self.on_left_iconview_item_activated(iconview, path)
            return True
        elif event.button == Gdk.BUTTON_SECONDARY:
            self.on_left_iconview_popup_menu(iconview, path, event)
            return True
        return False

    def on_left_iconview_popup_menu(self, iconview, path, event):
        self.left_menu.path = path
        if path is not None:
            self.on_left_iconview_item_activated(iconview, path)
            self.left_menu_delete.set_label(_('Delete'))
            self.left_menu_cache.set_label(_('Cache'))
        else:
            self.left_menu_delete.set_label(_('Delete All'))
            self.left_menu_cache.set_label(_('Cache All'))
        self.left_menu.show_all()
        self.left_menu.popup(None, None, None, None,
                event.button, event.time)

    def on_left_iconview_item_activated(self, iconview, path):
        self.left_iconview.select_path(path)
        model = self.left_iconview.get_model()
        pix, cat_id, title = model[path]
        self.curr_category = {'Pix': pix, 'Id': cat_id, 'Title': title, }
        self.right_liststore.clear()
        self.right_window.get_vadjustment().set_value(0)

        if cat_id != -1:
            self.append_song_to_liststore(cat_id)
            return
        for cat_id in self.playlist:
            self.append_song_to_liststore(cat_id)

    def on_left_menu_delete_activated(self, menu_item):
        path = self.left_menu.path
        if path is None or int(str(path)) == 0:
            while len(self.playlist) > 0:
                cat_id = self.playlist[len(self.playlist) - 1]
                self.remove_category(cat_id)
            return
        icon, cat_id, title = self.left_liststore[path]
        self.remove_category(cat_id)

    def on_left_menu_cache_activated(self, menu_item):
        path = self.left_menu.path
        if path is None:
            _path = Gtk.TreePath(0)
            self.left_iconview.select_path(_path)
            self.on_left_iconview_item_activated(self.left_iconview, _path)
        self.cache_job = Cache(self.app)
        self.cache_job.run()
        self.cache_job.destroy()

    def on_right_treeview_row_activated(self, treeview, path, column):
        self.play_song_at(int(str(path)))
    # signal handlers ends

    # 
    def show_category(self, cat_id):
        category = self.app.categories.category_list[str(cat_id)]
        image_path = Net.get_image(category['IconUrl'])
        if image_path:
            pix = GdkPixbuf.Pixbuf.new_from_file(image_path)
        else:
            pix = self.app.theme['default-icon']
        self.left_liststore.append([pix, category['Id'], category['Title']])

    def append_category(self, cat_id):
        if cat_id in self.playlist:
            return
        self.playlist.append(cat_id)
        self.show_category(cat_id)

    def remove_category(self, cat_id):
        if cat_id == -1:
            return
        index = self.playlist.index(cat_id)
        path = Gtk.TreePath(index + 1)
        _iter = self.left_liststore.get_iter(path)
        self.left_liststore.remove(_iter)
        self.playlist.remove(cat_id)

    def append_song_to_liststore(self, cat_id):
        songs_wrap = Net.get_songs(cat_id)
        if songs_wrap is None:
            return
        songs = songs_wrap['Items']
        category = self.get_category_title(cat_id)
        print('category:', category)
        for song in songs:
            self.right_liststore.append([
                song['Title'],
                Utils.print_size(song['Size']),
                Utils.print_duration(song['Duration']),
                song['Url'],
                category,
                ])

    def get_prev_song(self, repeat=False, shuffle=False):
        song_nums = len(self.right_liststore)
        if song_nums == 0:
            return None
        path = self.curr_playing
        if path == 0:
            if repeat:
                path = song_nums - 1
            else:
                path = 0
        else:
            path = path - 1
        self.prev_playing = path
        return self.get_song_from_index(self.prev_playing)

    def get_next_song(self, repeat=False, shuffle=False):
        song_nums = len(self.right_liststore)
        if song_nums == 0:
            return None
        path = self.curr_playing
        if shuffle:
            path = random.randint(0, song_nums-1)
        elif path == song_nums - 1:
            if repeat is False:
                self.next_playing = None
                return None
            path = 0
        else:
            path = path + 1
        self.next_playing = path
        print(self.curr_playing, self.prev_playing, self.next_playing)
        return self.get_song_from_index(self.next_playing)

    def play_prev_song(self, repeat=False, shuffle=False):
        if self.prev_playing is None:
            song = self.get_prev_song(repeat=repeat, shuffle=shuffle)
            if song is None:
                return
        self.curr_playing = self.prev_playing
        self.prev_playing = None
        self.play_song()

    def play_song(self):
        selection = self.right_treeview.get_selection()
        path = Gtk.TreePath(self.curr_playing)
        selection.select_path(path)
        song = self.get_song_from_index(self.curr_playing)
        self.app.player.load(song)

    def play_song_at(self, pos):
        print('play song at:', pos)
        self.curr_playing = pos
        self.play_song()

    def play_next_song(self, repeat=False, shuffle=False):
        if self.next_playing is None:
            song = self.get_next_song(repeat=repeat, shuffle=shuffle)
            if song is None:
                return
        self.curr_playing = self.next_playing
        self.next_playing = None
        self.play_song()

    def get_song_from_index(self, index):
        row = self.right_liststore[index]
        song = song_row_to_dict(row)
        return song

    def get_category_title(self, cat_id):
        return self.app.categories.category_list[str(cat_id)]['Title']

    def activate_iconview_item_with_cat_id(self, cat_id):
        i = 0
        for cate in self.left_liststore:
            if cate[1] == cat_id:
                break
            i += 1
        path = Gtk.TreePath(i)
        self.on_left_iconview_item_activated(self.left_iconview, path)