我是靠谱客的博主 潇洒日记本,最近开发中收集的这篇文章主要介绍使用python实现桌面输入框,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

有必要说下,这个输入框可以用来做什么?

其实,这个输入框只是一个便捷操作入口,具体的业务逻辑是可以自由定制的。

比如我就开发过一个脚本管理工具,这个输入框作为执行脚本的便捷补充方式,如在输入框里键入show chrome并回车,就可以把chrome浏览器快速调出来,整个过程是不需要鼠标参与的,相信在使用习惯之后,某些情况下应该会比鼠标操作更加方便高效。

      

当然,你完全可以用来做些更有趣的事情,下面是具体的实现细节。

开发环境:

     Platform:Windows-10

     Python:2.7

     PyInstaller:3.5

    

涉及的主要技术:

    Tkinter :python gui

    pywin32 :调用windows的API

    multiprocessing:进行多进程通信

打包运行:

pyinstaller.exe -F xxx.py会在./dist目录下生成xxx.exe可执行文件,双击运行即可

实现源码:

# coding=utf-8
import os
import sys
import time
import subprocess
import multiprocessing
from multiprocessing import Process, Manager
from Tkinter import Tk,Entry,Frame,Toplevel,Menu
from Tkinter import BOTH,YES
from tkFont import Font
import pythoncom
import pyHook
from win32api import GetSystemMetrics
from win32con import SM_CMONITORS,SM_CXVIRTUALSCREEN
import ctypes
# 记录上次敲击的键
last_key = None
def get_screens_info():
""" 获取屏幕的分辨率 支持双屏 """
monitors_info = []
# 主流的显示器分辨率
screen_support = {
1280:720,
1920:1080,
2560:1440,
3840:2160,
4096:2160
}
# 获取显示器数量
monitor_count = GetSystemMetrics(SM_CMONITORS)
if monitor_count == 1:
# 解决因dpi问题导致获取屏幕宽度不准确
ctypes.windll.shcore.SetProcessDpiAwareness(2)
main_screen_width = GetSystemMetrics(0)
monitors_info.append({'width':main_screen_width,'height':screen_support.get(main_screen_width)})
elif monitor_count == 2:
v_screen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN)
# 解决因dpi问题导致获取屏幕宽度不准确
ctypes.windll.shcore.SetProcessDpiAwareness(2)
main_screen_width = GetSystemMetrics(0)
monitors_info.append({'width':main_screen_width, 'height':screen_support.get(main_screen_width)})
sub_screen_width = v_screen_width-main_screen_width
monitors_info.append({'width':sub_screen_width, 'height':screen_support.get(sub_screen_width)})
else:
print "More than two display monitors are not supported"
sys.exit()
return monitors_info
class POINT(ctypes.Structure):
""" 表示屏幕上某个点(x,y) """
_fields_ = [("x", ctypes.c_ulong), ("y", ctypes.c_ulong)]
def get_mouse_pos():
""" 获取鼠标位置 """
point = POINT()
ctypes.windll.user32.GetCursorPos(ctypes.byref(point))
return {'x':point.x, 'y':point.y}
class App(Tk):
""" 输入框窗体类 """
def __init__(self):
""" 初始化窗体 """
Tk.__init__(self)
self.create_ui()
def create_ui(self):
self.title('Input GUI')
# 去掉窗体边框以及最小化、最大化、关闭这几个
self.overrideredirect(True)
# 置顶窗体
self.wm_attributes('-topmost',1)
# 设置窗体透明度
self.attributes("-alpha", 0.8)
# 获取屏幕信息
screens_info = get_screens_info()
if len(screens_info) == 1: # 只有一个屏幕
screen1_info = screens_info[0]
width = screen1_info['width']*0.33
height = screen1_info['height']*0.06
pos_x = screen1_info['width']*(1-0.33)/2
pos_y = screen1_info['height']*(1-0.06)/2
elif len(screens_info) == 2: # 有两个屏幕
# 获取鼠标所在屏幕位置
mouse_pos = get_mouse_pos()
mouse_pos_x = mouse_pos['x']
screen1_info = screens_info[0]
screen1_width = screen1_info['width']
if mouse_pos_x > screen1_width: # 当前鼠标在第二屏幕
screen2_info = screens_info[1]
# 计算输入框的宽度和高度
width = screen2_info['width']*0.33
height = screen2_info['height']*0.06
# 将输入框居中
pos_x = screen1_info['width']+(screen2_info['width']-width)/2
pos_y = (screen2_info['height']-height)/2
print pos_x,pos_y
else: # 当前鼠标在第一屏幕
width = screen1_info['width']*0.33
height = screen1_info['height']*0.06
pos_x = screen1_info['width']*(1-0.33)/2
pos_y = screen1_info['height']*(1-0.06)/2
# 设置布局和位置
align = '%dx%d+%d+%d' % (width, height, pos_x, pos_y)
self.geometry(align)
# 设置窗口是否可变长宽,True:可变,False:不可变
self.resizable(width=False, height=True)
# 设置输入框字体样式
self.font = Font(family="Microsoft YaHei", size=32)
# 创建一个单行文本输入框组件
self.entry = Entry(self, bd=0, font=self.font, insertbackground='red', insertofftime=600, insertontime=600)
# 绑定键入回车和失去焦点时触发的函数
self.entry.bind('<Return>', self.on_return)
self.entry.bind('<FocusOut>', self.hide)
# fill=BOTH:填充水平和竖直方向, expand=YES:扩展整个空白区
self.entry.pack(fill=BOTH, expand=YES)
self.entry.after(1, lambda: self.entry.focus_force())
# 在第1个位置插入一个空格
self.entry.insert(0,"
")
def on_return(self,event):
# === 这里可以定制具体的业务逻辑 ===
print "execute: " + self.entry.get()
# 销毁窗体,实现窗体消失的效果
self.destroy()
def hide(self,event):
# 销毁窗体,实现窗体消失的效果
self.destroy()
# 桌面输入框窗体变量
app = None
def new_app():
""" 创建一个新的输入框窗体 """
app = App()
# 显示窗体,并开始事件循环
app.mainloop()
class Listener:
""" 键盘事件监听器 """
def __init__(self, queue):
self.queue = queue
def onKeyboardEvent(self, event):
""" 处理键盘事件,实现双击右侧Ctrl键创建桌面输入框的效果 """
this_key = event.Key
# 双击键盘右侧Ctrl键
if last_key == 'Rcontrol':
if this_key == 'Rcontrol':
# 如果连续两次敲击右侧Ctrl键,将发送消息通知主进程创建桌面输入框
self.queue.put(1, block=False)
self.key_last(None)
else:
self.key_last(this_key)
else:
self.key_last(this_key)
return True
def key_last(self, this_key):
""" 记下上次键盘输入 """
global last_key
last_key = this_key
def start(self):
""" 启动事件监听器 """
# 创建一个“钩子”管理对象
hm = pyHook.HookManager()
# 监听键盘事件
hm.KeyDown = self.onKeyboardEvent
# 设置键盘“钩子”
hm.HookKeyboard()
# 进入循环,如不手动关闭,程序将一直处于监听状态
pythoncom.PumpMessages()
def new_listener(queue):
""" 创建并启动一个键盘事件监听器 """
listener = Listener(queue)
listener.start()
if __name__ == "__main__":
""" 运行两个进程 主进程负责创建输入框,键盘事件监听进程负责监听键盘事件并在满足条件时通过队列通知主进程创建输入框 """
multiprocessing.freeze_support()
# 创建一个队列,键盘事件监听进程与主进程之间通过队列进行通信
queue = Manager().Queue(10)
# 创建一个独立的进程用来监听键盘事件
p = Process(name="Hook-Helper", target=new_listener, args={queue})
# 启动键盘事件监听进程
p.start()
# 主进程轮询接收创建输入框窗体的消息通知
while True:
if queue.get():
p = Process(name="My-input", target=new_app)
p.start()
p.join()

欢迎关注我微信公众号《倔强的文哥》(一个表面冷酷,内心热乎的互联网码农),不定时分享各种Java技术经验、面试热题、Python实用小技巧。  

最后

以上就是潇洒日记本为你收集整理的使用python实现桌面输入框的全部内容,希望文章能够帮你解决使用python实现桌面输入框所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(74)

评论列表共有 0 条评论

立即
投稿
返回
顶部