当前位置:首页>python>《还在用HDMI线投屏?Python一键局域网无线投屏,太方便了!》

《还在用HDMI线投屏?Python一键局域网无线投屏,太方便了!》

  • 2026-10-11 07:49:41
《还在用HDMI线投屏?Python一键局域网无线投屏,太方便了!》

“带你横跨办公自动化的数据江海”

@摸鱼

前言

关于摸鱼

(

ABOUT MOYU

)

闻道有先后,术业有专攻。

各位大佬朋友们好!

~我依旧是你们的老朋友摸鱼~

在职场摸爬滚打的这十多年里,我用Python悄悄干了不少“正事”——不知不觉攒下了一整套办公自动化的实用项目技巧。去年10月初创立了公众号 「码海听潮」 ,初衷很简单:把重复的劳动交给代码,把摸鱼的时间留给生活。

目前已经吭哧吭哧更新了100多篇原创文章,每一篇都是实操干货,不讲虚的,只聊怎么用代码真正解放双手,帮大家早点下班、准点摸鱼

好了,多了不说,少了不唠,今天给大佬们分享一款局域网多台电脑投屏小工具

《办公工具成品展示:》

《该办公工具核心功能亮点:》

01

 亮点1:现代化高颜值UI

      • PyQt6优雅的QSS样式表

      • 响应式布局,窗口自适应

      • 深色日志区域,护眼且专业

      • 按钮悬停、按下状态反馈

      02

       亮点2:架构设计,轻量级UDP广播方案

        • 无需中心服务器,点对点直连

        • 使用广播地址 255.255.255.255,接收端即插即用

        • 避免了复杂的服务发现机制,局域网内自动发现

        03

        亮点3:鼠标光标实时同步

        • 在第一个分片中嵌入鼠标坐标(屏幕绝对坐标)

        • 接收端等比例映射到显示窗口

        • 绘制红色光晕光标效果,视觉醒目

        《该办公工具代码展示:》

        下面,我就用python代码让各位大佬见识一下,什么叫"传统文化"遇上"赛博效率"

        import sysfrom PyQt6.QtWidgets import (    QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,    QLabel, QPushButton, QTextEdit, QGroupBox, QGraphicsView, QGraphicsScene,    QGraphicsTextItem)from PyQt6.QtCore import Qt, QRectFfrom PyQt6.QtGui import QFont, QColor, QPainter, QImage, QPixmapclass BroadcastReceiver(QMainWindow):    def __init__(self, broadcast_port=19895):        super().__init__()        self.broadcast_port = broadcast_port        # 设置窗口        self.setWindowTitle("局域网投屏工具 - 接收端(欢迎关注微信公众号:码海听潮)")        self.setFixedSize(800, 600)        self.setStyleSheet(self._get_stylesheet())        # 创建界面        self._setup_ui()    def _get_stylesheet(self):        """返回样式表"""        return """            QMainWindow {                background-color: #f5f7fa;            }            QWidget {                background-color: #f5f7fa;                font-family: 'Microsoft YaHei', '微软雅黑', sans-serif;            }            QGroupBox {                font-size: 13px;                font-weight: bold;                color: #2c3e50;                border: 1px solid #dcdde1;                border-radius: 8px;                margin-top: 12px;                padding: 16px 12px 12px 12px;                background-color: #ffffff;            }            QGroupBox::title {                subcontrol-origin: margin;                subcontrol-position: top left;                padding: 0 8px;                background-color: #ffffff;            }            QLabel {                color: #2c3e50;                font-size: 13px;                background-color: transparent;            }            QPushButton {                border-radius: 6px;                padding: 8px 16px;                font-size: 12px;                font-weight: bold;                color: white;                border: none;                min-width: 100px;            }            QPushButton#acceptBtn {                background-color: #27ae60;            }            QPushButton#acceptBtn:hover {                background-color: #2ecc71;            }            QPushButton#acceptBtn:pressed {                background-color: #219a52;            }            QPushButton#acceptBtn:disabled {                background-color: #bdc3c7;            }            QPushButton#rejectBtn {                background-color: #e74c3c;            }            QPushButton#rejectBtn:hover {                background-color: #c0392b;            }            QPushButton#rejectBtn:pressed {                background-color: #a93226;            }            QPushButton#rejectBtn:disabled {                background-color: #bdc3c7;            }            QTextEdit {                border: none;                border-radius: 6px;                padding: 10px;                font-family: 'Consolas', 'Courier New', monospace;                font-size: 12px;                background-color: #2c3e50;                color: #ecf0f1;            }            QTextEdit:focus {                border: 1px solid #3498db;            }            QGraphicsView {                border: 1px solid #dcdde1;                border-radius: 6px;                background-color: #000000;            }        """    def _setup_ui(self):        """设置界面"""        central_widget = QWidget()        self.setCentralWidget(central_widget)        main_layout = QHBoxLayout(central_widget)        main_layout.setContentsMargins(20, 20, 20, 20)        main_layout.setSpacing(20)        # 左侧控制面板        left_panel = QWidget()        left_panel.setFixedWidth(320)        left_layout = QVBoxLayout(left_panel)        left_layout.setContentsMargins(0, 0, 0, 0)        left_layout.setSpacing(16)        # 连接信息组        info_group = QGroupBox("连接信息")        info_layout = QVBoxLayout(info_group)        info_layout.setSpacing(8)        self.port_label = QLabel(f"监听端口: {self.broadcast_port}")        self.port_label.setStyleSheet("font-size: 13px; font-weight: normal;")        info_layout.addWidget(self.port_label)        self.status_label = QLabel("状态: 等待投屏信号...")        self.status_label.setStyleSheet("color: #2980b9; font-size: 13px; font-weight: normal;")        info_layout.addWidget(self.status_label)        left_layout.addWidget(info_group)        # 投屏控制组        preview_group = QGroupBox("投屏控制")        preview_layout = QVBoxLayout(preview_group)        preview_layout.setSpacing(8)        self.preview_label = QLabel("等待连接...")        self.preview_label.setAlignment(Qt.AlignmentFlag.AlignCenter)        self.preview_label.setStyleSheet("color: #7f8c8d; font-size: 14px; padding: 1px;")        preview_layout.addWidget(self.preview_label)        # 倒计时标签        self.countdown_label = QLabel("")        self.countdown_label.setAlignment(Qt.AlignmentFlag.AlignCenter)        self.countdown_label.setStyleSheet("color: #e67e22; font-size: 48px; font-weight: bold;")        preview_layout.addWidget(self.countdown_label)        # 按钮区域        button_layout = QHBoxLayout()        button_layout.setSpacing(10)        self.accept_btn = QPushButton("✓ 接受投屏")        self.accept_btn.setObjectName("acceptBtn")        self.reject_btn = QPushButton("✗ 拒绝投屏")        self.reject_btn.setObjectName("rejectBtn")        button_layout.addWidget(self.accept_btn)        button_layout.addWidget(self.reject_btn)        preview_layout.addLayout(button_layout)        left_layout.addWidget(preview_group)        # 日志信息组        log_group = QGroupBox("日志信息")        log_layout = QVBoxLayout(log_group)        log_layout.setContentsMargins(0, 10, 0, 0)        self.log_area = QTextEdit()        self.log_area.setReadOnly(True)        self.log_area.setMinimumHeight(190)        log_layout.addWidget(self.log_area)        left_layout.addWidget(log_group)        # 右侧显示区域        right_panel = QWidget()        right_layout = QVBoxLayout(right_panel)        right_layout.setContentsMargins(0, 0, 0, 0)        # 显示视图        self.graphics_view = QGraphicsView()        self.graphics_view.setRenderHint(QPainter.RenderHint.Antialiasing)        self.graphics_view.setRenderHint(QPainter.RenderHint.SmoothPixmapTransform)        self.graphics_view.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)        self.graphics_view.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)        self.graphics_scene = QGraphicsScene()        self.graphics_view.setScene(self.graphics_scene)        # 设置视图背景为黑色        self.graphics_view.setStyleSheet("background-color: #000000; border: 2px solid #34495e; border-radius: 8px;")        right_layout.addWidget(self.graphics_view)        # 将面板添加到主布局        main_layout.addWidget(left_panel)        main_layout.addWidget(right_panel, 1)        # 初始显示提示文本        self._show_initial_hint()    def _show_initial_hint(self):        """显示初始提示文本"""        self.graphics_scene.clear()        hint_text = QGraphicsTextItem("等待投屏画面...")        hint_text.setDefaultTextColor(QColor("#7f8c8d"))        font = QFont("Microsoft YaHei", 16)        hint_text.setFont(font)        text_rect = hint_text.boundingRect()        scene_width = 400        scene_height = 300        x = (scene_width - text_rect.width()) / 2        y = (scene_height - text_rect.height()) / 2        hint_text.setPos(x, y)        self.graphics_scene.addItem(hint_text)        self.graphics_scene.setSceneRect(QRectF(0, 0, scene_width, scene_height))        self.hint_text_item = hint_text    def _update_hint_position(self):        """更新提示文本位置"""        if hasattr(self, 'hint_text_item') and self.hint_text_item.scene() is not None:            view_rect = self.graphics_view.viewport().rect()            scene_rect = QRectF(0, 0, view_rect.width(), view_rect.height())            self.graphics_scene.setSceneRect(scene_rect)            text_rect = self.hint_text_item.boundingRect()            x = (scene_rect.width() - text_rect.width()) / 2            y = (scene_rect.height() - text_rect.height()) / 2            self.hint_text_item.setPos(x, y)    def resizeEvent(self, event):        """窗口大小改变事件"""        super().resizeEvent(event)        from PyQt6.QtCore import QTimer        QTimer.singleShot(100, self._update_hint_position)if __name__ == "__main__":    port = int(sys.argv[1]) if len(sys.argv) > 1 else 19895    app = QApplication(sys.argv)    font = QFont("Microsoft YaHei", 10)    app.setFont(font)    receiver = BroadcastReceiver(broadcast_port=port)    receiver.show()    sys.exit(app.exec())

        通过上面Python自动化脚本,仅用几秒钟的时间就完成原需手动操作数小时甚至数天的工作任务。从最初准备手动人工机械操作的麻木到用python实现高效自动化的畅快,工作效率获得指数级提升,终于实现了不加班熬夜的自由!

        大佬们也可以举一反三,参照上面的代码思路根据自己工作中的实际情况来具体问题具体分析,实现自己定制化的需求。

        《该办公工具的应用场景:》

          这套工具特别适合:

          • 技术培训:讲师屏幕实时投屏

          • 会议演示:快速屏幕共享

          • 远程协助:实时查看对方屏幕操作

          • 教学监控:学生屏幕集中展示

          结语

          当Python遇见办公,牛马打工人终于笑出了猪叫声

          【职场人必看】每天早上一睁眼,想到又要面对:

          1.📊 堆积如山的Excel表格

          2.📑 机械重复的复制粘贴

          3.✍️ 永远改不完的各类文档

          4.诸如此类的更多........

          是不是连Ctrl+Alt+Delete的心都有了?

          别慌!别急,摸鱼这位“职场外挂”已经带着Python代码来拯救你了!

          感谢各位大佬观看,还望各位大佬抬抬贵手一键三连,多多关注点赞转发评论,大佬们的支持才是摸鱼孜孜不倦更新原创干货的动力!

          最新文章

          随机文章