Kivy复制按钮文本到剪贴板

时间:2017-12-27 05:12:10

标签: python python-3.x kivy

这是我的第一个Kivy应用程序,令人惊讶的是,我没有通常使用剪贴板复制/粘贴按钮文本的文档数量,因为它很简单,但是我得到一个跟踪,说ValueError嵌入了空字符。

我认为这是因为按钮产生了最近散列文本的文本,并且它仍然包含在字节字符串中,但是当解码时,如果它已经解码并且状态字符串没有解码属性,则它会起作用。我提前为我的代码中的“玩”而道歉,如果答案一直在盯着我

kivy剪贴板doc: https://kivy.org/docs/api-kivy.core.clipboard.html#

**更新 我相信我发现了这个问题,无论传递给剪贴板函数的数据类型是否存在Value错误,我都看了kivy文件中的剪贴板“clipboard_winctypes.py”和put()函数下的函数调用msvcrt.wcscpy_s()。当这被注释掉时,剪贴板将复制按钮文本,但是,我收到了奇怪的东西,如⫐ᵄƅ

也在put()函数下,其中​​text被设置为text + = u'x00',如果这被注释掉并且msvcrt.wscpy_s()被取消注释而被调用则执行时没有错误但没有任何内容被复制到剪贴板然而msvcrt是ctypes.cdll.msvcrt的一个对象,我不知道从哪里开始

clipboard_winctypes.py:

'''
Clipboard windows: an implementation of the Clipboard using ctypes.
'''

__all__ = ('ClipboardWindows', )

from kivy.utils import platform
from kivy.core.clipboard import ClipboardBase

if platform != 'win':
    raise SystemError('unsupported platform for Windows clipboard')

import ctypes
from ctypes import wintypes
user32 = ctypes.windll.user32
kernel32 = ctypes.windll.kernel32
msvcrt = ctypes.cdll.msvcrt
c_char_p = ctypes.c_char_p
c_wchar_p = ctypes.c_wchar_p


class ClipboardWindows(ClipboardBase):

    def get(self, mimetype='text/plain'):
        GetClipboardData = user32.GetClipboardData
        GetClipboardData.argtypes = [wintypes.UINT]
        GetClipboardData.restype = wintypes.HANDLE

        user32.OpenClipboard(user32.GetActiveWindow())
        # 1 is CF_TEXT
        pcontents = GetClipboardData(13)
        if not pcontents:
            return ''
        data = c_wchar_p(pcontents).value.encode(self._encoding)
        user32.CloseClipboard()
        return data

    def put(self, text, mimetype='text/plain'):
        text = text.decode(self._encoding)  # auto converted later
        text += u'\x00'

        SetClipboardData = user32.SetClipboardData
        SetClipboardData.argtypes = [wintypes.UINT, wintypes.HANDLE]
        SetClipboardData.restype = wintypes.HANDLE

        GlobalAlloc = kernel32.GlobalAlloc
        GlobalAlloc.argtypes = [wintypes.UINT, ctypes.c_size_t]
        GlobalAlloc.restype = wintypes.HGLOBAL

        CF_UNICODETEXT = 13

        user32.OpenClipboard(user32.GetActiveWindow())
        user32.EmptyClipboard()
        hCd = GlobalAlloc(0, len(text) * ctypes.sizeof(ctypes.c_wchar))
        msvcrt.wcscpy_s(c_wchar_p(hCd), len(text), c_wchar_p(text))
        SetClipboardData(CF_UNICODETEXT, hCd)
        user32.CloseClipboard()

    def get_types(self):
        return ['text/plain']

cry_hash.py

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.label import Label
import hashlib


class Hasher:
    def __init__(self, to_hash, hash_alg, hash_length):
        if to_hash != type(bytes):
            self.to_hash = bytes(to_hash, encoding='utf-8')
        else:
            self.to_hash = to_hash
        self.hash_alg = hash_alg
        self.hash_length = int(hash_length)

    def create_hash(self):
        hash_object = hashlib.new(self.hash_alg)
        hash_object.update(self.to_hash)
        result = hash_object.hexdigest()[:self.hash_length]
        del hash_object
        return result


class LabelBackground(Label):
    pass


class CryHashWidgetBoxLayout(BoxLayout):
    def get_hash(self, user_hash, hash_length):
        tb = next((t for t in ToggleButton.get_widgets('hash_type') if  t.state == 'down'), None)
        hash_alg = tb.text if tb else None
        krypt_tool = Hasher(user_hash, hash_alg, hash_length)
        hashed_input = krypt_tool.create_hash()

        self.ids.hash_return.text = hashed_input

    def reset(self, text_reset):
        incoming = text_reset
        del incoming
        incoming = ''
        self.ids.hash_return.text = incoming


class CryHashApp(App):
    def build(self):
        return CryHashWidgetBoxLayout()


if __name__ == '__main__':
    CryHashApp().run()

KV文件:cryhash.kv

#File name: cry_hash.py
#:import utils kivy.utils
#:import Clipboard kivy.core.clipboard.Clipboard


<ToggleButton>:
    background_color: utils.get_color_from_hex('#E00000')

<TextInput>:
    background_color: utils.get_color_from_hex('#5F9B9F')

<Label>
    font_name: 'fonts/arialbd.ttf'

<CryHashWidgetBoxLayout>:
    orientation: 'vertical'

    Label:
        font_name: 'fonts/welga.ttf'
        color: utils.get_color_from_hex('#E00000')
        text: 'Welcome to Cry Hash!'
        font_size: 80

    Button:
        id: hash_return
        background_color: utils.get_color_from_hex('#F15E92')
        font_size: 40
        text: ''
        on_release:
            Clipboard.copy(hash_return.text)

    BoxLayout:
        orientation: 'horizontal'
        BoxLayout:
            orientation: 'vertical'

            Label:
                id: bg_hash
                color: utils.get_color_from_hex('#E00000')
                text: 'Enter text to hash'

            TextInput:
                id: user_hash
                multiline: False
                text: ''


            Label:
                id: bg_length
                color: utils.get_color_from_hex('#E00000')
                text: 'Enter length'

            TextInput:
                id: get_hash_length
                multiline: False
                text: '10'

            Button:
                id: get_data
                background_color: utils.get_color_from_hex('#1900FF')
                text: 'get hash!'
                on_release: root.get_hash(user_hash.text, get_hash_length.text)

        BoxLayout:
            orientation: 'vertical'

            ToggleButton:
                id: SHA256
                text: 'SHA256'
                state: 'down'
                group: 'hash_type'

            ToggleButton:
                id: SHA512
                text: 'SHA512'
                group: 'hash_type'

            ToggleButton:
                id: SHA1
                text: 'SHA1'
                group: 'hash_type'

            ToggleButton:
                id: MD5
                text: 'MD5'
                group: 'hash_type'

2 个答案:

答案 0 :(得分:1)

总结其他答案:

问题

  

使用复制到剪贴板(Kivy)时出现“ ValueError:嵌入的空字符”

解决方案

  1. pip安装pyperclip
  2. pyperclip.copy('text that you want into clipboard')

答案 1 :(得分:0)

我找到了一个解决方法,我相信这只是Kivy框架中的一个错误,如果有人能在kivy代码中找到真正的解决方案请告诉我,否则我只需导入pyperclip,创建一个pyperclip复制函数在.py文件中并调用.kv文件中的函数。完美无瑕!

cry_hash.py:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.label import Label
import hashlib
import pyperclip

class Hasher:
    def __init__(self, to_hash, hash_alg, hash_length):
        if to_hash != type(bytes):
            self.to_hash = bytes(to_hash, encoding='utf-8')
        else:
            self.to_hash = to_hash
        self.hash_alg = hash_alg
        self.hash_length = int(hash_length)

    def create_hash(self):
        hash_object = hashlib.new(self.hash_alg)
        hash_object.update(self.to_hash)
        result = hash_object.hexdigest()[:self.hash_length]
        del hash_object
        return result


class LabelBackground(Label):
    pass


class CryHashWidgetBoxLayout(BoxLayout):
    def get_hash(self, user_hash, hash_length):
        tb = next((t for t in ToggleButton.get_widgets('hash_type') if t.state == 'down'), None)
        hash_alg = tb.text if tb else None
        krypt_tool = Hasher(user_hash, hash_alg, hash_length)
        hashed_input = krypt_tool.create_hash()
        self.ids.hash_return.text = str(hashed_input)

    def reset(self, text_reset):
        incoming = text_reset
        del incoming
        incoming = ''
        self.ids.hash_return.text = incoming

    def copy_text(self, text):
        pyperclip.copy(text)


class CryHashApp(App):
    def build(self):
        return CryHashWidgetBoxLayout()


if __name__ == '__main__':
    CryHashApp().run()

cryhash.kv:

#File name: cry_hash.py
#:import utils kivy.utils
#:import Clipboard kivy.core.clipboard.Clipboard


<ToggleButton>:
    background_color: utils.get_color_from_hex('#E00000')

<TextInput>:
    background_color: utils.get_color_from_hex('#5F9B9F')

<Label>
    font_name: 'fonts/arialbd.ttf'

<CryHashWidgetBoxLayout>:
    orientation: 'vertical'

    Label:
        font_name: 'fonts/welga.ttf'
        color: utils.get_color_from_hex('#E00000')
        text: 'Welcome to Cry Hash!'
        font_size: 80

    Button:
        id: hash_return
        background_color: utils.get_color_from_hex('#F15E92')
        font_size: 40
        text: ''
        on_release: root.copy_text(hash_return.text)

    BoxLayout:
        orientation: 'horizontal'
        BoxLayout:
            orientation: 'vertical'

            Label:
                id: bg_hash
                color: utils.get_color_from_hex('#E00000')
                text: 'Enter text to hash'

            TextInput:
                id: user_hash
                multiline: False
                text: ''


            Label:
                id: bg_length
                color: utils.get_color_from_hex('#E00000')
                text: 'Enter length'

            TextInput:
                id: get_hash_length
                multiline: False
                text: '10'

            Button:
                id: get_data
                background_color: utils.get_color_from_hex('#1900FF')
                text: 'get hash!'
                on_release: root.get_hash(user_hash.text, get_hash_length.text)

        BoxLayout:
            orientation: 'vertical'

            ToggleButton:
                id: SHA256
                text: 'SHA256'
                state: 'down'
                group: 'hash_type'

            ToggleButton:
                id: SHA512
                text: 'SHA512'
                group: 'hash_type'

            ToggleButton:
                id: SHA1
                text: 'SHA1'
                group: 'hash_type'

            ToggleButton:
                id: MD5
                text: 'MD5'
                group: 'hash_type'