如何使用wxpython判断剪贴板中的bmp图片是否相同?

How to judge bmp pictures from clipboard whether they are same using wxpython?

我想实现的功能: 从剪贴板获取的bmp图片改变时,刷新window。否则什么都不做。

我遇到的问题: 每次我的程序进入 UpdateMsgShownArea() 函数时,self.oldBmp 将与 self.bmp 不同,但如果它们不同,我已经让 self.oldBmp = self.bmp,并打印“111111”。下一次程序进入 UpdateMsgShownArea() 时,self.oldBmp 将再次与 self.bmp 不同。这让我很困惑。

代码如下:

#!/usr/bin/env python

import wx
import os, sys

#----------------------------------------------------------------------------

# main window
class MyFrame(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(600,480))
        self.panel = MyPanel(self)
        self.CreateStatusBar() # A StatusBar in the bottom of the window

        # Setting up the menu.
        filemenu= wx.Menu()

        # wx.ID_ABOUT and wx.ID_EXIT are standard ids provided by wxWidgets.
        menuAbout = filemenu.Append(wx.ID_ABOUT, "&About"," Information about this program")
        menuExit = filemenu.Append(wx.ID_EXIT,"E&xit"," Terminate the program")

        # Creating the menubar.
        menuBar = wx.MenuBar()
        menuBar.Append(filemenu,"&File") # Adding the "filemenu" to the MenuBar
        self.SetMenuBar(menuBar)  # Adding the MenuBar to the Frame content.

        # Set events.
        self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout)
        self.Bind(wx.EVT_MENU, self.OnExit, menuExit)

        self.Show(True)

    def OnAbout(self,e):
        # A message dialog box with an OK button. wx.OK is a standard ID in wxWidgets.
        dlg = wx.MessageDialog( self, "A small text editor", "About Sample Editor", wx.OK)
        dlg.ShowModal() # Show it
        dlg.Destroy() # finally destroy it when finished.

    def OnExit(self,e):
        self.Close(True)  # Close the frame.

#----------------------------------------------------------------------------

# main panel
class MyPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1)

        # shared path boxsizer, DirPickerCtrl is alternative and better realization for textCtrl + btn
        sharedPathStaticText = wx.StaticText(self, -1, 'Shared Dir:')
        self.sharedPathTextCtrl = wx.TextCtrl(self, -1, 'Please choose a dir', style = wx.TE_READONLY|wx.TE_RICH)
        sharedPathBtn = wx.Button(self, -1, 'Browse', name = 'Shared dir button')


        box1 = wx.BoxSizer(wx.HORIZONTAL)
        box1.Add(sharedPathStaticText, 0, wx.ALIGN_CENTER)
        box1.Add(self.sharedPathTextCtrl, 1, wx.ALIGN_CENTER|wx.LEFT|wx.RIGHT, 5) # proportion = 1, border = 5
        box1.Add(sharedPathBtn, 0)

        self.Bind(wx.EVT_BUTTON, self.OnOpen, sharedPathBtn)

        # local path boxsizer
        localPathStaticText = wx.StaticText(self, -1, 'Local Dir:   ')
        self.localPathTextCtrl = wx.TextCtrl(self, -1, 'Please choose a dir', style = wx.TE_READONLY|wx.TE_RICH)
        localPathBtn = wx.Button(self, -1, 'Browse', name = 'local dir button')

        box2 = wx.BoxSizer(wx.HORIZONTAL)
        box2.Add(localPathStaticText, 0, wx.ALIGN_CENTER)
        box2.Add(self.localPathTextCtrl, 1, wx.ALIGN_CENTER|wx.LEFT|wx.RIGHT, 5) # proportion = 1, border = 5
        box2.Add(localPathBtn, 0)

        self.Bind(wx.EVT_BUTTON, self.OnOpen, localPathBtn)

        # message show area
        messageShowStaticText = wx.StaticText(self, -1, 'Sync info shown area:   ')

        box5 = wx.BoxSizer(wx.HORIZONTAL)
        box5.Add(messageShowStaticText, 0, wx.ALIGN_LEFT)

        # size (200,200) don't take effect
        #msgShowAreaID = wx.NewId()
        #print msgShowAreaID
        self.msgShowArea = wx.ScrolledWindow(self, -1, size = (200,200), style = wx.SIMPLE_BORDER)

        box3 = wx.BoxSizer(wx.HORIZONTAL)
        box3.Add(self.msgShowArea, 1, wx.ALIGN_CENTER, 10)

        # sync ctrl buttons
        stopSyncBtn = wx.Button(self, -1, 'Stop Sync', name = 'Stop Sync button')
        resumeSyncBtn = wx.Button(self, -1, 'Resume Sync', name = 'Resume Sync button')

        box4 = wx.BoxSizer(wx.HORIZONTAL)
        box4.Add(stopSyncBtn, 0, wx.ALIGN_CENTER|wx.RIGHT, 20)
        box4.Add(resumeSyncBtn, 0, wx.ALIGN_CENTER|wx.LEFT, 20)

        # sizer
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(box1, 0, wx.EXPAND|wx.ALL, 10)
        sizer.Add(box2, 0, wx.EXPAND|wx.ALL, 10)
        sizer.Add(box5, 0, wx.EXPAND|wx.ALL, 10)
        sizer.Add(box3, 0, wx.EXPAND|wx.ALL, 10)
        sizer.Add(box4, 0, wx.ALIGN_CENTER, 10)

        self.SetSizer(sizer)
        self.SetAutoLayout(True)

        # clipboard
        self.clip = wx.Clipboard()
        self.x = wx.BitmapDataObject()
        self.bmp = None
        self.oldBmp = None

        self.msgShowArea.Bind(wx.EVT_IDLE, self.UpdateMsgShownArea)
        self.msgShowArea.Bind(wx.EVT_PAINT, self.OnPaint)

    def OnOpen(self, e):
        """ Open a file"""
        button = e.GetEventObject()
        dlg = wx.DirDialog(self, "Choose a dir", "", wx.DD_DEFAULT_STYLE | wx.DD_DIR_MUST_EXIST)
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()

            if button.GetName() == 'Shared dir button':
                self.sharedPathTextCtrl.SetValue(path)
            if  button.GetName() == 'local dir button':
                self.localPathTextCtrl.SetValue(path)
        dlg.Destroy()

    def UpdateMsgShownArea(self, e):
        print "UpdateMsgShownArea"
        self.clip.Open()
        self.clip.GetData(self.x)
        self.clip.Close()
        self.bmp = self.x.GetBitmap()
        if self.oldBmp == self.bmp:
            print "same pic"
            return
        else:
            print "diff pic"
            self.oldBmp = self.bmp
            if  self.oldBmp == self.bmp:
                print "111111"
            else:
                print "222222"

        print "abcd"
        #self.Refresh()
        #self.msgShowArea.Refresh()

    def OnPaint(self, evt):
        if self.bmp:
            dc = wx.PaintDC(self.msgShowArea)
            dc.DrawBitmap(self.bmp, 20, 20, True)


#----------------------------------------------------------------------------

if __name__ == '__main__':
    app = wx.App(False)
    frame = MyFrame(None, "EasySync")
    app.MainLoop()

不幸的是,wxWidgets 不支持剪贴板更改通知。在 MSW 下添加它会相对简单,但我不太确定其他平台。

无论如何,现在您唯一的选择是轮询剪贴板的更改,即设置一个计时器并在每次触发时检查剪贴板内容。这很丑陋且效率低下,但应该有效。

将位图转换为图像,然后比较图像可以解决这个问题。

        self.clip.GetData(self.bmpObj)
        self.bmp = self.bmpObj.GetBitmap()  # bitmap
        self.Img = self.bmp.ConvertToImage().GetData()  # convert bmp to image
        isDrawBmp = True

        if CLIP_TYPE_IMAGE == self.lastClipType:
            if self.oldImg == self.Img:    # compare images
                #print "same pic"
                #return
                isDrawBmp = False
            else:
                #print "diff pic"
                self.oldImg = self.Img

        else:
            self.oldImg = self.Img