单例模式
# -*- coding: utf-8 -*-
import functools
import tkinter as tk
def just_one_instance(func):
"""
保证只能运行一个Python实例,方法是程序运行时监听一个特定端口,如果失败则说明已经有实例在跑。
"""
@functools.wraps(func)
def f(*args, **kwargs):
import socket
try:
# 全局属性,否则变量会在方法退出后被销毁
global s
s = socket.socket()
host = socket.gethostname()
s.bind((host, 60124))
except:
print('程序已经在运行了')
return None
return func(*args, **kwargs)
return f
@just_one_instance
def run():
tk.Tk().mainloop()
if __name__ == '__main__':
run()
单例模式下激活窗口
当运行了一个tkinter程序后,重新运行程序,使用上面代码可以拦住运行,那如何激活已经运行了的那个应用,让它跳出到桌面上呢?
改造单例代码
def just_one_instance(func):
@functools.wraps(func)
def f(*args, **kwargs):
try:
# 全局属性,否则变量会在方法退出后被销毁
global s
s = socket.socket()
host = socket.gethostname()
s.bind((host, 60124))
except:
# 拦截后,这里发送一段socket指令
tcpCliSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpCliSock.connect(('127.0.0.1', 60124))
tcpCliSock.send("show".encode())
tcpCliSock.close()
return None
return func(*args, **kwargs)
return f
tkinter代码
# 监听重新打开,激活主页面
self.recv_msg_thread = threading.Thread(target=self.recv_msg)
self.recv_msg_thread.setDaemon(True)
self.recv_msg_thread.start()
def recv_msg(self):
tcpSerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpSerSock.bind(('127.0.0.1', 60124))
tcpSerSock.listen(5)
while True:
tcpCliSock, addr = tcpSerSock.accept()
while True:
data = tcpCliSock.recv(1024)
if not data:
break
self.root.deiconify()
self.root.wm_attributes('-topmost', 1)
self.root.wm_attributes('-topmost', 0)
tcpCliSock.close()