PyGTK自定义组合框行为

0 投票
1 回答
971 浏览
提问于 2025-04-16 12:51

我正在尝试创建一个自定义的下拉框,想让它的行为和这里的那个一样:http://chir.ag/projects/name-that-color/

现在我遇到了两个问题:

  1. 我找不到办法在旁边加一个滚动条;理论上,gtk.rc_parse_string 函数应该可以做到这一点,因为下拉框小部件有一个“看起来像列表”的样式属性,但我的自定义小部件似乎没有受到影响,不知道为什么。

  2. 当你从我的小部件中选择一个颜色后,再次点击下拉框时,它并没有显示你选中的项目和它的邻近项,而是滚动窗口又从顶部开始,原因不明。

这是代码,你可以基本上忽略 __load_name_palette 方法。运行这段代码需要 /usr/share/X11/rgb.txt 文件,它的内容长这样:http://pastebin.com/raw.php?i=dkemmEdr

import gtk
import gobject
from os.path import exists

def window_delete_event(*args):
   return False

def window_destroy(*args):
    gtk.main_quit()

class ColorName(gtk.ComboBox):
    colors = []
    def __init__(self, name_palette_path, wrap_width=1):
        gtk.ComboBox.__init__(self)
        liststore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING,
                                 gobject.TYPE_STRING)
        name_palette = self.__load_name_palette(name_palette_path)
        for c in name_palette:
            r, g, b, name = c
            if ((r + g + b) / 3.) < 128.:
                fg = '#DDDDDD'
            else:
                fg = '#222222'
            bg = "#%02X%02X%02X" % (r, g, b)
            liststore.append((name, bg, fg))

        self.set_model(liststore)
        label = gtk.CellRendererText()
        self.pack_start(label, True)
        self.set_attributes(label, background=1, foreground=2, text=0)
        self.set_wrap_width(wrap_width)

        if len(name_palette) > 0:
            self.set_active(0)
        self.show_all()

    def __load_name_palette(self, name_palette_path):
        if exists(name_palette_path):
            try:
                f = open(name_palette_path,'r')
                self.colors = []
                palette = set()
                for l in f:
                    foo = l.rstrip().split(None,3)
                    try:
                        rgb = [int(x) for x in foo[:3]]
                        name, = foo[3:]
                    except:
                        continue
                    k = ':'.join(foo[:3])
                    if k not in palette:
                        palette.add(k)
                        self.colors.append(rgb + [name])
                f.close()
                return self.colors
            except IOError as (errno, strerror):
                print "error: failed to open {0}: {1}".format(name_palette_path, strerror)
                return []
            else:
                return []

if __name__ == '__main__':
    win = gtk.Window()
    #colname = ColorName('./ntc.txt')
    colname = ColorName('/usr/share/X11/rgb.txt')
    gtk.rc_parse_string("""style "mystyle" { GtkComboBox::appears-as-list = 1 }
    class "GtkComboBox" style "mystyle" """)
    print 'appears-as-list:', colname.style_get_property('appears-as-list')
    model = gtk.ListStore(gobject.TYPE_STRING)
    hbox = gtk.HBox()
    win.add(hbox)
    hbox.pack_start(colname)
    win.connect('delete-event', window_delete_event)
    win.connect('destroy', window_destroy)
    win.show_all()
    gtk.main()

1 个回答

1

问题出在 self.show_all() 这一行。另外,你不能同时使用列表和 wrap_width 不等于 1 的情况。

撰写回答