当前位置: 代码网 > it编程>前端脚本>Python > Python结合PyQt6实现屏幕截图工具(附源码)

Python结合PyQt6实现屏幕截图工具(附源码)

2026年08月07日 Python 我要评论
一、源码分享1、源码分享import sysimport osfrom pyqt6.qtwidgets import (qapplication, qmainwindow, qpushbutton,

一、源码分享

1、源码分享

import sys
import os
from pyqt6.qtwidgets import (qapplication, qmainwindow, qpushbutton, qwidget,
                             qvboxlayout, qlabel, qmessagebox, qdialog)
from pyqt6.qtgui import qscreen, qpixmap, qpainter, qcolor, qpen
from pyqt6.qtcore import qt, qrect, qpoint, qdatetime


class screenshotmask(qdialog):
    def __init__(self, full_screen_pix):
        super().__init__()
        self.full_pix = full_screen_pix
        # 全屏无边框置顶
        self.setwindowflags(
            qt.windowtype.framelesswindowhint
            | qt.windowtype.windowstaysontophint
        )
        self.setgeometry(0, 0, self.full_pix.width(), self.full_pix.height())
        self.setattribute(qt.widgetattribute.wa_translucentbackground)
        self.setmousetracking(true)

        self.start_pos = qpoint()
        self.end_pos = qpoint()
        self.is_drawing = false
        self.select_rect = qrect()
        self.result_pix = none

    def paintevent(self, event):
        painter = qpainter(self)
        # 底层原图
        painter.drawpixmap(self.rect(), self.full_pix)
        # 半透明遮罩
        painter.fillrect(self.rect(), qcolor(0, 0, 0, 130))

        if self.is_drawing:
            rect = qrect(self.start_pos, self.end_pos).normalized()
            # 选区清空遮罩
            painter.setcompositionmode(qpainter.compositionmode.compositionmode_clear)
            painter.fillrect(rect, qt.globalcolor.transparent)
            painter.setcompositionmode(qpainter.compositionmode.compositionmode_sourceover)
            # 绘制边框
            pen = qpen(qcolor(0, 160, 255), 2)
            painter.setpen(pen)
            painter.drawrect(rect)
            self.select_rect = rect

    def mousepressevent(self, event):
        if event.button() == qt.mousebutton.leftbutton:
            self.is_drawing = true
            self.start_pos = event.pos()
            self.end_pos = event.pos()
            self.update()

    def mousemoveevent(self, event):
        if self.is_drawing:
            self.end_pos = event.pos()
            self.update()

    def mousereleaseevent(self, event):
        if event.button() == qt.mousebutton.leftbutton and self.is_drawing:
            self.is_drawing = false
            if not self.select_rect.isempty():
                self.result_pix = self.full_pix.copy(self.select_rect)
            self.accept()  # 关闭对话框

    def keypressevent(self, event):
        if event.key() == qt.key.key_escape:
            self.reject()  # 取消截图


class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.setwindowtitle("pyqt6 截图工具")
        self.resize(300, 150)
        center = qwidget()
        self.setcentralwidget(center)
        layout = qvboxlayout(center)
        layout.setspacing(12)
        layout.setcontentsmargins(30, 30, 30, 30)

        btn_full = qpushbutton("全屏截图")
        btn_area = qpushbutton("区域拖拽截图")
        tip = qlabel("按住鼠标拖拽选区 | esc取消")
        tip.setalignment(qt.alignmentflag.aligncenter)
        tip.setstylesheet("color:#666")

        layout.addwidget(btn_full)
        layout.addwidget(btn_area)
        layout.addwidget(tip)

        btn_full.clicked.connect(self.capture_full)
        btn_area.clicked.connect(self.start_area_capture)

    def capture_full(self):
        screen = qapplication.primaryscreen()
        full_img = screen.grabwindow(0)
        time_str = qdatetime.currentdatetime().tostring("yyyymmdd_hhmmss")
        save_path = f"full_{time_str}.png"
        full_img.save(save_path, "png")
        qmessagebox.information(self, "保存成功", f"路径:\n{os.path.abspath(save_path)}")

    def start_area_capture(self):
        # 先隐藏主窗口,避免截图包含自身
        self.hide()
        qapplication.processevents()

        screen = qapplication.primaryscreen()
        full_img = screen.grabwindow(0)

        mask = screenshotmask(full_img)
        # 正确使用qdialog的exec(),不会卡死
        ret = mask.exec()

        # 截图完成后恢复窗口
        self.show()

        if ret == 1 and mask.result_pix is not none:
            time_str = qdatetime.currentdatetime().tostring("yyyymmdd_hhmmss")
            save_path = f"region_{time_str}.png"
            mask.result_pix.save(save_path, "png")
            qmessagebox.information(self, "区域截图完成", f"已保存:\n{os.path.abspath(save_path)}")


if __name__ == "__main__":
    app = qapplication(sys.argv)
    win = mainwindow()
    win.show()
    sys.exit(app.exec())

2、效果展示

二、详解

1、核心代码解析

导入模块

import sys
from pyqt6.qtwidgets import qapplication, qmainwindow, qpushbutton, qwidget, qvboxlayout
from pyqt6.qtgui import qscreen
from pyqt6.qtcore import qt
  • qapplication: pyqt6应用程序的核心类,管理gui程序的控制流和主要设置
  • qmainwindow: 主窗口类,提供标准的应用程序主窗口框架
  • qscreen: 屏幕类,用于获取屏幕信息和进行屏幕截图操作
  • qt.alignmentflag: 对齐标志枚举,用于控制界面元素的布局对齐方式

screenshotwindow类结构

class screenshotwindow(qmainwindow):
    def __init__(self):
        super().__init__()
        self.init_ui()
  • 继承自qmainwindow,获得标准主窗口的所有功能
  • 在构造函数中调用init_ui()方法初始化用户界面

界面初始化

def init_ui(self):
    self.setwindowtitle("屏幕截图工具")
    self.resize(300, 120)
    
    # 中心部件与布局
    central_widget = qwidget()
    self.setcentralwidget(central_widget)
    layout = qvboxlayout(central_widget)
    layout.setcontentsmargins(50, 30, 50, 30)
    
    # 截图按钮
    self.btn_capture = qpushbutton("点击截取全屏并保存png")
    self.btn_capture.clicked.connect(self.capture_screen)
    layout.addwidget(self.btn_capture, alignment=qt.alignmentflag.aligncenter)
  • setwindowtitle(): 设置窗口标题
  • resize(): 设置窗口初始大小(300×120像素)
  • qvboxlayout: 垂直布局管理器,自动排列子部件
  • setcontentsmargins(): 设置布局边距(左、上、右、下)
  • clicked.connect(): 连接按钮点击信号到槽函数

2、截图功能详解

capture_screen方法

def capture_screen(self):
    # 获取主屏幕对象
    screen: qscreen = qapplication.primaryscreen()
    # 截取整个屏幕
    pixmap = screen.grabwindow(0)
    # 保存为png文件,保存在程序同级目录
    save_path = "screenshot.png"
    pixmap.save(save_path, "png")
    print(f"截图已保存至: {save_path}")

qapplication.primaryscreen()

  • 返回应用程序的主屏幕对象(qscreen实例)
  • 在多显示器系统中,返回操作系统定义的主显示器
  • 可以通过qapplication.screens()获取所有可用屏幕列表

screen.grabwindow(0)

  • 参数0: 表示截取整个屏幕(桌面窗口)
  • 返回一个qpixmap对象,包含屏幕的像素数据
  • 可以指定特定窗口的id来截取特定窗口

pixmap.save()

  • qpixmap保存为图像文件
  • 支持多种格式:png、jpg、bmp等
  • 第二个参数指定格式(“png”、"jpeg"等)

3、关键api说明

qscreen类的重要方法

方法说明返回值
grabwindow(wid window, x=0, y=0, width=-1, height=-1)截取指定窗口区域qpixmap
geometry()获取屏幕的几何信息(位置和大小)qrect
availablegeometry()获取可用区域(排除任务栏等)qrect
name()获取屏幕名称str
devicepixelratio()获取设备像素比float

qpixmap类的重要方法

方法说明
save(filename, format)保存图像到文件
toimage()转换为qimage对象
scaled(width, height)缩放图像
copy(rect)复制指定区域

4、功能扩展建议

多显示器支持

def capture_all_screens(self):
    """截取所有屏幕"""
    screens = qapplication.screens()
    for i, screen in enumerate(screens):
        pixmap = screen.grabwindow(0)
        pixmap.save(f"screenshot_screen_{i}.png", "png")

选择保存路径

from pyqt6.qtwidgets import qfiledialog

def capture_with_dialog(self):
    screen = qapplication.primaryscreen()
    pixmap = screen.grabwindow(0)
    
    # 弹出文件保存对话框
    file_path, _ = qfiledialog.getsavefilename(
        self, 
        "保存截图", 
        "screenshot.png", 
        "png files (*.png);;jpeg files (*.jpg);;all files (*)"
    )
    
    if file_path:
        pixmap.save(file_path, "png")
        print(f"截图已保存至: {file_path}")

截取指定区域

def capture_region(self, x, y, width, height):
    """截取屏幕指定区域"""
    screen = qapplication.primaryscreen()
    pixmap = screen.grabwindow(0, x, y, width, height)
    return pixmap

添加时间戳

from datetime import datetime

def capture_with_timestamp(self):
    screen = qapplication.primaryscreen()
    pixmap = screen.grabwindow(0)
    
    # 生成带时间戳的文件名
    timestamp = datetime.now().strftime("%y%m%d_%h%m%s")
    save_path = f"screenshot_{timestamp}.png"
    
    pixmap.save(save_path, "png")
    print(f"截图已保存至: {save_path}")

5、常见问题与解决方案

权限问题

  • macos: 需要屏幕录制权限
    • 系统偏好设置 → 安全性与隐私 → 隐私 → 屏幕录制
    • 勾选终端或ide应用
  • linux: 可能需要x11或wayland相关权限
  • windows: 通常无需特殊配置

多显示器坐标系统

  • 每个显示器有独立的坐标系统
  • 主显示器的原点为(0, 0)
  • 副显示器可能有负坐标或大于主显示器分辨率的坐标

高dpi屏幕适配

# 启用高dpi支持
if hasattr(qt, 'aa_enablehighdpiscaling'):
    qapplication.setattribute(qt.aa_enablehighdpiscaling, true)
if hasattr(qt, 'aa_usehighdpipixmaps'):
    qapplication.setattribute(qt.aa_usehighdpipixmaps, true)

6、总结

本文详细介绍了使用pyqt6实现屏幕截图的核心技术:

  1. 基础实现: 使用qscreen.grabwindow()方法截取全屏
  2. 界面设计: 使用qmainwindowqvboxlayout创建简洁界面
  3. 文件保存: 使用qpixmap.save()方法保存为png格式
  4. 扩展功能: 提供了多显示器、区域截图、自定义保存路径等扩展方案

pyqt6的屏幕截图功能简单高效,适合需要集成截图功能的桌面应用程序开发。通过本文的示例代码和详细解析,读者可以快速掌握这一实用技术。

以上就是python结合pyqt6实现屏幕截图工具(附源码)的详细内容,更多关于pyqt屏幕截图的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com