The following PyGTk code, gives a combo-box without an active item.
This serves a case where we do not want to have a default,
and force the user to select.
Still, is there a way to have the empty combo-bar show something like:
"Select an item..."
without adding a dummy item?
import gtk
import sys
say = sys.stdout.write
def cb_changed(w):
say("Active index=%d\n" % w.get_active())
topwin = gtk.Window()
topwin.set_title("No Default")
topwin.set_size_request(0x100, 0x20)
topwin.connect('delete-event', gtk.main_quit)
vbox = gtk.VBox()
ls = gtk.ListStore(str, str)
combo = gtk.ComboBox(ls)
cell = gtk.CellRendererText()
combo.pack_start(cell)
combo.add_attribute(cell, 'text', 0)
combo.connect('changed', cb_changed)
ls.clear()
map(lambda i: ls.append(["Item-%d" % i, "Id%d" % i]), range(3))
vbox.pack_start(combo, padding=2)
topwin.add(vbox)
topwin.show_all()
gtk.main()
say("%s Exiting\n" % sys.argv[0])
sys.exit(0)
Huge hack ahead (I just added this to your program):
import gtk
import sys
say = sys.stdout.write
def cb_changed(w):
say("Active index=%d\n" % w.get_active())
topwin = gtk.Window()
topwin.set_title("No Default")
topwin.set_size_request(0x100, 0x20)
topwin.connect('delete-event', gtk.main_quit)
vbox = gtk.VBox()
ls = gtk.ListStore(str, str)
combo = gtk.ComboBox(ls)
cell = gtk.CellRendererText()
combo.pack_start(cell)
combo.add_attribute(cell, 'text', 0)
combo.connect('changed', cb_changed)
#- Begin of the hack ----------------------------------
def special_empty_text (cell_view, event):
if cell_view.window is None:
return False
row = cell_view.get_displayed_row ()
if row is not None:
return False
layout = cell_view.create_pango_layout ('bla bla bla')
context = cell_view.window.cairo_create ()
xpad = 0
ypad = 0
renderer = cell_view.get_cells () [0]
if renderer is not None:
xpad = renderer.props.xpad
ypad = renderer.props.ypad
context.move_to (cell_view.allocation.x + xpad, cell_view.allocation.y + ypad)
context.set_source_rgb (0.6, 0.6, 0.6)
context.show_layout (layout)
return True
combo.child.connect ('expose-event', special_empty_text)
#- End of the hack ----------------------------------
ls.clear()
map(lambda i: ls.append(["Item-%d" % i, "Id%d" % i]), range(3))
vbox.pack_start(combo, padding=2)
topwin.add(vbox)
topwin.show_all()
gtk.main()
say("%s Exiting\n" % sys.argv[0])
sys.exit(0)
Don't see a nicer way.
Related
I have written up a simple UI that requires user to select something from a drop-down list, then using that selection, the code will executes the rest of the stuff
Right now, I am having 2 issues..
1. The 'value' is not exactly returning, as soon as a Format is selected and the OK button is hit... Am I missing something?
2. How can I make my UI closes upon a OK button has been selected?
import maya.cmds as cmds
def mainCode():
...
...
print "UI popping up"
showUI()
print "A format has been selected"
cmds.optionMenu('filmbackMenu', edit = True, value = xxx ) # <-- I want to grab the value from the menu selection and input into this 'value' flag
...
...
def showUI():
if cmds.window("UI_MainWindow", exists = True):
cmds.deleteUI("UI_MainWindow")
cmds.window("UI_MainWindow", title = "User Interface Test", w = 500, h = 700, mnb = False, mxb = False, sizeable = False)
cmds.columnLayout("UI_MainLayout", w = 300, h =500)
cmds.optionMenu("UI_FormatMenu", w = 250, label = "Select a Format")
list01 = ['itemA-01', 'itemB-02', 'itemC-02', 'itemD-01', 'itemE-01', 'itemF-03']
for x in list01:
cmds.menuItem(label = str(x))
cmds.button("UI_SelectButton", label = "OK", w = 200, command=ObjectSelection)
cmds.showWindow("UI_MainWindow") #shows window
def ObjectSelection(*args):
currentFormat = cmds.optionMenu("UI_FormatMenu", query=True, value=True)
print currentFormat
return currentFormat
Use python dictionnaries or class to pass data in your script.
I really don't understand what the problem is.
When you say : "The 'value' is not exactly returning", what do you mean ? Can you tell us what do you get and what do you expect ?
def mainCode():
...
...
showUI()
cmds.optionMenu('filmbackMenu', edit = True, value = xxx ) # <-- I want to grab the value from the menu selection and input into this 'value' flag
...
Here the value selection from the "input value", I guess it is :
cmds.optionMenu('filmbackMenu', edit = True, value = ObjectSelection())
But as there is not filmbackMenu in your code, I'm not sure.
Your second question has been answered on google groups by Justin. You just have to do :
def ObjectSelection(*args):
currentFormat = cmds.optionMenu("UI_FormatMenu", query=True, value=True)
cmds.deleteUI("UI_MainWindow")#close the UI
print currentFormat
return currentFormat
Or maybe "upon a OK button has been selected?" doesn't mean "OK button pressed" ?
If you want to see how use dictionnaries, you can read this other post where I have answered : Maya Python - Using data from UI
You are in a good path to using partial, I recommend you to read about it : Calling back user input values inside maya UI
--- EDIT ---
I tried to create a fully functionnal example :
import maya.cmds as cmds
uiDic = {}
uiDic['this']= 1
def ui_refresh(*args):
uiDic['this'] = cmds.optionMenu("UI_FormatMenu", query=True, value=True)
return uiDic['this']
def showUI():
if cmds.window("UI_MainWindow", exists = True):
cmds.deleteUI("UI_MainWindow")
cmds.window("UI_MainWindow", title = "User Interface Test", w = 500, h = 700, mnb = False, mxb = False, sizeable = False)
cmds.columnLayout("UI_MainLayout", w = 300, h =500)
cmds.optionMenu("UI_FormatMenu", w = 250, label = "Select a Format")
list01 = ['itemA-01', 'itemB-02', 'itemC-02', 'itemD-01', 'itemE-01', 'itemF-03']
for x in list01:
cmds.menuItem(label = str(x))
cmds.button("UI_SelectButton", label = "OK", w = 200, command=ObjectSelection)
uiDic['om_filmback'] = cmds.optionMenu('filmbackMenu' )
list01 = ['itemA-01', 'itemB-02', 'itemC-02', 'itemD-01', 'itemE-01', 'itemF-03']
for x in list01:
cmds.menuItem(label = str(x))
cmds.showWindow("UI_MainWindow") #shows window
def ObjectSelection(*args):
cmds.optionMenu(uiDic['om_filmback'], edit = True, value=ui_refresh())
showUI()
I'm a bit stuck on how to write the correct syntax for editing a command.
way down in my radioOn and radioOff commands, I would like the enable / disable checkbox to enable or disable the radio buttons.
from functools import partial
import maya.cmds as cmds
def one ():
print '1'
def two ():
print '2'
winID = 'xx'
if cmds.window(winID, exists=True):
cmds.deleteUI(winID)
window = cmds.window(winID, sizeable = False, title="Resolution Switcher", widthHeight=(300, 100) )
cmds.columnLayout( )
cmds.text (label = '')
cmds.text (label = '')
cmds.checkBoxGrp( cat = (1,'left', 20), ncb = 1, l1=' DISABLE', offCommand = partial(radioOn, a), onCommand = partial(radioOff, a) )
a = cmds.radioButtonGrp( cat = [(1,'left', 90),(2, 'left', 100)], numberOfRadioButtons=2, on1 = 'one ()' , on2 = 'two ()' )
cmds.text (label = '')
def radioOff (a, *args):
print 'radios off'
a(ed=True, enable=False)
def radioOn (a, *args):
print 'radios on'
a(ed=True, enable=False)
cmds.showWindow( window )
I've tried to get an idea from examples such as the one shown here, but
but when I put down cmds.radioButtonGrp(a, ed=True, enable=False) it just keeps creating new radio buttons, not unlike what was shown in the example with float fields.
bottom line is - I just want the radio buttons to be greyed out and disabled whenever I hit the checkbox. Speaking of which - Is it possible to grey out the radio buttons the same way float fields can? I noticed that disabling them only makes them unclickable - but not greyed out.
Thank you in advance.
from functools import partial
import maya.cmds as cmds
def one (*args):
print '1'
def two (*args):
print '2'
def radioSwitch (a, state, *args):
if state:
cmds.radioButtonGrp(a, e=True, enable=False)
else:
cmds.radioButtonGrp(a, e=True, enable=True)
winID = 'xx'
if cmds.window(winID, exists=True):
cmds.deleteUI(winID)
window = cmds.window(winID, sizeable = False, title="Resolution Switcher", widthHeight=(300, 100) )
cmds.columnLayout( )
cmds.text (label = '')
cmds.text (label = '')
cb_disable = cmds.checkBoxGrp( cat = (1,'left', 20), ncb = 1, l1=' DISABLE', offCommand = "" , onCommand = "" )
a = cmds.radioButtonGrp( cat = [(1,'left', 90),(2, 'left', 100)], enable=True, numberOfRadioButtons=2, on1 = one , on2 = two )
cmds.checkBoxGrp(cb_disable, e=1, offCommand = partial(radioSwitch, a, False))
cmds.checkBoxGrp(cb_disable, e=1, onCommand = partial(radioSwitch, a, True))
cmds.text (label = '')
cmds.showWindow( window )
I'm trying to open a QtGui.QDialog, request a set of values from the user, then return the values after "save" is clicked.
The following code should run without modification.
import sys
from PySide import QtCore, QtGui
import numpy as np
class MyQDialog(QtGui.QDialog):
def __init__(self, parent=None):
super(MyQDialog, self).__init__(parent)
## Default values
self.eta1 = 1.0
self.eta2 = 1.0
## Create labels and buttons
frameStyle = QtGui.QFrame.Sunken | QtGui.QFrame.Panel
self.eta1__QL = QtGui.QLabel(str(self.eta1))
self.eta1__QL.setFrameStyle(frameStyle)
self.eta1__QBtn = QtGui.QPushButton("Set eta1:")
self.eta2__QL = QtGui.QLabel(str(self.eta2))
self.eta2__QL.setFrameStyle(frameStyle)
self.eta2__QBtn = QtGui.QPushButton("Set eta2:")
self.cancel__QBtn = QtGui.QPushButton("Cancel")
self.save__QBtn = QtGui.QPushButton("Save")
self.eta1__QBtn.clicked.connect(self.set_eta1)
self.eta2__QBtn.clicked.connect(self.set_eta2)
self.cancel__QBtn.clicked.connect(self.cancel)
self.save__QBtn.clicked.connect(self.save)
## Set layout, add buttons
layout = QtGui.QGridLayout()
layout.setColumnStretch(1, 1)
layout.setColumnMinimumWidth(1, 250)
layout.addWidget(self.eta1__QBtn, 1, 0)
layout.addWidget(self.eta1__QL, 1, 1)
layout.addWidget(self.eta2__QBtn, 2, 0)
layout.addWidget(self.eta2__QL, 2, 1)
layout.addWidget(self.cancel__QBtn, 3, 0)
layout.addWidget(self.save__QBtn, 3, 1)
self.setLayout(layout)
self.setWindowTitle("Thank you for reading!")
## Button functions
def set_eta1(self):
self.eta1, ok = QtGui.QInputDialog.getDouble(self,
"Change of variable", "Rate (type 1):", 0.1, 0, 1e8, 3)
if ok:
self.eta1__QL.setText(str(self.eta1))
def set_eta2(self):
self.eta2, ok = QtGui.QInputDialog.getDouble(self,
"Change of variable", "Rate (type 2):", 0.3, 0, 1e8, 3)
if ok:
self.eta2__QL.setText(str(self.eta2))
def cancel(self):
self.close()
def save(self):
return self.eta2, self.eta2
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
edit_params__QD = MyQDialog()
if edit_params__QD.exec_():
value1, value2 = edit_params__QD.save()
print 'Success!', value1, value2
else:
print 'I shouldn\'t print, but I do.'
sys.exit()
Thank you very much for your time! Any suggestions for improvement are greatly appreciated!
Change the return values in this line:
def save(self):
return self.eta2, self.eta2
to: return self.eta1, self.eta2
In main (of course your need to import sys):
app = QtGui.QApplication(sys.argv)
edit_params__QD = MyQDialog()
edit_params__QD.exec_()
if edit_params__QD.result() == 0:
value1, value2 = edit_params__QD.save()
print('Success!', value1, value2)
Add the second connection to what you already have:
self.save__QBtn.clicked.connect(self.save)
self.save__QBtn.clicked.connect(self.close)
I hope this helps.
Ok, let's get straight to the point. I got 2 questions
1. Why self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "fore:#000000" + FontSet) not working?
2. Why the custom lexer is not applied?
This is the source code
import wx, re, keyword
from wx import stc
class BaseLexer(object):
"""Defines simple interface for custom lexer objects"""
def __init__(self):
super(BaseLexer, self).__init__()
def StyleText(self, event):
raise NotImplementedError
class STC_LEX_VOTONUSA(BaseLexer):
# Define some style IDs
STC_VOTONUSA_DEFAULT = wx.NewId()
STC_VOTONUSA_VALUE = wx.NewId()
STC_VOTONUSA_OBJECT = wx.NewId()
STC_VOTONUSA_TYPE = wx.NewId()
STC_VOTONUSA_OPERATION = wx.NewId()
STC_VOTONUSA_COMMENT =wx.NewId()
STC_VOTONUSA_QUALIFIER = wx.NewId()
def __init__(self):
super(STC_LEX_VOTONUSA, self).__init__()
# Attributes
self.Comment = re.compile("""
//
""", re.X)
self.Types = re.compile("""
\\b
(void|integer|shortint|(short)?word|float|boolean|char|record|program|module)
\\b
""", re.I|re.X)
self.Operation = re.compile("""
(read|write)(line)?|if|main|case|while|use|return|exit|in_case|repeat_until
(\+|-|\*|/|%|\*\*|:|!|<|>)?=?|
(\{|\}|\(|\)|\[|\])
""", re.I|re.X)
self.Value = re.compile("""
[(`\d*)+\'\w*\']*|\'.*\'|[\+-]*\d*\.?\d*
""", re.I|re.X)
self.Qualifier = re.compile("""
interface|implementation
""", re.I|re.X)
self.Object = re.compile("""
s
""", re.I|re.X)
def GetLastWord(self, Line, CaretPos):
"""
Get the last word from a line
"""
LastWord = re.search(
"""
\s*
(
".*"| # String data type
\w*| # Any letter/number
(\+|-|\*|/|%|\*\*|:|!|<|>)?=?| # Assignment, Comparison & Mathematical
(\{|\}|\(|\)|\[|\]) # Brackets
)
\s*\Z
""",
Line[:CaretPos], re.VERBOSE)
return LastWord
def StyleText(self, event):
"""Handle the EVT_STC_STYLENEEDED event"""
Obj = event.GetEventObject()
# Get Last Correctly Styled
LastStyledPos = Obj.GetEndStyled()
# Get Styling Range
Line = Obj.LineFromPosition(LastStyledPos)
StartPos = Obj.PositionFromLine(Line)
EndPos = event.GetPosition()
# Walk the Range and Style Them
while StartPos < EndPos:
Obj.StartStyling(StartPos, 0x1f)
LastWord = self.GetLastWord(Line, CaretPos)
if self.Comment.search(LastWord):
# Set Comment Keyword style
Style = self.STC_VOTONUSA_COMMENT
elif self.Type.search(LastWord):
# Set Type Keyword style
Style = self.STC_VOTONUSA_TYPE
elif self.Operation.search(LastWord):
# Set Operation Keyword style
Style = self.STC_VOTONUSA_OPERATION
elif self.Value.search(LastWord):
# Set Value Keyword style
Style = self.STC_VOTONUSA_VALUE
elif self.Qualifier.search(LastWord):
# Set Qualifier Keyqord style
Style = self.STC_VOTONUSA_QUALIFIER
elif self.Object.search(LastWord):
# Set Object Keyword style
Style = self.STC_VOTONUSA_OBJECT
# Set the styling byte information for length of LastWord from
# current styling position (StartPos) with the given style.
Obj.SetStyling(len(LastWord), Style)
StartPos += len(LastWord)
class CustomSTC(stc.StyledTextCtrl):
def __init__(self, parent):
super(CustomSTC, self).__init__(parent)
# Attributes
self.custlex = None
Font = wx.Font(12, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
Face = Font.GetFaceName()
Size = Font.GetPointSize()
# Setup
kwlist = u" ".join(keyword.kwlist)
self.SetKeyWords(0, kwlist)
self.StyleClearAll()
self.SetLexer(wx.NewId(), STC_LEX_VOTONUSA)
self.EnableLineNumbers()
FontSet = "face:%s, size:%d" % (Face, Size)
self.StyleSetSpec(stc.STC_STYLE_LINENUMBER, FontSet)
# Set Default to Black
self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "fore:#000000" + FontSet)
# Set Comment to Pink
self.StyleSetSpec(STC_LEX_VOTONUSA.STC_VOTONUSA_COMMENT, "fore:#ff007f" + FontSet)
# Set Value to Green
self.StyleSetSpec(STC_LEX_VOTONUSA.STC_VOTONUSA_VALUE, "fore:#00ff00" + FontSet)
# Set Object to Brown
self.StyleSetSpec(STC_LEX_VOTONUSA.STC_VOTONUSA_OBJECT, "fore:#a52a2a" + FontSet)
# Set Type to Red
self.StyleSetSpec(STC_LEX_VOTONUSA.STC_VOTONUSA_TYPE, "fore:#ff0000" + FontSet)
# Set Operation to Blue
self.StyleSetSpec(STC_LEX_VOTONUSA.STC_VOTONUSA_OPERATION, "fore:#0000ff" + FontSet)
# Set Qualifier to Orange
self.StyleSetSpec(STC_LEX_VOTONUSA.STC_VOTONUSA_QUALIFIER, "fore:#cc3232" + FontSet)
# Event Handlers
self.Bind(stc.EVT_STC_STYLENEEDED, self.OnStyle)
def EnableLineNumbers(self, enable=True):
"""Enable/Disable line number margin"""
if enable:
self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
self.SetMarginMask(1, 0)
self.SetMarginWidth(1, 25)
else:
self.SetMarginWidth(1, 0)
def OnStyle(self, event):
# Delegate to custom lexer object if one exists
if self.custlex:
self.custlex.StyleText(event)
else:
event.Skip()
def SetLexer(self, lexerid, lexer=None):
"""
Overrides StyledTextCtrl.SetLexer
Adds optional param to pass in custom container
lexer object.
"""
self.custlex = lexer
super(CustomSTC, self).SetLexer(lexerid)
class NUSAIPT(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, None, wx.ID_ANY, 'VOTO NUSA IPT')
self.TextArea = CustomSTC(self)
self.Show()
app = wx.App()
frame = NUSAIPT()
app.MainLoop()
If I change
self.SetLexer(wx.NewId(), STC_LEX_VOTONUSA)
into
self.SetLexer(stc.STC_LEX_CPP)
and
self.StyleSetSpec(STC_LEX_VOTONUSA.STC_VOTONUSA_COMMENT, "fore:#ff007f" + FontSet)
into
self.StyleSetSpec(stc.STC_C_COMMENT, "fore:#ff007f" + FontSet)
the comment highlighting worked. so the mistake should be in self.SetLexer(wx.NewId(), STC_LEX_VOTONUSA) or STC_LEX_VOTONUSA.STC_VOTONUSA_COMMENT
Thanks in advance. Hope to see some answer soon.
Just stuck with same problem yesterday, here are my results. Hope it's not too late :)
First, i set lexer to this one, and internal lexer as you do:
self.SetLexer(stc.STC_LEX_CONTAINER)
self.custlex = SCT_LEX_ERLANG_IDNOISE(self)
Bind to event and OnStyle method are same.
And also i changed id of styles from wx.newId() to just numbers starting from 1.
Without it i didn't see any styling at all. Also stc.STC_STYLE_DEFAULT started to work too.
Full listing:
class SCT_LEX_ERLANG_IDNOISE(BaseLexer):
STC_ERLANG_IDNOISE_DEFAULT = 1
STC_ERLANG_IDNOISE_VARIABLE = 2
STC_ERLANG_IDNOISE_ATOM = 3
STC_ERLANG_IDNOISE_MODULE = 4
STC_ERLANG_IDNOISE_KEYWORD = 5
STC_ERLANG_IDNOISE_COMMENT = 6
STC_ERLANG_IDNOISE_MACROS = 7
STC_ERLANG_IDNOISE_NUMBER = 8
def __init__(self, control):
super(SCT_LEX_ERLANG_IDNOISE, self).__init__(control)
self.typeFormatDict = {}
self.typeFormatDict["other"] = SCT_LEX_ERLANG_IDNOISE.STC_ERLANG_IDNOISE_DEFAULT
self.typeFormatDict["variable"] = SCT_LEX_ERLANG_IDNOISE.STC_ERLANG_IDNOISE_VARIABLE
self.typeFormatDict["atom"] = SCT_LEX_ERLANG_IDNOISE.STC_ERLANG_IDNOISE_ATOM
self.typeFormatDict["module"] = SCT_LEX_ERLANG_IDNOISE.STC_ERLANG_IDNOISE_MODULE
self.typeFormatDict["keyword"] = SCT_LEX_ERLANG_IDNOISE.STC_ERLANG_IDNOISE_KEYWORD
self.typeFormatDict["comment"] = SCT_LEX_ERLANG_IDNOISE.STC_ERLANG_IDNOISE_COMMENT
self.typeFormatDict["macros"] = SCT_LEX_ERLANG_IDNOISE.STC_ERLANG_IDNOISE_MACROS
self.typeFormatDict["number"] = SCT_LEX_ERLANG_IDNOISE.STC_ERLANG_IDNOISE_NUMBER
def StyleText(self, event):
start = self.control.GetEndStyled()
end = event.GetPosition()
line = self.control.LineFromPosition(start)
start = self.control.PositionFromLine(line)
text = self.control.GetTextRange(start, end)
self.control.StartStyling(start, 0x1f)
lastEnd = 0
for type, start, end, value in getHighlightRules(text):
style = SCT_LEX_ERLANG_IDNOISE.STC_ERLANG_IDNOISE_DEFAULT
if start > lastEnd:
self.control.SetStyling(start - lastEnd, style)
if type in self.typeFormatDict:
style = self.typeFormatDict[type]
self.control.SetStyling(len(value), style)
lastEnd = end
class CustomSTC(stc.StyledTextCtrl):
def __init__(self, parent):
super(CustomSTC, self).__init__(parent)
self.custlex = SCT_LEX_ERLANG_IDNOISE(self)
#self.SetKeyWords(0, kwlist)
self.SetLexer(stc.STC_LEX_CONTAINER)
self.EnableLineNumbers()
self.StyleSetSpec(stc.STC_STYLE_DEFAULT, ColorSchema.formats["other"])
self.StyleClearAll()
self.StyleSetSpec(stc.STC_STYLE_LINENUMBER, ColorSchema.lineFont)
self.StyleSetSpec(SCT_LEX_ERLANG_IDNOISE.STC_ERLANG_IDNOISE_DEFAULT, ColorSchema.formats["other"])
self.StyleSetSpec(SCT_LEX_ERLANG_IDNOISE.STC_ERLANG_IDNOISE_VARIABLE, ColorSchema.formats["variable"])
self.StyleSetSpec(SCT_LEX_ERLANG_IDNOISE.STC_ERLANG_IDNOISE_ATOM, ColorSchema.formats["atom"])
self.StyleSetSpec(SCT_LEX_ERLANG_IDNOISE.STC_ERLANG_IDNOISE_MODULE, ColorSchema.formats["module"])
self.StyleSetSpec(SCT_LEX_ERLANG_IDNOISE.STC_ERLANG_IDNOISE_KEYWORD, ColorSchema.formats["keyword"])
self.StyleSetSpec(SCT_LEX_ERLANG_IDNOISE.STC_ERLANG_IDNOISE_COMMENT, ColorSchema.formats["comment"])
self.StyleSetSpec(SCT_LEX_ERLANG_IDNOISE.STC_ERLANG_IDNOISE_MACROS, ColorSchema.formats["macros"])
self.StyleSetSpec(SCT_LEX_ERLANG_IDNOISE.STC_ERLANG_IDNOISE_NUMBER, ColorSchema.formats["number"])
# Event Handlers
self.Bind(stc.EVT_STC_STYLENEEDED, self.OnStyle)
def EnableLineNumbers(self, enable=True):
"""Enable/Disable line number margin"""
if enable:
self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
self.SetMarginMask(1, 0)
self.SetMarginWidth(1, 35)
else:
self.SetMarginWidth(1, 0)
def OnStyle(self, event):
if self.custlex:
self.custlex.StyleText(event)
else:
event.Skip()
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_string function 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 a wrap_width != 1