开发者

how to create read only text ctrl but support copy paste event

开发者 https://www.devze.com 2023-01-15 22:42 出处:网络
In my application i have text control. I want my text ctrl should be read only but when some 开发者_运维问答one right click on this he is able to copy the value from that ctrl and he can paste that va

In my application i have text control. I want my text ctrl should be read only but when some 开发者_运维问答one right click on this he is able to copy the value from that ctrl and he can paste that value in other text control.

If i made my text control read only with wx.TE_READONLY then copy/paste is not working.

Is there any requirement to handle other type of wx event or i have to set more type of wx style flags while creating the text control object.

Thanks in advance.


Hmm Im on windows 7 and don't have any problem copying from a textCtrl that has the wx.READ_ONLY style flag set.

You said you wanted to paste into another textCtrl -obviously you can't have the wx.READ_ONLY style flag set in the textCtrl you want to be able to paste into.

Try out the demo below, you should be able to copy from the textCtrl on the left(which is read only) to the one on the right(which doesn't have the read only style set).

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


We should bind wx.EVT_TEXT_COPY and wx.EVT_TEXT_PASTE with text control. one can copy and paste data from text ctrl although text ctrl is read only mode.


Actually I had the same challenge. I needed a textbox where users could paste information (or open -> read file via a menu). The app would then analyze the info for correctness. But I didn't want to allow editing in the textbox - it would suggest that you could correct in the same textbox, while the app was for analysis only. Yeah, requirements, I know.

Weird thing was, I could make a readonly TextCtrl under MacOSX that would allow pasting (but not editing), but not on Windows.

In order to support both, I ended up creating a read/writesuper(MyWin, self).init(None, size=(800,600)) textbox (to allow pasting under windows) and binding wx.EVT_TEXT events to it (apart from wx.EVT_TEXT_PASTE for the obvious pasting). The EVT_TEXT handler that's triggered when the textctrl's contents change, simply shows a dialog that you aren't allowed to do this.

In the app a boolean this.painted plays the following role: when this.painted is true, then modifications of the textctrl aren't allowed. So, the onpaste handler first sets this.painted to false, then modifies the TextCtrl's contents, then sets this.painted to true (otherwise the dialog alert would also go off during the paste event, which I wanted to allow). Unfortunately when the EVT_TEXT handler goes off, the window's contents have already been modified by a user hitting some key. Therefore the app also needs a backup buffer to put back into the TextCtrl when such editing has been detected.

According to the Python docs, TextCtrl.ChangeValue() instead of SetValue() should not trigger the EVT_TEXT event (which would be handy) but I couldn't get that to work, might be my mistake due to not-enough-time-to-investigate-because-it-should-have-been-done-yesterday.

Not an elegant solution, but works.

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

精彩评论

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