防止wxpython TextCtrl.WriteText()后出现换行

2 投票
1 回答
1956 浏览
提问于 2025-04-16 13:02

我有一个类似命令行的控制台,用于我的应用程序,每次输入命令后都会显示一个提示符“>>>”。问题是每次我让控制台显示“>>> ”时,它都会自动换行。用户虽然可以用退格键回到正确的行,但这样看起来实在太糟糕了。有没有办法解决这个问题?

1 个回答

6

我怀疑你在定义你的 TextCtrl 时用了 wx.TE_PROCESS_ENTER 这个样式,然后又绑定了 EVT_TEXT_ENTER 事件——我也是因为遇到同样的问题才这么想的。

我最开始的想法是写一个方法来处理 wx.EVT_TEXT_ENTER,然后用 TextCtrl:Remove() 方法来删除内容。可惜这个方法似乎只能删除可见的字符。接着我想到了用 EmulateKeyPress() 方法配合退格键(WKX_BACK)来删除换行符。这个方法可能可行,但我找不到一个好的办法来伪造 wx.KeyEvent(不能直接用 event.m_keyCode,因为 EVT_TEXT_ENTER 发送的是 CommandEvent,而不是 KeyEvent),所以我放弃了这个思路……呃,我是说这个解决方案留给读者自己去探索。

由于 wx.EVT_TEXT_ENTER 是一个 CommandEvent,这让我找到了第三种有效的方法。与其绑定 wx.EVT_TEXT_ENTER,我选择绑定 wx.EVT_CHAR,并为 Return 键(ASCII 码 13)添加了特殊处理逻辑。然后我打算实现之前提到的 EmulateKeyPress(),但当我把 wx.TE_PROCESS_ENTER 从 TextCtrl 的样式中去掉后,我发现换行符 \n 不再被偷偷添加了。代码如下:

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

event.Skip() 这一行非常重要;在我研究这个问题时,我了解到 KeyEvent 通常会跟着一个 CharEventCharEvent 是将字符写入 TextCtrl 的部分。当你拦截 KeyEvent 时,CharEvent 只有在你明确调用的情况下才会被触发——所以如果你想让你的 TextCtrl 正常工作,event.skip() 是必不可少的。没有它,任何不是 ASCII 码 13 的键盘输入都不会有任何反应。

根据我的测试,似乎是因为定义 TextCtrl 使用了 wx.TE_PROCESS_ENTER 这个样式,导致每次调用 WriteText() 后都会自动添加一个换行符。我的方法可以绕过这个问题,不过你需要更多的工作来确保插入点始终在正确的位置等等。

祝你好运!

撰写回答