QT截图程序,可多屏幕截图

截图程序,支持多屏幕时跨屏幕截图。截图使用setMask达到镂空效果,截图后会有预览和保存功能。截图时按下Esc可退出。

mainwindow.ui

mainwindow.cpp

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QFileDialog>
#include <QPushButton>
#include <QPixmap>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowTitle(QString(tr("截图")));
    ui->centralwidget->setMouseTracking(true);
    ui->comboBox->addItem(QString(tr(".")));
    ui->comboBox->addItem(QString(tr("Select Folder")));
    connect(ui->comboBox, SIGNAL(activated(int)), this, SLOT(SelectFolder(int)));
    connect(ui->button_reset, SIGNAL(clicked(bool)), this, SLOT(ResetSnap(bool)));
    connect(ui->button_save, SIGNAL(clicked(bool)), this, SLOT(SavePicture(bool)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    qDebug()<<this->geometry();
    QMainWindow::mouseMoveEvent(event);
}

void MainWindow::SetImage(QPixmap &pixmap)
{
    const double defultWidth = 400.0;
    const double defaultHeight = 160.0;

    ui->label->setPixmap(pixmap);
    double pixscale = 1.0 * pixmap.width()/pixmap.height();
    double initscale = defultWidth/defaultHeight;
    if (pixscale > initscale)
    {
        ui->label->setFixedWidth(defultWidth);
        ui->label->setFixedHeight(defultWidth / pixscale);
    }
    else
    {
        ui->label->setFixedHeight(defaultHeight);
        ui->label->setFixedWidth(defaultHeight * pixscale);
    }
}

void MainWindow::SelectFolder(int index)
{
    if (index == 1)
    {
        qDebug()<<ui->comboBox->itemText(index);
        QString directory = QFileDialog::getExistingDirectory(this,
                                    tr("QFileDialog::getExistingDirectory()"),
                                    ".");
        if (!directory.isEmpty())
        {
            qDebug()<<directory;
            ui->comboBox->addItem(directory);
            ui->comboBox->setCurrentText(directory);
        }
        else
        {
            ui->comboBox->setCurrentIndex(0);
        }
    }
}

void MainWindow::ResetSnap(bool)
{
    this->hide();
    emit resetSnap();
}

void MainWindow::SavePicture(bool)
{
    if (ui->lineEdit->text().trimmed() == QString(""))
    {
        ui->lineEdit->setFocus();
        return;
    }
    if (ui->comboBox->currentText() != ".")
    {
        ui->label->pixmap()->save(ui->comboBox->currentText() + "/" + ui->lineEdit->text(), "PNG");
    }
    else
    {
        ui->label->pixmap()->save(ui->lineEdit->text(), "PNG");
    }
}

maskwidget.cpp

cpp 复制代码
#include "maskwidget.h"
#include "ui_maskwidget.h"
#include <QMouseEvent>
#include <QRegion>
#include <QScreen>
#include <QPainter>
#include <QGuiApplication>
#include <QPixmap>
#include <QDebug>
#include <QtMath>

MaskWidget::MaskWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MaskWidget)
{
    ui->setupUi(this);
    setMouseTracking(true);
    setWindowFlags(Qt::FramelessWindowHint);

    setWindowOpacity(0.8);
    QList<QScreen*> screens = QGuiApplication::screens();
    int width = 0;
    int height = 0;
    for (QScreen *screen : screens)
    {
        width += screen->geometry().width();
        if (height < screen->geometry().height())
        {
            height = screen->geometry().height();
        }
        qDebug()<<screen->geometry();
    }
    this->setFixedSize(width, height);

    m.hide();

    connect(&m, SIGNAL(resetSnap()), this, SLOT(ResetSnap()));
}

MaskWidget::~MaskWidget()
{
    delete ui;
}

void MaskWidget::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        m_pressPos = event->pos();

        isPressed = true;
        update();
    }

    QWidget::mousePressEvent(event);
}

void MaskWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if (isPressed)
    {
        isPressed = false;
        QRegion all(0, 0, width(), height());

        QRegion sub(m_maskRect);
        setMask(all.subtracted(sub));


        QPixmap combined(this->width(), this->height());
        combined.fill(Qt::transparent);
        QPainter painter(&combined);

        QList<QScreen*> screens = QGuiApplication::screens();
        for (QScreen *screen : screens)
        {
            m_image = screen->grabWindow(0);
            painter.drawPixmap(screen->geometry().x(), 0, screen->geometry().width(), screen->geometry().height(), m_image);
        }

        auto gpos = mapToGlobal(event->pos());
        auto gposStart = mapToGlobal(m_pressPos);
        qDebug()<<gpos<<gposStart;
        m_image = combined.copy(qMin(gpos.x(), gposStart.x()), qMin(gpos.y(), gposStart.y()),
                                qFabs(gpos.x() - gposStart.x()), qFabs(gpos.y() - gposStart.y()));
        this->hide();

        m.SetImage(m_image);
        update();

        m.show();

    }

    return QWidget::mouseReleaseEvent(event);
}

void MaskWidget::mouseMoveEvent(QMouseEvent* event)
{
    if (isPressed)
    {
        m_newPos = event->pos();
        QRegion all(0, 0, width(), height());
        m_maskRect = QRect(qMin(m_pressPos.x(), m_newPos.x()),
                       qMin(m_pressPos.y(), m_newPos.y()),
                       qFabs(m_newPos.x() - m_pressPos.x()),
                       qFabs(m_newPos.y() - m_pressPos.y()));

        QRegion sub(m_maskRect);
        setMask(all.subtracted(sub));
        
        update();
    }
    return QWidget::mouseMoveEvent(event);
}

void MaskWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    
    painter.setPen(Qt::red);
    painter.drawRect(m_maskRect.x()-1, m_maskRect.y()-1, m_maskRect.width()+2, m_maskRect.height() + 2);

}

void MaskWidget::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_Escape)
    {
        close();
    }
    QWidget::keyPressEvent(event);
}

void MaskWidget::showEvent(QShowEvent *event)
{
    QWidget::showEvent(event);
}

void MaskWidget::ResetSnap()
{
    QRegion all(0, 0, width(), height());
    setMask(all);
    m_maskRect.setRect(0,0,0,0);
    this->show();
}

main.cpp

cpp 复制代码
#include "mainwindow.h"
#include "maskwidget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    MaskWidget m;
    m.move(0, 0);
    m.show();



    return a.exec();
}

多个屏幕时,默认设置位置和大小总是在一个屏,需要用move()将它移动到(0, 0)位置。多屏幕跨屏幕截图时,先分别截取每个屏幕的图,然后把他们拼起来。

代码

相关推荐
云空16 分钟前
《QT 5.14.1 搭建 opencv 环境全攻略》
开发语言·qt·opencv
小老鼠不吃猫1 小时前
力学笃行(二)Qt 示例程序运行
开发语言·qt
晓纪同学3 小时前
QT创建一个模板槽和信号刷新UI
开发语言·qt·ui
爱码小白5 小时前
PyQt5 学习方法之悟道
开发语言·qt·学习方法
人才程序员17 小时前
QML z轴(z-order)前后层级
c语言·前端·c++·qt·软件工程·用户界面·界面
学习BigData18 小时前
【使用PyQt5和YOLOv11开发电脑屏幕区域的实时分类GUI】——选择检测区域
qt·yolo·分类
yerennuo1 天前
FFmpeg库之ffmpeg
qt·ffmpeg
冷眼看人间恩怨1 天前
【Qt笔记】QComboBox控件详解
c++·笔记·qt
阿松のblog1 天前
pyQt5实现页面切换操作
开发语言·qt
人才程序员1 天前
【无标题】
c语言·前端·c++·qt·软件工程·qml·界面