wxPython: How to use the Clipboard

Everyone who uses computers regularly knows that they can copy and paste text. What they might not know is that when you copy something, it goes into a location known as the “clipboard”. Most programs provide access to a clipboard of some sort, whether it be just within the program itself or to the system clipboard, which allows items to be copied to other applications. The wxPython GUI toolkit also provides clipboard access, which you can use to copy text to and from within your program and even to the system clipboard. You can also copy images to the clipboard. In this tutorial, we’ll take a look at how you can do this in your own code.

We’ll start out with a really simple example code snippet. The following contains two buttons, one which copies any text that’s added to the text control and which you can then paste elsewhere, such as in the text box, in a search engine or whatever. The other button also copies to clipboard and then closes the application after flushing the data. This is supposed to make the data available in the system clipboard even after the application is closed. Both work great on Windows, but wxGTK (i.e. the Linux version) doesn’t work in the latter case. See the bug ticket for more information.

Anyway, let’s look at the code!

import wx

########################################################################
class ClipboardPanel(wx.Panel):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent)
        
        lbl = wx.StaticText(self, label="Enter text to copy to clipboard:")
        self.text = wx.TextCtrl(self, style=wx.TE_MULTILINE)
        copyBtn = wx.Button(self, label="Copy")
        copyBtn.Bind(wx.EVT_BUTTON, self.onCopy)
        copyFlushBtn = wx.Button(self, label="Copy and Flush")
        copyFlushBtn.Bind(wx.EVT_BUTTON, self.onCopyAndFlush)
        
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(lbl, 0, wx.ALL, 5)
        sizer.Add(self.text, 1, wx.EXPAND)
        sizer.Add(copyBtn, 0, wx.ALL|wx.CENTER, 5)
        sizer.Add(copyFlushBtn, 0, wx.ALL|wx.CENTER, 5)
        self.SetSizer(sizer)
        
    #----------------------------------------------------------------------
    def onCopy(self, event):
        """"""
        self.dataObj = wx.TextDataObject()
        self.dataObj.SetText(self.text.GetValue())
        if wx.TheClipboard.Open():
            wx.TheClipboard.SetData(self.dataObj)
            wx.TheClipboard.Close()
        else:
            wx.MessageBox("Unable to open the clipboard", "Error")
            
    #----------------------------------------------------------------------
    def onCopyAndFlush(self, event):
        """"""
        self.dataObj = wx.TextDataObject()
        self.dataObj.SetText(self.text.GetValue())
        if wx.TheClipboard.Open():
            wx.TheClipboard.SetData(self.dataObj)
            wx.TheClipboard.Flush()
        else:
            wx.MessageBox("Unable to open the clipboard", "Error")
            
        self.GetParent().Close()

########################################################################
class ClipboardFrame(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="Clipboard Tutorial")
        panel = ClipboardPanel(self)
        self.Show()
    
    
if __name__ == "__main__":
    app = wx.App(False)
    frame = ClipboardFrame()
    app.MainLoop()
    

As you might have guessed, the guts of this script are in the button event handlers. The main bit is wx.TextDataObject which will store the data from the text control. Next we attempt to open the clipboard. If we’re successful, we add our text to the clipboard and then close it. The data is now there for the pasting. The second event handler does the same thing, but it Flushes to the clipboard rather than just closing it. If you wanted to copy a bitmap instead, then you’d want to use a wx.BitmapDataObject and pass it an wx.Bitmap object. Otherwise, the rest is the same.

Wrapping Up

Now you know how to use the clipboard from wxPython! Get out there and start creating something to amaze your friends and strangers alike!

Additional Resources