
import io
import time
import socket
import pyautogui
def capture_and_send_image():
while True:
try:
# pil_image = Image.new("RGB", (160, 90), (255, 255, 255))
# # 截图
screenshot = pyautogui.screenshot()
# # 缩小图片
new_size = (screenshot.width // 20, screenshot.height // 20)
resized_screenshot = screenshot.resize(new_size)
# 将图片转换为字节流
img_byte_arr = io.BytesIO()
resized_screenshot.save(img_byte_arr, format='PNG')
img_byte_arr = img_byte_arr.getvalue()
# 发送数据
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
s.connect(('localhost', 10000))
s.sendall(img_byte_arr)
s.close()
except Exception as e:
print(f"发送端发生错误: {e}")
# 暂停一段时间,避免过于频繁发送
time.sleep(0.0001)
if __name__ == "__main__":
while True:
try:
capture_and_send_image()
except Exception as e:
print(e)
time.sleep(1)
print("重新连接")
import io
import time
import socket
import weakref
import threading
import tkinter as tk
from PIL import Image, ImageTk
start_time = None
network_flux = 0
one_second_data = 0
fps_times = 0
fps = 0
all_times = 0
pil_data = None
# 获取网速
def network(KB):
global start_time, network_flux, one_second_data, fps_times, fps
network_flux += KB
if start_time is None:
start_time = time.time()
return
if time.time() - start_time > 2: # 两秒更新一次
one_second_data = f"{network_flux / 1024 / (time.time() - start_time):.1f} kb/s"
fps = f"{fps_times / (time.time() - start_time):.1f} fps/s"
print(one_second_data)
network_flux = KB
start_time = None
fps_times = 0
# 绘画层
class DraggableImage:
def __init__(self):
self.root = tk.Tk()
self.root.title("Image")
self.bg_color = '#F0F0F0' # 透明
self.root.config(bg=self.bg_color) # 背景色
self.root.wm_attributes('-transparentcolor', self.bg_color) # 透明
self.root.wm_attributes("-topmost", True) # 置顶
# self.root.overrideredirect(True) # 无边框
self.drag_data = {"x": 0, "y": 0, "is_dragging": False}
self.tk_image_ref = None # 使用弱引用
self.canvas = tk.Canvas(self.root)
self.canvas.pack()
self.time_label = tk.Label(self.root, bg=self.bg_color, fg='white', font=('Arial', 12))
self.time_label.pack(side=tk.TOP)
self.fps_label = tk.Label(self.root, bg=self.bg_color, fg='white', font=('Arial', 12))
self.fps_label.pack(side=tk.TOP)
self.image_id = None
self.img = None
# 存储当前显示的图像对象
self.current_tk_image = None
# 鼠标事件绑定
self.canvas.bind("<ButtonPress-1>", self.on_press)
self.canvas.bind("<B1-Motion>", self.on_drag)
self.canvas.bind("<ButtonRelease-1>", self.on_release)
self.canvas.bind("<Button-3>", self.on_right_click)
# 初始化图像对象
self.init_image()
# 图片数据获取
self.start_receive_image()
# 数据更新
self.update_time_and_fps()
# 初始化图像对象
def init_image(self):
# 创建一个初始的空白 PIL 图像
pil_image = Image.new("RGB", (160, 90), (255, 255, 255))
# 确保创建一个初始的 ImageTk.PhotoImage 对象
self.current_tk_image = ImageTk.PhotoImage(pil_image)
self.image_id = self.canvas.create_image(0, 0, anchor=tk.NW, image=self.current_tk_image)
# 数据更新
def start_receive_image(self):
thread = threading.Thread(target=self.receive_image)
thread.start()
# 获取图片数据
def receive_image(self):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
s.bind(('localhost', 10000))
s.listen(1)
while True:
try:
conn, addr = s.accept()
img_data = b""
# 使用 makefile 提高接收性能
with conn.makefile('rb') as f:
while True:
data = f.read(1024)
if not data:
break
img_data += data
conn.close()
network(len(img_data))
global all_times,pil_data
all_times += 1
if all_times % 100 == 0:
print(all_times)
# 全局数据
pil_data = img_data
# 使用 root.after 将更新操作调度到主线程
self.root.after(0, lambda: self.update_image(img_data))
except Exception as e:
print(f"接收端发生错误: {e}")
# 获取图片数据
def update_image(self, img_data):
global fps_times
fps_times += 1
if fps_times%100 == 0:
self.canvas.delete("all")
pil_image = Image.open(io.BytesIO(img_data))
original_width, original_height = pil_image.size
# 创建一个新的 ImageTk.PhotoImage 对象
new_tk_image = ImageTk.PhotoImage(pil_image)
# 仅更新图像,而不是销毁并重建 canvas
self.canvas.config(width=original_width, height=original_height)
# 使用 after 方法更新图像
self.root.after(0, lambda: self._update_image_on_canvas(new_tk_image))
# 更新图片
def _update_image_on_canvas(self, new_tk_image):
# 在主线程中更新图像
if self.image_id:
old_image = self.canvas.itemcget(self.image_id, 'image')
if old_image:
# 删除旧的图像对象
self.canvas.delete(self.image_id)
# 显式删除对象引用
del old_image
self.image_id = self.canvas.create_image(0, 0, anchor=tk.NW, image=new_tk_image)
else:
self.image_id = self.canvas.create_image(0, 0, anchor=tk.NW, image=new_tk_image)
self.current_tk_image = new_tk_image
self.img = weakref.ref(self.current_tk_image) # 弱引用释放
# self.root.tk.call('image', 'delete', self.current_tk_image)
# 网速和帧率
def update_time_and_fps(self):
global one_second_data, fps
self.time_label.config(text=one_second_data)
self.fps_label.config(text=fps)
self.root.after(2000, self.update_time_and_fps)
# 右键点击销毁
def on_right_click(self, event):
self.canvas.destroy()
self.root.destroy()
raise 0
def on_press(self, event):
# 记录鼠标按下时的位置
self.drag_data["x"] = event.x_root
self.drag_data["y"] = event.y_root
self.drag_data["is_dragging"] = True
def on_drag(self, event):
if self.drag_data["is_dragging"]:
# 计算鼠标移动的偏移量
dx = event.x_root - self.drag_data["x"]
dy = event.y_root - self.drag_data["y"]
# 移动窗口
self.root.geometry(f"+{self.root.winfo_x() + dx}+{self.root.winfo_y() + dy}")
# 更新鼠标位置
self.drag_data["x"] = event.x_root
self.drag_data["y"] = event.y_root
def on_release(self, event):
# 释放时清除拖动状态
self.drag_data["is_dragging"] = False
if __name__ == "__main__":
app = DraggableImage()
app.root.mainloop()
import io
import time
import socket
import pyautogui
def capture_and_send_image():
while True:
try:
# pil_image = Image.new("RGB", (160, 90), (255, 255, 255))
# # 截图
screenshot = pyautogui.screenshot()
# # 缩小图片
new_size = (screenshot.width // 20, screenshot.height // 20)
resized_screenshot = screenshot.resize(new_size)
# 将图片转换为字节流
img_byte_arr = io.BytesIO()
resized_screenshot.save(img_byte_arr, format='PNG')
img_byte_arr = img_byte_arr.getvalue()
# 发送数据
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
s.connect(('localhost', 10000))
s.sendall(img_byte_arr)
s.close()
except Exception as e:
print(f"发送端发生错误: {e}")
# 暂停一段时间,避免过于频繁发送
time.sleep(0.0001)
if __name__ == "__main__":
while True:
try:
capture_and_send_image()
except Exception as e:
print(e)
time.sleep(1)
print("重新连接")
import io
import time
import socket
import weakref
import threading
import tkinter as tk
from PIL import Image, ImageTk
start_time = None
network_flux = 0
one_second_data = 0
fps_times = 0
fps = 0
all_times = 0
pil_data = None
# 获取网速
def network(KB):
global start_time, network_flux, one_second_data, fps_times, fps
network_flux += KB
if start_time is None:
start_time = time.time()
return
if time.time() - start_time > 2: # 两秒更新一次
one_second_data = f"{network_flux / 1024 / (time.time() - start_time):.1f} kb/s"
fps = f"{fps_times / (time.time() - start_time):.1f} fps/s"
print(one_second_data)
network_flux = KB
start_time = None
fps_times = 0
# 绘画层
class DraggableImage:
def __init__(self):
self.root = tk.Tk()
self.root.title("Image")
self.bg_color = '#F0F0F0' # 透明
self.root.config(bg=self.bg_color) # 背景色
self.root.wm_attributes('-transparentcolor', self.bg_color) # 透明
self.root.wm_attributes("-topmost", True) # 置顶
# self.root.overrideredirect(True) # 无边框
self.drag_data = {"x": 0, "y": 0, "is_dragging": False}
self.tk_image_ref = None # 使用弱引用
self.canvas = tk.Canvas(self.root)
self.canvas.pack()
self.time_label = tk.Label(self.root, bg=self.bg_color, fg='white', font=('Arial', 12))
self.time_label.pack(side=tk.TOP)
self.fps_label = tk.Label(self.root, bg=self.bg_color, fg='white', font=('Arial', 12))
self.fps_label.pack(side=tk.TOP)
self.image_id = None
self.img = None
# 存储当前显示的图像对象
self.current_tk_image = None
# 鼠标事件绑定
self.canvas.bind("<ButtonPress-1>", self.on_press)
self.canvas.bind("<B1-Motion>", self.on_drag)
self.canvas.bind("<ButtonRelease-1>", self.on_release)
self.canvas.bind("<Button-3>", self.on_right_click)
# 初始化图像对象
self.init_image()
# 图片数据获取
self.start_receive_image()
# 数据更新
self.update_time_and_fps()
# 初始化图像对象
def init_image(self):
# 创建一个初始的空白 PIL 图像
pil_image = Image.new("RGB", (160, 90), (255, 255, 255))
# 确保创建一个初始的 ImageTk.PhotoImage 对象
self.current_tk_image = ImageTk.PhotoImage(pil_image)
self.image_id = self.canvas.create_image(0, 0, anchor=tk.NW, image=self.current_tk_image)
# 数据更新
def start_receive_image(self):
thread = threading.Thread(target=self.receive_image)
thread.start()
# 获取图片数据
def receive_image(self):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
s.bind(('localhost', 10000))
s.listen(1)
while True:
try:
conn, addr = s.accept()
img_data = b""
# 使用 makefile 提高接收性能
with conn.makefile('rb') as f:
while True:
data = f.read(1024)
if not data:
break
img_data += data
conn.close()
network(len(img_data))
global all_times,pil_data
all_times += 1
if all_times % 100 == 0:
print(all_times)
# 全局数据
pil_data = img_data
# 使用 root.after 将更新操作调度到主线程
self.root.after(0, lambda: self.update_image(img_data))
except Exception as e:
print(f"接收端发生错误: {e}")
# 获取图片数据
def update_image(self, img_data):
global fps_times
fps_times += 1
if fps_times%100 == 0:
self.canvas.delete("all")
pil_image = Image.open(io.BytesIO(img_data))
original_width, original_height = pil_image.size
# 创建一个新的 ImageTk.PhotoImage 对象
new_tk_image = ImageTk.PhotoImage(pil_image)
# 仅更新图像,而不是销毁并重建 canvas
self.canvas.config(width=original_width, height=original_height)
# 使用 after 方法更新图像
self.root.after(0, lambda: self._update_image_on_canvas(new_tk_image))
# 更新图片
def _update_image_on_canvas(self, new_tk_image):
# 在主线程中更新图像
if self.image_id:
old_image = self.canvas.itemcget(self.image_id, 'image')
if old_image:
# 删除旧的图像对象
self.canvas.delete(self.image_id)
# 显式删除对象引用
del old_image
self.image_id = self.canvas.create_image(0, 0, anchor=tk.NW, image=new_tk_image)
else:
self.image_id = self.canvas.create_image(0, 0, anchor=tk.NW, image=new_tk_image)
self.current_tk_image = new_tk_image
self.img = weakref.ref(self.current_tk_image) # 弱引用释放
# self.root.tk.call('image', 'delete', self.current_tk_image)
# 网速和帧率
def update_time_and_fps(self):
global one_second_data, fps
self.time_label.config(text=one_second_data)
self.fps_label.config(text=fps)
self.root.after(2000, self.update_time_and_fps)
# 右键点击销毁
def on_right_click(self, event):
self.canvas.destroy()
self.root.destroy()
raise 0
def on_press(self, event):
# 记录鼠标按下时的位置
self.drag_data["x"] = event.x_root
self.drag_data["y"] = event.y_root
self.drag_data["is_dragging"] = True
def on_drag(self, event):
if self.drag_data["is_dragging"]:
# 计算鼠标移动的偏移量
dx = event.x_root - self.drag_data["x"]
dy = event.y_root - self.drag_data["y"]
# 移动窗口
self.root.geometry(f"+{self.root.winfo_x() + dx}+{self.root.winfo_y() + dy}")
# 更新鼠标位置
self.drag_data["x"] = event.x_root
self.drag_data["y"] = event.y_root
def on_release(self, event):
# 释放时清除拖动状态
self.drag_data["is_dragging"] = False
if __name__ == "__main__":
app = DraggableImage()
app.root.mainloop()