在wx.TextCtrl中自动检测文件或文件夹路径

时间:2012-04-29 09:37:43

标签: python wxwidgets textctrl

是否有一种机制可以检测(突出显示并生成鼠标事件)wx.TextCtrl中的文件或文件夹路径?

URL检测存在类似的机制(使用style = wx.TE_AUTO_URL和wx.TE_RICH)。

示例:

“这是一个示例,我希望TextCtrl将 C:\ Temp \ Folder \ temp.txt 检测为路径。”

谢谢,Omer。

1 个答案:

答案 0 :(得分:0)

据我所知,没有内置的风格可以做你想要的。但是,您始终可以继承wx.TextCtrl。

下面提供的自定义窗口小部件会更改与正则表达式匹配的字符串子部分的样式。当光标悬停在其中一个子串上时,将生成自定义命令事件“EVT_TXT_PATH”。

正则表达式可能需要根据您希望控件识别的路径进行调整。 我从正则表达式库中抓取了一个可能适合您的方法:

http://regexlib.com/REDetails.aspx?regexp_id=127

import wx
import wx.lib.newevent

import re

re_path = re.compile(r'([A-Z]:\\[^/:\*\?<>\|]+\.\w{2,6})|(\\{2}[^/:\*\?<>\|]+\.\w{2,6})')

TextPathEvent, EVT_TXT_PATH = wx.lib.newevent.NewCommandEvent()

class PathTextCtrl(wx.TextCtrl):

    def __init__(self, parent, id=wx.ID_ANY, value="",
                 pos=wx.DefaultPosition, size=wx.DefaultSize,
                 style=0, validator=wx.DefaultValidator,
                 name=""):

        style = style | wx.TE_RICH

        super(PathTextCtrl, self).__init__(parent, id, value, pos, size,
                                           style,validator, name)

        self.groups = []

        self.SetDefaultStyle(wx.TextAttr(wx.BLACK, wx.NullColor))

        self.Bind(wx.EVT_TEXT, self.OnText, self)
        self.Bind(wx.EVT_MOTION, self.OnMotion, self)

    def OnText(self, evt):

        self.StyleText()

        evt.Skip()

    def StyleText(self):

        self.groups = []

        string = self.GetValue()
        n = len(string)

        defstyle = self.GetDefaultStyle()
        self.SetStyle(0, n, defstyle)

        font = self.GetFont()
        font.SetUnderlined(True)
        style = wx.TextAttr(colText=wx.BLUE, font=font)       

        index = 0

        while True:

            match = re_path.search(string, index, n)

            if match:

                start, end = match.span()

                self.groups.append((start, end))

                self.SetStyle(start, end, style)

                index = end+1

            else: return

    def OnMotion(self, evt):

        pos = evt.GetPosition()

        result = self.HitTestPos(pos)

        for group in self.groups:

            x, y = group

            if x <= result[1] <= y:

                string = self.GetValue()[x:y]

                print string

                event = TextPathEvent(id=self.GetId(), url=string)

                wx.PostEvent(self, event)

        evt.Skip()

class TestFrame(wx.Frame):

    def __init__(self, parent, id=wx.ID_ANY, title=""):

        super(TestFrame, self).__init__(parent, id, title)

        panel = wx.Panel(self)

        text = PathTextCtrl(panel, size=(400, -1))

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(text, 0, wx.ALL, 10)
        panel.SetSizer(sizer)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(panel)
        self.SetSizer(sizer)

        self.Fit()

if __name__ == '__main__':

    app = wx.App(redirect=True)
    top = TestFrame(None, title="PathTextCtrl Demonstration")
    top.Show()
    app.MainLoop()