I’m trying to create a custom ComboBox that behaves like the one in here: http://chir.ag/projects/name-that-color/
I’ve got two problems right now:
-
I can’t seem to find a way to have a scrollbar on the side; the
gtk.rc_parse_stringfunction should do that, since the ComboBox widget has a “appears-as-list” style property, but my custom widget seems unaffected for some reason. -
When you select a color from my widget, then click the ComboBox again, instead of showing the selected item and its neighbours, the scrolled window starts from the top, for no apparent reason.
This is the code, you can pretty much ignore the __load_name_palette method. You need the /usr/share/X11/rgb.txt file to run this code, it looks like this: 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()
The problem was the
self.show_all()line. Also, you can’t have a list AND awrap_width!= 1