目标: 使用python的build-in 的 package ,从windows clipboard获取粘贴板的图片. 不使用第三方库
1, Tkinter class 里面有一个clipboard.get()函数,可以很轻松的获得字符串类的数据。
import tkinter as tt
tk = tt.Tk()
copy = tk.clipboard_get()
print(copy)
2, 如果粘贴板上的内容是图像,那么这个方法就不行了,会报以下错误
TclError: CLIPBOARD selection doesn’t exist or form “STRING” not defined
这里涉及两个概念,一个是selection,另外一个是string。
去clipboard 的源码,我们发现
# Clipboard handling:
def clipboard_get(self, **kw):
"""Retrieve data from the clipboard on window's display.
The window keyword defaults to the root window of the Tkinter
application.
The type keyword specifies the form in which the data is
to be returned and should be an atom name such as STRING
or FILE_NAME. Type defaults to STRING, except on X11, where the default
is to try UTF8_STRING and fall back to STRING.
This command is equivalent to:
selection_get(CLIPBOARD)
"""
if 'type' not in kw and self._windowingsystem == 'x11':
try:
kw['type'] = 'UTF8_STRING'
return self.tk.call(('clipboard', 'get') + self._options(kw))
except TclError:
del kw['type']
return self.tk.call(('clipboard', 'get') + self._options(kw))
这里可以看到,get里面可以传 一个kw, 即 a = xxx 类型的变量。翻阅资料,查到get默认的传参是
type=“STRING”。
那么 改变参数,使其支持image不就行了。
网上可以搜到这样的设置, type=“image/png” ,据作者说,可以再unix上得到图像的byte形式的数据。
我在windows试了下这样的参数,结果还是报错。
于是打算继续看源码。
3, self.tk 的初始化在
class Tk(Misc, Wm):
"""Toplevel widget of Tk which represents mostly the main window
of an application. It has an associated Tcl interpreter."""
_w = '.'
def __init__(self, screenName=None, baseName=None, className='Tk',
useTk=1, sync=0, use=None):
"""Return a new Toplevel widget on screen SCREENNAME. A new Tcl interpreter will
be created. BASENAME will be used for the identification of the profile file (see
readprofile).
It is constructed from sys.argv[0] without extensions if None is given. CLASSNAME
is the name of the widget class."""
self.master = None
self.children = {}
self._tkloaded = 0
# to avoid recursions in the getattr code in case of failure, we
# ensure that self.tk is always _something_.
self.tk = None
if baseName is None:
import os
baseName = os.path.basename(sys.argv[0])
baseName, ext = os.path.splitext(baseName)
if ext not in ('.py', '.pyc'):
baseName = baseName + ext
interactive = 0
self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
if useTk:
self._loadtk()
if not sys.flags.ignore_environment:
# Issue #16248: Honor the -E flag to avoid code injection.
self.readprofile(baseName, className)
以下是个人猜测,不一定正确。
tk 是一个本身的包. tkinter 本身是一个纯python的module,可以从目录看到
感觉不像是直接能获取windows的clipboard的内容。 后来,继续查发现其可能借助tk。
可以在计算机上找到这样的
tcl8.6 tk8.6
4, 查看tk的 tk.tcl文件,我们发现一个selection的函数
# ::tk::GetSelection --
# This tries to obtain the default selection. On Unix, we first try
# and get a UTF8_STRING, a type supported by modern Unix apps for
# passing Unicode data safely. We fall back on the default STRING
# type otherwise. On Windows, only the STRING type is necessary.
在windows系统,只有string类型是必要的
# Arguments:
# w The widget for which the selection will be retrieved.
# Important for the -displayof property.
# sel The source of the selection (PRIMARY or CLIPBOARD)
# Results:
# Returns the selection, or an error if none could be found
#
if {[tk windowingsystem] ne "win32"} {
proc ::tk::GetSelection {w {sel PRIMARY}} {
if {[catch {
selection get -displayof $w -selection $sel -type UTF8_STRING
} txt] && [catch {
selection get -displayof $w -selection $sel
} txt]} then {
return -code error -errorcode {TK SELECTION NONE} \
"could not find default selection"
} else {
return $txt
}
}
} else {
proc ::tk::GetSelection {w {sel PRIMARY}} {
if {[catch {
selection get -displayof $w -selection $sel
} txt]} then {
return -code error -errorcode {TK SELECTION NONE} \
"could not find default selection"
} else {
return $txt
}
}
}
如果粘贴板上只有图片,没有string,那么就会报 没找到selection, 因为string是neccessary.