[Python] wxpython 支持python语法高亮的自定义文本框控件 →→→→→进入此内容的聊天室

来自 , 2019-12-11, 写在 Python, 查看 136 次.
URL http://www.code666.cn/view/8d235536
  1. import  keyword
  2. import  wx
  3. import  wx.stc  as  stc
  4. import  images
  5.  
  6.  
  7. #----------------------------------------------------------------------
  8.  
  9. demoText = """\
  10. ## This version of the editor has been set up to edit Python source
  11. ## code.  Here is a copy of wxPython/demo/Main.py to play with.
  12.  
  13.  
  14. """
  15.  
  16. #----------------------------------------------------------------------
  17.  
  18. if wx.Platform == '__WXMSW__':
  19.     faces = { 'times': 'Times New Roman',
  20.               'mono' : 'Courier New',
  21.               'helv' : 'Arial',
  22.               'other': 'Comic Sans MS',
  23.               'size' : 10,
  24.               'size2': 8,
  25.               }
  26. elif wx.Platform == '__WXMAC__':
  27.     faces = { 'times': 'Times New Roman',
  28.               'mono' : 'Monaco',
  29.               'helv' : 'Arial',
  30.               'other': 'Comic Sans MS',
  31.               'size' : 12,
  32.               'size2': 10,
  33.               }
  34. else:
  35.     faces = { 'times': 'Times',
  36.               'mono' : 'Courier',
  37.               'helv' : 'Helvetica',
  38.               'other': 'new century schoolbook',
  39.               'size' : 12,
  40.               'size2': 10,
  41.               }
  42.  
  43.  
  44. class PythonSTC(stc.StyledTextCtrl):
  45.  
  46.     fold_symbols = 2
  47.  
  48.     def __init__(self, parent, ID,
  49.                  pos=wx.DefaultPosition, size=wx.DefaultSize,
  50.                  style=0):
  51.         stc.StyledTextCtrl.__init__(self, parent, ID, pos, size, style)
  52.  
  53.         self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
  54.         self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
  55.  
  56.         self.SetLexer(stc.STC_LEX_PYTHON)
  57.         self.SetKeyWords(0, " ".join(keyword.kwlist))
  58.  
  59.         self.SetProperty("fold", "1")
  60.         self.SetProperty("tab.timmy.whinge.level", "1")
  61.         self.SetMargins(0,0)
  62.  
  63.         self.SetViewWhiteSpace(False)
  64.         #self.SetBufferedDraw(False)
  65.         #self.SetViewEOL(True)
  66.         #self.SetEOLMode(stc.STC_EOL_CRLF)
  67.         #self.SetUseAntiAliasing(True)
  68.  
  69.         self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
  70.         self.SetEdgeColumn(78)
  71.  
  72.         # Setup a margin to hold fold markers
  73.         #self.SetFoldFlags(16)  ###  WHAT IS THIS VALUE?  WHAT ARE THE OTHER FLAGS?  DOES IT MATTER?
  74.         self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
  75.         self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
  76.         self.SetMarginSensitive(2, True)
  77.         self.SetMarginWidth(2, 12)
  78.  
  79.         if self.fold_symbols == 0:
  80.             # Arrow pointing right for contracted folders, arrow pointing down for expanded
  81.             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_ARROWDOWN, "black", "black")
  82.             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_ARROW, "black", "black")
  83.             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "black", "black")
  84.             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "black", "black")
  85.             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY,     "white", "black")
  86.             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY,     "white", "black")
  87.             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY,     "white", "black")
  88.  
  89.         elif self.fold_symbols == 1:
  90.             # Plus for contracted folders, minus for expanded
  91.             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_MINUS, "white", "black")
  92.             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_PLUS,  "white", "black")
  93.             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "white", "black")
  94.             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "white", "black")
  95.             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY, "white", "black")
  96.             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
  97.             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
  98.  
  99.         elif self.fold_symbols == 2:
  100.             # Like a flattened tree control using circular headers and curved joins
  101.             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_CIRCLEMINUS,          "white", "#404040")
  102.             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_CIRCLEPLUS,           "white", "#404040")
  103.             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,                "white", "#404040")
  104.             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNERCURVE,         "white", "#404040")
  105.             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_CIRCLEPLUSCONNECTED,  "white", "#404040")
  106.             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040")
  107.             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE,         "white", "#404040")
  108.  
  109.         elif self.fold_symbols == 3:
  110.             # Like a flattened tree control using square headers
  111.             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_BOXMINUS,          "white", "#808080")
  112.             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_BOXPLUS,           "white", "#808080")
  113.             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,             "white", "#808080")
  114.             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNER,           "white", "#808080")
  115.             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_BOXPLUSCONNECTED,  "white", "#808080")
  116.             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
  117.             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER,           "white", "#808080")
  118.  
  119.  
  120.         self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
  121.         self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
  122.         self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
  123.  
  124.         # Make some styles,  The lexer defines what each style is used for, we
  125.         # just have to define what each style looks like.  This set is adapted from
  126.         # Scintilla sample property files.
  127.  
  128.         # Global default styles for all languages
  129.         self.StyleSetSpec(stc.STC_STYLE_DEFAULT,     "face:%(helv)s,size:%(size)d" % faces)
  130.         self.StyleClearAll()  # Reset all to be like the default
  131.  
  132.         # Global default styles for all languages
  133.         self.StyleSetSpec(stc.STC_STYLE_DEFAULT,     "face:%(helv)s,size:%(size)d" % faces)
  134.         self.StyleSetSpec(stc.STC_STYLE_LINENUMBER,  "back:#C0C0C0,face:%(helv)s,size:%(size2)d" % faces)
  135.         self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces)
  136.         self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,  "fore:#FFFFFF,back:#0000FF,bold")
  137.         self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,    "fore:#000000,back:#FF0000,bold")
  138.  
  139.         # Python styles
  140.         # Default
  141.         self.StyleSetSpec(stc.STC_P_DEFAULT, "fore:#000000,face:%(helv)s,size:%(size)d" % faces)
  142.         # Comments
  143.         self.StyleSetSpec(stc.STC_P_COMMENTLINE, "fore:#007F00,face:%(other)s,size:%(size)d" % faces)
  144.         # Number
  145.         self.StyleSetSpec(stc.STC_P_NUMBER, "fore:#007F7F,size:%(size)d" % faces)
  146.         # String
  147.         self.StyleSetSpec(stc.STC_P_STRING, "fore:#7F007F,face:%(helv)s,size:%(size)d" % faces)
  148.         # Single quoted string
  149.         self.StyleSetSpec(stc.STC_P_CHARACTER, "fore:#7F007F,face:%(helv)s,size:%(size)d" % faces)
  150.         # Keyword
  151.         self.StyleSetSpec(stc.STC_P_WORD, "fore:#00007F,bold,size:%(size)d" % faces)
  152.         # Triple quotes
  153.         self.StyleSetSpec(stc.STC_P_TRIPLE, "fore:#7F0000,size:%(size)d" % faces)
  154.         # Triple double quotes
  155.         self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, "fore:#7F0000,size:%(size)d" % faces)
  156.         # Class name definition
  157.         self.StyleSetSpec(stc.STC_P_CLASSNAME, "fore:#0000FF,bold,underline,size:%(size)d" % faces)
  158.         # Function or method name definition
  159.         self.StyleSetSpec(stc.STC_P_DEFNAME, "fore:#007F7F,bold,size:%(size)d" % faces)
  160.         # Operators
  161.         self.StyleSetSpec(stc.STC_P_OPERATOR, "bold,size:%(size)d" % faces)
  162.         # Identifiers
  163.         self.StyleSetSpec(stc.STC_P_IDENTIFIER, "fore:#000000,face:%(helv)s,size:%(size)d" % faces)
  164.         # Comment-blocks
  165.         self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, "fore:#7F7F7F,size:%(size)d" % faces)
  166.         # End of line where string is not closed
  167.         self.StyleSetSpec(stc.STC_P_STRINGEOL, "fore:#000000,face:%(mono)s,back:#E0C0E0,eol,size:%(size)d" % faces)
  168.  
  169.         self.SetCaretForeground("BLUE")
  170.  
  171.  
  172.         # register some images for use in the AutoComplete box.
  173.         self.RegisterImage(1, images.Smiles.GetBitmap())
  174.         self.RegisterImage(2,
  175.                            wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
  176.         self.RegisterImage(3,
  177.                            wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
  178.  
  179.  
  180.     def OnKeyPressed(self, event):
  181.         if self.CallTipActive():
  182.             self.CallTipCancel()
  183.         key = event.GetKeyCode()
  184.  
  185.         if key == 32 and event.ControlDown():
  186.             pos = self.GetCurrentPos()
  187.  
  188.             # Tips
  189.             if event.ShiftDown():
  190.                 self.CallTipSetBackground("yellow")
  191.                 self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n'
  192.                                       'show some suff, maybe parameters..\n\n'
  193.                                       'fubar(param1, param2)')
  194.             # Code completion
  195.             else:
  196.                 #lst = []
  197.                 #for x in range(50000):
  198.                 #    lst.append('%05d' % x)
  199.                 #st = " ".join(lst)
  200.                 #print len(st)
  201.                 #self.AutoCompShow(0, st)
  202.  
  203.                 kw = keyword.kwlist[:]
  204.                 kw.append("zzzzzz?2")
  205.                 kw.append("aaaaa?2")
  206.                 kw.append("__init__?3")
  207.                 kw.append("zzaaaaa?2")
  208.                 kw.append("zzbaaaa?2")
  209.                 kw.append("this_is_a_longer_value")
  210.                 #kw.append("this_is_a_much_much_much_much_much_much_much_longer_value")
  211.  
  212.                 kw.sort()  # Python sorts are case sensitive
  213.                 self.AutoCompSetIgnoreCase(False)  # so this needs to match
  214.  
  215.                 # Images are specified with a appended "?type"
  216.                 for i in range(len(kw)):
  217.                     if kw[i] in keyword.kwlist:
  218.                         kw[i] = kw[i] + "?1"
  219.  
  220.                 self.AutoCompShow(0, " ".join(kw))
  221.         else:
  222.             event.Skip()
  223.  
  224.  
  225.     def OnUpdateUI(self, evt):
  226.         # check for matching braces
  227.         braceAtCaret = -1
  228.         braceOpposite = -1
  229.         charBefore = None
  230.         caretPos = self.GetCurrentPos()
  231.  
  232.         if caretPos > 0:
  233.             charBefore = self.GetCharAt(caretPos - 1)
  234.             styleBefore = self.GetStyleAt(caretPos - 1)
  235.  
  236.         # check before
  237.         if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
  238.             braceAtCaret = caretPos - 1
  239.  
  240.         # check after
  241.         if braceAtCaret < 0:
  242.             charAfter = self.GetCharAt(caretPos)
  243.             styleAfter = self.GetStyleAt(caretPos)
  244.  
  245.             if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
  246.                 braceAtCaret = caretPos
  247.  
  248.         if braceAtCaret >= 0:
  249.             braceOpposite = self.BraceMatch(braceAtCaret)
  250.  
  251.         if braceAtCaret != -1  and braceOpposite == -1:
  252.             self.BraceBadLight(braceAtCaret)
  253.         else:
  254.             self.BraceHighlight(braceAtCaret, braceOpposite)
  255.             #pt = self.PointFromPosition(braceOpposite)
  256.             #self.Refresh(True, wxRect(pt.x, pt.y, 5,5))
  257.             #print pt
  258.             #self.Refresh(False)
  259.  
  260.  
  261.     def OnMarginClick(self, evt):
  262.         # fold and unfold as needed
  263.         if evt.GetMargin() == 2:
  264.             if evt.GetShift() and evt.GetControl():
  265.                 self.FoldAll()
  266.             else:
  267.                 lineClicked = self.LineFromPosition(evt.GetPosition())
  268.  
  269.                 if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
  270.                     if evt.GetShift():
  271.                         self.SetFoldExpanded(lineClicked, True)
  272.                         self.Expand(lineClicked, True, True, 1)
  273.                     elif evt.GetControl():
  274.                         if self.GetFoldExpanded(lineClicked):
  275.                             self.SetFoldExpanded(lineClicked, False)
  276.                             self.Expand(lineClicked, False, True, 0)
  277.                         else:
  278.                             self.SetFoldExpanded(lineClicked, True)
  279.                             self.Expand(lineClicked, True, True, 100)
  280.                     else:
  281.                         self.ToggleFold(lineClicked)
  282.  
  283.  
  284.     def FoldAll(self):
  285.         lineCount = self.GetLineCount()
  286.         expanding = True
  287.  
  288.         # find out if we are folding or unfolding
  289.         for lineNum in range(lineCount):
  290.             if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
  291.                 expanding = not self.GetFoldExpanded(lineNum)
  292.                 break
  293.  
  294.         lineNum = 0
  295.  
  296.         while lineNum < lineCount:
  297.             level = self.GetFoldLevel(lineNum)
  298.             if level & stc.STC_FOLDLEVELHEADERFLAG and\
  299.                (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
  300.  
  301.                 if expanding:
  302.                     self.SetFoldExpanded(lineNum, True)
  303.                     lineNum = self.Expand(lineNum, True)
  304.                     lineNum = lineNum - 1
  305.                 else:
  306.                     lastChild = self.GetLastChild(lineNum, -1)
  307.                     self.SetFoldExpanded(lineNum, False)
  308.  
  309.                     if lastChild > lineNum:
  310.                         self.HideLines(lineNum+1, lastChild)
  311.  
  312.             lineNum = lineNum + 1
  313.  
  314.  
  315.  
  316.     def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
  317.         lastChild = self.GetLastChild(line, level)
  318.         line = line + 1
  319.  
  320.         while line <= lastChild:
  321.             if force:
  322.                 if visLevels > 0:
  323.                     self.ShowLines(line, line)
  324.                 else:
  325.                     self.HideLines(line, line)
  326.             else:
  327.                 if doExpand:
  328.                     self.ShowLines(line, line)
  329.  
  330.             if level == -1:
  331.                 level = self.GetFoldLevel(line)
  332.  
  333.             if level & stc.STC_FOLDLEVELHEADERFLAG:
  334.                 if force:
  335.                     if visLevels > 1:
  336.                         self.SetFoldExpanded(line, True)
  337.                     else:
  338.                         self.SetFoldExpanded(line, False)
  339.  
  340.                     line = self.Expand(line, doExpand, force, visLevels-1)
  341.  
  342.                 else:
  343.                     if doExpand and self.GetFoldExpanded(line):
  344.                         line = self.Expand(line, True, force, visLevels-1)
  345.                     else:
  346.                         line = self.Expand(line, False, force, visLevels-1)
  347.             else:
  348.                 line = line + 1
  349.  
  350.         return line
  351.  
  352.  
  353. #----------------------------------------------------------------------
  354.  
  355. _USE_PANEL = 1
  356.  
  357. def runTest(frame, nb, log):
  358.     if not _USE_PANEL:
  359.         ed = p = PythonSTC(nb, -1)
  360.     else:
  361.         p = wx.Panel(nb, -1, style = wx.NO_FULL_REPAINT_ON_RESIZE)
  362.         ed = PythonSTC(p, -1)
  363.         s = wx.BoxSizer(wx.HORIZONTAL)
  364.         s.Add(ed, 1, wx.EXPAND)
  365.         p.SetSizer(s)
  366.         p.SetAutoLayout(True)
  367.  
  368.  
  369.     ed.SetText(demoText + open('main.py').read())
  370.     ed.EmptyUndoBuffer()
  371.     ed.Colourise(0, -1)
  372.  
  373.     # line numbers in the margin
  374.     ed.SetMarginType(1, stc.STC_MARGIN_NUMBER)
  375.     ed.SetMarginWidth(1, 25)
  376.  
  377.     return p
  378.  
  379.  
  380.  
  381. #----------------------------------------------------------------------
  382.  
  383.  
  384. overview = """\
  385. <html><body>
  386. Once again, no docs yet.  <b>Sorry.</b>  But <a href="data/stc.h.html">this</a>
  387. and <a href="http://www.scintilla.org/ScintillaDoc.html">this</a> should
  388. be helpful.
  389. </body><html>
  390. """
  391.  
  392.  
  393. if __name__ == '__main__':
  394.     import sys,os
  395.     import run
  396.     run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])
  397.  
  398. #//python/2329

回复 "wxpython 支持python语法高亮的自定义文本框控件"

这儿你可以回复上面这条便签

captcha