开发者

wxpython run when textctrl changes

开发者 https://www.devze.com 2023-03-28 18:35 出处:网络
I am making a simple text editor in wxpython. I would like it to be able to edit code such as python, and as such I would like to have it highlight the text in a similar manner to IDLE or Notepad++. I

I am making a simple text editor in wxpython. I would like it to be able to edit code such as python, and as such I would like to have it highlight the text in a similar manner to IDLE or Notepad++. I know how I would highlight it, but I would like the best way of running it. I don't know if it is possible but what I would really like is to run whenever a key is pressed, and not on a loop checking if it is pressed, so as to save on processing.

import wx
class MainWindow(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(500,600))
        style = wx.TE_MULTILINE|wx.BORDER_SUNKEN|wx.TE_RICH2
        self.status_area = wx.TextCtrl(self, -1,
                                   pos=(10, 270),style=style,
                                   size=(380,150))
        self.status_area.AppendText("Type in your wonderfull code here.")
        fg = wx.Colour(200,80,100)
        at = wx.TextAttr(fg)
        self.status_area.SetStyle(3, 5, at)
        self.CreateStatusBar() # A Statusbar in the bottom of the window

        # Setting up the menu.
        filemenu= wx.Menu()

        filemenu.Append(wx.ID_ABOUT, "&About","Use to edit python code")
        filemenu.AppendSeparator()
        filemenu.Append(wx.ID_EXIT,"&Exit"," Terminate the program")

        # Creating the menubar.
        menuBar = wx.MenuBar()
        menuBar.Append(filemenu,"&File") # Adding the "filemenu" to the MenuBar
        self.SetMenuBar(menuBar)  # Adding the MenuBar to the Frame content.
        self.Show(True)


app = wx.App(False)
frame = MainWindow(None, "Python Coder")
app.MainLoop()

If a loop is needed what would be the best way to make it loop, with a while loop, or a

def Loop():
    <code>
    Loop()

My new code with the added bind:

import wx

class MainWindow(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(500,600))
        style = wx.TE_MULTILINE|wx.BORDER_SUNKEN|wx.TE_RICH2
        self.status_area = wx.TextCtrl(self, -1,
                                   pos=(10, 270),style=style,
                                   size=(380,150))
        #settup the syntax highlighting to run on a key press
        self.Bind(wx.EVT_CHAR, self.onKeyPress, self.status_area)
        self.status_area.AppendText("Type in your wonderfull code here.")
        fg = wx.Colour(200,80,100)
        at = wx.TextAttr(fg)
        self.status_area.SetStyle(3, 5, at)
        self.CreateStatusBar() # A Statusbar in the bottom of the window

        # Setting up the menu.
        filemenu= wx.Menu()

        filemenu.Append(wx.ID_ABOUT, "&About","Use to edit python code")
        filemenu.AppendSeparator()
        filemenu.Append(wx.ID_EXIT,"&Exit"," Terminate the program")

        # Creating the menubar.
        menuBar = wx.MenuBar()
        menuBar.Append(filemenu,"&File") # Adding the "开发者_运维问答filemenu" to the MenuBar
        self.SetMenuBar(menuBar)  # Adding the MenuBar to the Frame content.
        self.Show(True)


    def onKeyPress (self, event):
        print "KEY PRESSED"
        kc = event.GetKeyCode()
        if kc == WXK_SPACE or kc == WXK_RETURN:
            Line = self.status_area.GetValue()
            print Line
app = wx.App(False)
frame = MainWindow(None, "Python Coder")
app.MainLoop()


In your MainWindow __init__ function add this

self.Bind(wx.EVT_CHAR, self.onKeyPress, self.status_area)

then define onKeyPress in MainWindow

def onKeyPress (self, event):
    kc = event.GetKeyCode()
    if kc == WXK_SPACE or kc == WXK_RETURN:
        #Run your highlighting code here

Come to think of it, this might not be the most efficient way of doing code highlighting. Let me look this up. But in the meantime you can try this.

Edit: Take a look at this - StyledTextCtrl . I think its more along the lines of what you need.


I solved this when I faced the same issue by creating a custom event.

First, I created a subclass of the TextCtrl, so I had a place in code to raise/post the custom event from:

import  wx.lib.newevent
(OnChangeEvent, EVT_VALUE_CHANGED) = wx.lib.newevent.NewEvent()

class TextBox(wx.TextCtrl):
    old_value = u''

    def __init__(self,*args,**kwargs):
        wx.TextCtrl.__init__(self,*args,**kwargs)
        self.Bind(wx.EVT_SET_FOCUS, self.gotFocus) # used to set old value
        self.Bind(wx.EVT_KILL_FOCUS, self.lostFocus) # used to get new value

    def gotFocus(self, evt):
        evt.Skip()
        self.old_value = self.GetValue()

def lostFocus(self, evt):
    evt.Skip()
    if self.GetValue() != self.old_value:
        evt = OnChangeEvent(oldValue=self.old_value, newValue=self.GetValue())
        wx.PostEvent(self, evt)

Now, in my frame's code, here is a snippet of me Binding the event, and using it.

summ_text_ctrl = TextBox(self, -1, size=(400, -1))
summ_text_ctrl.Bind(EVT_VALUE_CHANGED, self.onTextChanged)

def OnTextChanged(self, evt):
    evt.Skip()
    print('old Value: %s' % evt.oldValue )
    print('new Value: %s' % evt.newValue )
0

精彩评论

暂无评论...
验证码 换一张
取 消