使用PyQT做一个快捷剪切板功能

1.背景

之前使用mac办公,alfred里有个剪切板功能非常好用,因为工作原因需要使用window办公,网上寻找替代品功能上有点不近人意,没有剪切板功能十分难受,于是决定自己做一个

2.技术选型

当然是使用Qt来做,但是不会C++会Python就用PyQt来实现

3.需求

  1. 系统托盘
  2. 窗口失去焦点自动最小化托盘
  3. 快捷键唤起
  4. 输入框补全提示
  5. 补全提示如果有直接展示
  6. 键盘down键直接选择提示文字回车之前进行粘贴
  7. pyQt打包成exe文件后多次打开exe程序只存活一个应用程序

4.实现

一、构建QT界面
class ClipboardViewer(QWidget):

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.center()
        self.line_edit = QLineEdit(self)
        self.setWindowOpacity(0.9)
        self.line_edit.setStyleSheet("""
QLineEdit{
 border: 1px solid #555555;      /* 边框宽度为1px,颜色为#A0A0A0 */
 border-radius: 5px;         /* 边框圆角 */
 padding-left: 5px;           /* 文本距离左边界有5px */
 background-color: #faf9f3;     /* 背景颜色 */
 color: black;     /* 文本颜色 */
 selection-background-color: #A0A0A0;     /* 选中文本的背景颜色 */
 selection-color: #F2F2F2;    /* 选中文本的颜色 */
 font-family: "Microsoft YaHei";    /* 文本字体族 */
}
""")
        font_size = 40
        self.line_edit.setFixedSize(400, font_size)
        # 根据文本长度调整字体大小
        font = self.line_edit.font()
        font.setPointSize(font_size - 25)
        self.line_edit.setFont(font)
        #唤起时窗口保持在所有其他窗口的顶部
        self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
        #窗口无边框和标题栏
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        layout = QVBoxLayout()
        layout.setSpacing(0)
        layout.addWidget(self.line_edit)
        self.setLayout(layout)
       



    def center(self):
        # 获取屏幕的几何信息
        screen = QDesktopWidget().screenGeometry()
        # 获取窗口的几何信息
        window_size = self.geometry()
        # 计算居中的位置
        x = (screen.width() - window_size.width()) / 2
        y = (screen.height() - window_size.height()) / 2
        # 设置窗口的位置
        self.move(x, y)

   只构建了一个文本框用于搜索剪切板的内容

二、实现功能
    系统托盘
class ClipboardViewerApp(QApplication):

     def __init__(self, sys_argv):
        super().__init__(sys_argv)
        self.setApplicationName("剪切板内容查看器")
        self.viewer = ClipboardViewer()
        # 设置系统托盘图标和菜单
        self.tray_icon = QSystemTrayIcon(QIcon(":/favicon.ico"), self)
        self.viewer.setWindowIcon(QIcon(":/favicon.ico"))
        self.tray_icon.setToolTip("剪切板内容查看器")
         # 添加右键菜单
        self.menu = QMenu()
        exit_action = QAction("退出", self)
        # 退出事件
        exit_action.triggered.connect(self.quit)
        self.tray_icon.setContextMenu(self.menu)
        self.tray_icon.activated.connect(self.on_tray_icon_activated)
        self.tray_icon.show()
    窗口失去焦点自动最小化托盘
class ClipboardViewer(QWidget):
    # 控制展示标识
    hidden_to_tray = True
    #信号
    sig_show_viewer = pyqtSignal()
    
     def __init__(self):
        super().__init__()
        self.initUI()

     def event(self, event):
        # 窗口事件失去焦点
        if event.type() == QEvent.WindowDeactivate:
            self.sig_show_viewer.emit()
        return super().event(event)


class ClipboardViewerApp(QApplication):

      def __init__(self, sys_argv):
           # ...代码省略
           self.viewer.sig_show_viewer.connect(self.showViewer)
       

      def showViewer(self):
        if self.viewer.hidden_to_tray:
            self.viewer.show()
            self.viewer.activateWindow()
            self.viewer.hidden_to_tray = False
        else:
            self.viewer.hide()
            self.viewer.hidden_to_tray = True
    快捷键唤起关闭 

(不能跟系统快捷键冲突 我这边设置的alt+x ps:mac的commond键按习惯了。。)

class ClipboardViewerApp(QApplication):
    #热键信号
    sigkeyhot = pyqtSignal()

    def __init__(self, sys_argv):
       #。。。代码省略
       # 设置我们的自定义热键响应函数-窗口展示
       self.sigkeyhot.connect(self.showViewer)
       # 初始化热键
       self.hk_start =  SystemHotkey()
       # 绑定快捷键和对应的信号发送函数
       self.hk_start.register(('alt', 'x'), callback=lambda x:  self.sigkeyhot.emit())
输入框补全提示 和  补全提示如果有直接展示 

输入框提示可以使用QComboBox来做 但是对于cv工程师来说有这么一个场景我复制的一个字符串,然后我在复制另一个字符串,这时候我想使用第一次复制的字符串,我唤起剪切板窗口就能直接找到我要的文本,QComboBox必须输入提示词才能展示出来,一直找不到让他一直展示的属性,就自己实现了下这个功能

class ClipboardViewer(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

     def initUI(self):
        #。。代码省略
        # 设置一个列表框让他充当提示框
        self.list_widget = QListWidget()
        # 设置显示的选项数
        self.list_widget.setStyleSheet("""QListWidget{
border:1px solid gray; color:black; 
 border-radius: 5px;
 border: 1px solid #555555;
  background-color: #faf9f3;     /* 背景颜色 */
                           hover:background:skyblue; 

                           }
                           
}
    """)
      layout.addWidget(self.list_widget)


class ClipboardViewerApp(QApplication):
     def __init__(self, sys_argv):
        #让列表无值的时候不显示有值的话一直显示
        self.updateVisibility()

        clipboard = self.clipboard()
        # 监听剪切板变动
        clipboard.dataChanged.connect(self.change_deal)

     def updateVisibility(self):
        if self.viewer.list_widget.count() == 0:
            self.viewer.list_widget.setVisible(False)
        else:
            self.viewer.list_widget.setVisible(True)

     


     def change_deal(self):
        data = self.clipboard().mimeData()
        text = data.text()
        text = str(text)
        text = text.strip()
        # 判断文本是否存在历史记录里有就清掉
        if text in paseList:
            paseList.remove(text)
        # 最多20条历史记录
        if len(paseList) > 20:
            temp = paseList
            temp = temp[:19]
            paseList.clear()
            paseList.extend(temp)
        paseList.insert(0, text)
        # 每次清空列表在放进去
        self.viewer.list_widget.clear()
        self.viewer.list_widget.addItems(paseList)
        self.updateVisibility()


if __name__ == '__main__':
    #将复制的内容放在这个列表中
    paseList = []
键盘down键直接选择提示文字回车之前进行粘贴 
class ClipboardViewer(QWidget):
     enterHot = pyqtSignal()
    
     #窗口中键盘事件
     def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Down:
            # 按键时列表聚焦
            if self.list_widget.count() > 0:
                a = self.list_widget.currentIndex()
                index = a.row()
                index += 1
                if index == self.list_widget.count():
                    index = 0
                self.list_widget.setCurrentRow(index)
        if event.key() == QtCore.Qt.Key_Up:
            # 按键时列表聚焦
            if self.list_widget.count() > 0:
                a = self.list_widget.currentIndex()
                index = a.row()
                index -= 1
                if index < 0:
                    index = self.list_widget.count()-1
                if index == self.list_widget.count():
                    index = 0
                self.list_widget.setCurrentRow(index)
        if event.key() == QtCore.Qt.Key_Return:
            # 回车时发送信号
            self.enterHot.emit()
        return super().keyPressEvent(event)

class ClipboardViewerApp(QApplication):

      def __init__(self, sys_argv):
          #接收回车信号
          self.viewer.enterHot.connect(self.enterHotEvent)
      

       def enterHotEvent(self):
         date = self.viewer.list_widget.currentIndex().data()
         self.showViewer()
         # 模拟键盘按键组合
         pyperclip.copy(date)
         pyautogui.hotkey('ctrl', 'v')  # 模拟复制操作
pyQt打包成exe文件后多次打开exe程序只存活一个应用程序 
if __name__ == '__main__':

    paseList = []

    try:

        serverName = 'pasteServer'
        socket = QLocalSocket()
        socket.connectToServer(serverName)
        # 如果连接成功,表明server已经存在,当前已有实例在运行
        if socket.waitForConnected(500):
            pass
        else:
            app = ClipboardViewerApp(sys.argv)
            localServer = QLocalServer()  # 没有实例运行,创建服务器
            localServer.listen(serverName)
            localServer.newConnection.connect(app.showViewer)
            # 处理其他
            sys.exit(app.exec_())

    except:
        pass
三、界面展示效果: 

四、总结

界面有点丑O(∩_∩)O哈哈~ 主打一个能用就行  这期间也学到了许多关于Qt的知识 以后有机会继续坐点小工具

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值