2

I have a shell-like console for my app, which prompts with ">>>" after every command. The problem is every time I have my shell WriteText(">>> "), it also appends a new line. The user can backspace up to the correct line, but this just looks terrible. Any way to fix it?

chucksmash
  • 5,777
  • 1
  • 32
  • 41
Shaunak
  • 27
  • 3

1 Answers1

6

I suspect you are declaring your TextCtrl to be of style wx.TE_PROCESS_ENTER and then binding the EVT_TEXT_ENTER event - only because I ran into the same problem when I tried that.

My first instinct was to write a method to process wx.EVT_TEXT_ENTER that would then use the TextCtrl:Remove() method. This method only seems to remove visible characters, unfortunately. My next thought was to use the EmulateKeyPress() method along with backspace (WKX_BACK) to erase the newline character. This might be doable though I couldn't come up with a good way to spoof a wx.KeyEvent (can't just use event.m_keyCode since EVT_TEXT_ENTER sends a CommandEvent, and not a KeyEvent) so I gave up on that approach... err, I mean this solution is left as an exercise to the reader.

wx.EVT_TEXT_ENTER being a CommandEvent finally led to a third angle which did work. Instead of binding wx.EVT_TEXT_ENTER, I bound wx.EVT_CHAR and put in logic with special processing for the Return key (ASCII key code 13). I then planned to implement the EmulateKeyPress() bit I talked about earlier but when I removed wx.TE_PROCESS_ENTER from the TextCtrl style, I discovered that the \n was no longer being surreptitiously added. Code follows:

import wx

class TestRun(wx.Frame):
    def __init__(self,parent):
        wx.Frame.__init__(self, parent, title="StackO Test", size=(400,400))
        self.control = wx.TextCtrl(self, id=wx.ID_ANY, style=wx.TE_MULTILINE)
        self.control.Bind(wx.EVT_CHAR, self.OnPress)

        self.Show(True)

    def OnPress(self, event):
        if event.GetKeyCode() == 13:
            self.control.WriteText('\n>>>')
        else:
            event.Skip()

if __name__ == '__main__':
    app = wx.App(False)
    TestRun(None)
    app.MainLoop()

The event.Skip() line is crucial; during my research into this, I learned that a KeyEvent is usually followed by a CharEvent. The CharEvent is the part where the character is written to the TextCtrl. When you intercept the KeyEvent, the CharEvent is only called if you do so explicitly - event.skip() is therefore vital if you want your TextCtrl to otherwise behave as normal. Without it, any keyboard input not equal to ASCII keycode 13 would do nothing.

From my tests, it appears that there is something about declaring the TextCtrl to have style wx.TE_PROCESS_ENTER that makes it print a newline after each call to WriteText(). My way gets around this though you will have more work to do with regard to making sure the insertion point is always in the right place, etc.

Best of luck!

chucksmash
  • 5,777
  • 1
  • 32
  • 41
  • Yea figured this out after a little tinkering, but great answer. – Shaunak Mar 25 '11 at 18:17
  • Maybe my particular setup/case isn't exactly the same but I prevented my `wx.TextCtrl.write(text)` from adding newlines by simply doing `wx.TextCtrl.write(text.rstrip())`, I was surprised this worked since I did not input any newlines into my `text` variable myself, but apparently they where somehow added by `.write()` and using `.rstrip()` on my textvariable stops it from doing that. (+1 for @chucksmash clear and extensive answer though). – Montmons Dec 25 '17 at 13:12