如何创建只读文本ctrl但支持复制粘贴事件

时间:2010-09-14 16:13:40

标签: python wxpython

在我的应用程序中,我有文本控制。 我希望我的文本ctrl应该是只读的,但当有人右键单击它时,他可以从该ctrl中复制该值,并且可以将该值粘贴到其他文本控件中。

如果我的文本控件只能用wx.TE_READONLY读取,那么复制/粘贴不起作用。

是否需要处理其他类型的wx事件,或者我必须在创建文本控制对象时设置更多类型的wx样式标志。

提前致谢。

3 个答案:

答案 0 :(得分:2)

嗯我在Windows 7上,并且从设置了textCtrl样式标志的wx.READ_ONLY复制没有任何问题。

你说你想粘贴到另一个textCtrl - 显然你不能在你想要粘贴的wx.READ_ONLY中设置textCtrl样式标志。

尝试下面的演示,你应该能够从左边的textCtrl(只读)复制到右边的那个(没有只读样式集)。

import wx

class MainWindow(wx.Frame):
    def __init__(self, parent, id=-1):
        wx.Frame.__init__(self,parent,id, size=(200,200))

        self.panel = wx.Panel(self,wx.ID_ANY)     
        bsizer = wx.BoxSizer()       
        read_only_txtCtrl = wx.TextCtrl(self,-1,
                        "This textCtrl is read only",
                        style=wx.TE_MULTILINE|wx.TE_READONLY)

        editable_txtCtrl = wx.TextCtrl(self,-1,
                        "This textCtrl is editable",
                        style=wx.TE_MULTILINE)

        bsizer.Add(read_only_txtCtrl, 1, wx.EXPAND)
        bsizer.Add(editable_txtCtrl, 1, wx.EXPAND)

        self.SetSizerAndFit(bsizer)


if __name__ == "__main__":

    app = wx.PySimpleApp()
    frame = MainWindow(None)
    frame.SetSize((200,200))
    frame.Show()
    app.MainLoop()

答案 1 :(得分:1)

我们应该使用文本控件绑定wx.EVT_TEXT_COPY和wx.EVT_TEXT_PASTE。 可以从文本ctrl复制和粘贴数据,尽管文本ctrl是只读模式。

答案 2 :(得分:0)

其实我遇到了同样的挑战。我需要一个文本框,用户可以在其中粘贴信息(或打开 - >通过菜单读取文件)。然后,应用程序将分析信息的正确性。但是我不想在文本框中进行编辑 - 这表示你可以在相同的文本框中进行修改,而应用程序仅用于分析。是的,要求,我知道。

奇怪的是,我可以在MacOSX下制作一个允许粘贴(但不能编辑)的只读TextCtrl,但不能在Windows上。

为了支持两者,我最终创建了一个read / writesuper(MyWin,self)。 init (None,size =(800,600))textbox(允许在windows下粘贴)和绑定wx.EVT_TEXT事件(除了wx.EVT_TEXT_PASTE以外的明显粘贴)。当文本控件的内容发生变化时触发的EVT_TEXT处理程序只显示一个您不允许执行此操作的对话框。

在app中,boolean this.painted扮演以下角色:当this.painted为true时,则不允许修改textctrl。因此,onpaste处理程序首先将this.painted设置为false,然后修改TextCtrl的内容,然后将this.painted设置为true(否则对话框警报也会在粘贴事件期间关闭,我想允许) 。不幸的是,当EVT_TEXT处理程序关闭时,用户点击某个键已经修改了窗口的内容。因此,当检测到这样的编辑时,应用程序还需要一个备份缓冲区以重新进入TextCtrl。

根据Python文档,TextCtrl.ChangeValue()而不是SetValue()不应该触发EVT_TEXT事件(这会很方便)但是我无法使它工作,可能是我的错误,因为没有-enough时间到调查 - 因为,它-应该具备的,是全熟昨。

不是一个优雅的解决方案,但有效。

import wx

class MyWin(wx.Frame):

    def __init__(self):
        super(MyWin, self).__init__(None, size=(800,600))
        self.painted = True
        self.backup = ''
        self.text = wx.TextCtrl(self, style=wx.TE_MULTILINE | wx.HSCROLL)
        self.text.Bind(wx.EVT_TEXT_PASTE, self.onpaste)
        self.text.Bind(wx.EVT_TEXT, self.ontextchange)
        self.Show()

    def onpaste(self, event):
        if not wx.TheClipboard.IsOpened():
            buf = wx.TextDataObject()
            wx.TheClipboard.Open()
            success = wx.TheClipboard.GetData(buf)
            wx.TheClipboard.Close()
            if success:
                self.painted = False
                self.backup = buf.GetText()
                self.text.SetValue(self.backup)
                self.painted = True

    def ontextchange(self, event):
        if self.painted:
            dlg = wx.MessageDialog(self, 'Editing not allowed', '', wx.OK)
            dlg.ShowModal()
            dlg.Destroy()
            self.painted = False
            self.text.SetValue(self.backup)
            self.painted = True


app = wx.App()
frame = MyWin()
app.MainLoop()