likes
comments
collection
share

JavaFx 全局快捷键和监听剪切板功能实现(Kotlin)

作者站长头像
站长
· 阅读数 27

全局快捷键实现

最近整款工具需要用到全局快捷键,搜集了下网上的资料,发现有个JIntellitype库可以用来实现全局快捷键,下面记录下个人的使用

JIntellitype只适用windows的全局快捷键绑定,并不能全平台支持!!

注:本文使用的Kotlin,Java版的可以参考下JIntellitype的文档,

PS:后面我还发现有个jnativehook的库,在github上的:star:还挺多的,文档介绍其支持全平台的

然后使用文档啥也没有,参考的示例整了些没能成功就放弃了,其例子也是给的swing,而不是javafx,我自己摸索了半天还报错,就放弃了

使用

吐槽下,这个作者写的文档使用说明其实有点不是太明确,第一遍看过去人都懵的...

而且看网上的资料,都是自己去拷贝jar包,实际上作者已经把jar包发布在maven中央仓库了,根本没有必要手动去下载

JIntellitype此库好像支持JDK8和JDK9

1.导入依赖

<dependency>
    <groupId>com.melloware</groupId>
    <artifactId>jintellitype</artifactId>
    <version>1.4.0</version>
</dependency>

2.注册按键

我们以全局注册个Ctrl+Shift+G的快捷键为例

//这里必须是大写字母
val keyCode = 'G'.toInt() //这个其实是ASCII码(G的ASCII码数值为71)

//注意这个1,下面第三步的回调函数会根据这个来进行判断
JIntellitype.getInstance().registerHotKey(1, JIntellitype.MOD_CONTROL + JIntellitype.MOD_SHIFT, keyCode)
  • JIntellitype.MOD_CONTROL Ctrl键
  • JIntellitype.JIntellitype.MOD_SHIFT Shift键
  • JIntellitype.MOD_ALT Alt键
  • JIntellitype.MOD_WIN Windows键

3.注册按键监听器

JIntellitype.getInstance().addHotKeyListener {
    if (it == 1) {
        //写上触发快捷键后的处理逻辑
        println("已按下快捷键")
    }
}

注意,addHotKeyListener中回调函数会返回一个数字,这个数字是用来区分不同的快捷键的,是在上面注册按键的步骤中定义的

PS:如果想取消注册,使用unregisterHotKey()方法即可,如下面所示

//1就是上面注册用的
JIntellitype.getInstance().unregisterHotKey(1)

4.下载dll文件

点击dll文件下载

上面我把32位和64位的dll文件都打包上传到蓝奏云了,各位需要自取

下载下来后需要把文件放在指定路径中,如下图所示

JavaFx 全局快捷键和监听剪切板功能实现(Kotlin)

测试

随便在一个地方,按下设置好的快捷键就会成功触发

JavaFx 全局快捷键和监听剪切板功能实现(Kotlin)

监听剪切板实现

软件有个需求,想要实现监听剪切板的内容,若内容符合预期,则进行相关的操作,就可以免去用户手动粘贴的操作,提供软件的用户体验感

比如说之前我的一款下载小说的软件,复制小说的地址后,实现自动解析功能

本篇代码以Kotlin为主,Java实现也是类似,各位可以参考下

实现

本质上是利用一个剪切板的setContents方法,可以传递个监听接口ClipboardOwner

定义个类实现此接口ClipboardOwner,实现此接口定义个的方法lostOwnership

class SystemClipboardMonitor : ClipboardOwner {
    private val clipboard = Toolkit.getDefaultToolkit().systemClipboard
    //定义个变量,用来控制监听的开关
    private var isOpenListener = true

    //定义个接口回调,方便在使用的时候回调
    var listener: GlobalClipBoardListener? = null

    init {
        clipboard.setContents(clipboard.getContents(null), this)
    }

    override fun lostOwnership(clipboard: Clipboard?, contents: Transferable?) {
        
        try {
            Thread.sleep(1)
            var text = ""
            if (clipboard?.isDataFlavorAvailable(DataFlavor.stringFlavor) == true) {
                text = clipboard.getData(DataFlavor.stringFlavor).toString()
            }
            clipboard?.setContents(clipboard.getContents(null), this)
            if (isOpenListener) {
                listener?.onCopy(text, clipboard, contents)
            }
        } catch (e: IllegalStateException) {
            //有时候会出现剪切板被占用就会出现此异常
        }
    }

    /**
     * 移除监听
     *
     */
    fun stopListen() {
        isOpenListener = false
    }

    /**
     * 开启监听
     *
     */
    fun startListen() {
        isOpenListener = true
    }

    fun addClipboardListener(listener: GlobalClipBoardListener) {
        this.listener = listener
    }
}

interface GlobalClipBoardListener {
    fun onCopy(text: String?, clipboard: Clipboard?, contents: Transferable?)
}

使用

使用的话,新建一个SystemClipboardMonitor对象即可,之后设置你的监听操作,如下面所示

val monitor = SystemClipboardMonitor()
monitor.addClipboardListener(object :GlobalClipBoardListener{
    override fun onCopy(text: String?, clipboard: Clipboard?, contents: Transferable?) {
        //这里可以加上相关的判断来测试内容是否是符合自己的定义的条件才触发对应的操作
        println("已监听到方法...")
        println(text)
    }
})

考虑到会有设置的选项,就定义了两个开关方法,可以在需要的时候进行开关的设置(默认是剪切板的监听就是开启的)

//开启监听
monitor.stopListen()

//停止监听
monitor.startListen()

参考