Skip to main content
 首页 » 编程设计

python之wxPython StyleSetSpec 和 SetLexer 不工作

2024年08月30日2498°冷暖

好了,进入正题。我有 2 个问题
1. 为什么 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "fore:#000000"+ FontSet) 不起作用?
2. 为什么没有应用自定义词法分析器?

这是源码

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() 

如果我改变

self.SetLexer(wx.NewId(), STC_LEX_VOTONUSA) 

进入

self.SetLexer(stc.STC_LEX_CPP) 

和

self.StyleSetSpec(STC_LEX_VOTONUSA.STC_VOTONUSA_COMMENT, "fore:#ff007f" + FontSet) 

进入

self.StyleSetSpec(stc.STC_C_COMMENT, "fore:#ff007f" + FontSet) 

评论突出显示有效。所以错误应该在 self.SetLexer(wx.NewId(), STC_LEX_VOTONUSA) 或者 STC_LEX_VOTONUSA.STC_VOTONUSA_COMMENT

提前致谢。希望尽快看到一些答案。

请您参考如下方法:

昨天刚遇到同样的问题,这是我的结果。希望还不算太晚:)

首先,我将词法分析器设置为这个,并像您一样设置内部词法分析器:

self.SetLexer(stc.STC_LEX_CONTAINER) 
self.custlex = SCT_LEX_ERLANG_IDNOISE(self) 

绑定(bind)到事件和 OnStyle 方法相同。

而且我也将样式的 id 从 wx.newId() 更改为仅从 1 开始的数字。 没有它,我根本看不到任何样式。 stc.STC_STYLE_DEFAULT 也开始工作了。

完整列表:

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()