单例模式

  1. # -*- coding: utf-8 -*-
  2. import functools
  3. import tkinter as tk
  4. def just_one_instance(func):
  5. """
  6. 保证只能运行一个Python实例,方法是程序运行时监听一个特定端口,如果失败则说明已经有实例在跑。
  7. """
  8. @functools.wraps(func)
  9. def f(*args, **kwargs):
  10. import socket
  11. try:
  12. # 全局属性,否则变量会在方法退出后被销毁
  13. global s
  14. s = socket.socket()
  15. host = socket.gethostname()
  16. s.bind((host, 60124))
  17. except:
  18. print('程序已经在运行了')
  19. return None
  20. return func(*args, **kwargs)
  21. return f
  22. @just_one_instance
  23. def run():
  24. tk.Tk().mainloop()
  25. if __name__ == '__main__':
  26. run()

单例模式下激活窗口

当运行了一个tkinter程序后,重新运行程序,使用上面代码可以拦住运行,那如何激活已经运行了的那个应用,让它跳出到桌面上呢?

改造单例代码

  1. def just_one_instance(func):
  2. @functools.wraps(func)
  3. def f(*args, **kwargs):
  4. try:
  5. # 全局属性,否则变量会在方法退出后被销毁
  6. global s
  7. s = socket.socket()
  8. host = socket.gethostname()
  9. s.bind((host, 60124))
  10. except:
  11. # 拦截后,这里发送一段socket指令
  12. tcpCliSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  13. tcpCliSock.connect(('127.0.0.1', 60124))
  14. tcpCliSock.send("show".encode())
  15. tcpCliSock.close()
  16. return None
  17. return func(*args, **kwargs)
  18. return f

tkinter代码

  1. # 监听重新打开,激活主页面
  2. self.recv_msg_thread = threading.Thread(target=self.recv_msg)
  3. self.recv_msg_thread.setDaemon(True)
  4. self.recv_msg_thread.start()
  5. def recv_msg(self):
  6. tcpSerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  7. tcpSerSock.bind(('127.0.0.1', 60124))
  8. tcpSerSock.listen(5)
  9. while True:
  10. tcpCliSock, addr = tcpSerSock.accept()
  11. while True:
  12. data = tcpCliSock.recv(1024)
  13. if not data:
  14. break
  15. self.root.deiconify()
  16. self.root.wm_attributes('-topmost', 1)
  17. self.root.wm_attributes('-topmost', 0)
  18. tcpCliSock.close()