QT Screenshot Example 看看看

Screenshot Example展示了怎么用QApplicationQDesktopWidget获取桌面的截屏。它也展示了怎么用QTimer提供一个单发时间(single-shot timer)、怎么样为了确保应用程序没有数据丢失地调整大小而重新实现QWidget::resizeEvent()事件处理器。

通过程序,使用者可以获取自己桌面的截图。其中有两个设置:

1. 延迟截屏时间,让用户可以重新排列他的桌面。

2. 当程序截图时隐藏应用程序窗口。

除此之外,还可以让用户保存自己的截图。


该程序只有一个类:Screenshot类。先看看main.cpp文件。

int main(int argc, char *argv[])

{

   QApplication app(argc, argv);

   Screenshot screenshot;

   screenshot.show();

   return app.exec();

}


再看看screenshot类定义:

class Screenshot : public QWidget

{

   Q_OBJECT

public:

   Screenshot();

protected:

   void resizeEvent(QResizeEvent *event);

private slots:

   void newScreenshot();           // 新建截图槽

   void saveScreenshot();          // 保存截图槽

   void shootScreen();             // 截图槽

   void updateCheckBox();          // 是否隐藏窗体槽

private:

   void createOptionsGroupBox();       // 构造groupbox窗体部件

   void createButtonsLayout();         // 窗体部件布局管理

   QPushButton *createButton(const QString &text, QWidget *receiver,

                             const char *member);

   void updateScreenshotLabel();

   QPixmap originalPixmap            // 保存获取到的桌面截屏

   QLabel *screenshotLabel           // 以下为控件和布局管理器

   QGroupBox *optionsGroupBox;

   QSpinBox *delaySpinBox;

   QLabel *delaySpinBoxLabel;

   QCheckBox *hideThisWindowCheckBox;

   QPushButton *newScreenshotButton;

   QPushButton *saveScreenshotButton;

   QPushButton *quitScreenshotButton;

   QVBoxLayout *mainLayout;

   QGridLayout *optionsGroupBoxLayout;

   QHBoxLayout *buttonsLayout;

};

 

Screenshot继承自QWidget,重写了QWidget::resizeEvent(), 为了确保用户调整窗口大小时预览截图可能的缩放调整。

所有控件以及布局管理器都作为数据成员

//! [0]

Screenshot::Screenshot()

{

   screenshotLabel = new QLabel   // 用啦显示截图的Label

   screenshotLabel->setSizePolicy(QSizePolicy::Expanding // 大小策略

                                  QSizePolicy::Expanding);

   screenshotLabel->setAlignment(Qt::AlignCenter);         // 居中对齐

   screenshotLabel->setMinimumSize(240160);              // 最小大小

   createOptionsGroupBox();        // 调用创建groupbox窗体部件及布局

   createButtonsLayout();          // 调用创建buttonlayout以及布局

   mainLayout = new QVBoxLayout  // 主布局:label+groupbox+buttonlayout

   mainLayout->addWidget(screenshotLabel);

   mainLayout->addWidget(optionsGroupBox);

   mainLayout->addLayout(buttonsLayout);

   setLayout(mainLayout);

   shootScreen();               // 截图

   delaySpinBox->setValue(5);   // 设置默认延迟时间5

   setWindowTitle(tr("Screenshot"));  // 主窗口标题

   resize(300200);                  // 大小

}

//! [0]


//! [1]

// 窗体调整大小时,调整截图label的大小

void Screenshot::resizeEvent(QResizeEvent * /* event */)

{

   QSize scaledSize = originalPixmap.size();

   scaledSize.scale(screenshotLabel->size(), Qt::KeepAspectRatio);

   if (!screenshotLabel->pixmap()   // 当没有设置位图或者这里的缩放大小和screenshotLabel的大小不一致时

           || scaledSize != screenshotLabel->pixmap()->size())

       updateScreenshotLabel();     // 更新screenshotLabel

}

//! [1]

QSize::scale()函数,有三种模式:IgnoreAspectRatio,KeepAspectRatio,KeepAspectRatioByExpanding

   QSize t1(10, 12);

   t1.scale(60, 60, Qt::IgnoreAspectRatio);

   // t1 is (60, 60)

   QSize t2(10, 12);

   t2.scale(60, 60, Qt::KeepAspectRatio);

   // t2 is (50, 60)

   QSize t3(10, 12);

   t3.scale(60, 60, Qt::KeepAspectRatioByExpanding);

   // t3 is (60, 72)

//! [2]

void Screenshot::newScreenshot()

{

   if (hideThisWindowCheckBox->isChecked())    // 检查是否隐藏主窗体

       hide();

   newScreenshotButton->setDisabled(true);     // 新建时新建截屏按钮不可用

   // 设置一个单发时间器,时间为延迟时间spinBox里头的值,时间到时就发送信息到shootScreen()

   QTimer::singleShot(delaySpinBox->value() * 1000thisSLOT(shootScreen()));

}

//! [2]

QTimer提供重复和单发时间器。当时间结束时会发送信号:timeout()。例如:

QTimer *timer = new QTimer(this);

     connect(timer, SIGNAL(timeout()), this, SLOT(update()));

     timer->start(1000);

update()将会每一秒被触发一次。

使用singleShot就只会被发送一次。例如:

QTimer::singleShot(200, this, SLOT(updateCaption()));

updateCaption()0.2秒后被触发。


//! [3]

void Screenshot::saveScreenshot()

{

   QString format = "png"    // 保存图片的格式

   // 初始化路径:当前程序路径

   QString initialPath = QDir::currentPath() + tr("/untitled.") + format;

   // getSaveFileName对话框获取保存的路径

   QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"),

                              initialPath,

                              tr("%1 Files (*.%2);;All Files (*)")

                              .arg(format.toUpper())

                              .arg(format));

   if (!fileName.isEmpty()) // 保存对话框里路径不为空就执行保存QPixmap::save(..)

       originalPixmap.save(fileName, format.toAscii());

}

//! [3]


以下shootScreen就是程序的核心

//! [4]

void Screenshot::shootScreen()

{

   // 这里的qApp是应用程序QApplication对象的一个全局指针,用它来轻松获取程序的控制

   if (delaySpinBox->value() != 0)

       qApp->beep();   // 一声响铃

//! [4]

   originalPixmap = QPixmap(); // clear image for low memory situations

                               // on embedded devices.

//! [5]

   // 窗体抓图:grabWindow( WId window, int x = 0, int y = 0, int width = -1, int height = -1)

   // WId每一个窗体都有一个ID,可以用 QWidget::winId()获取

   originalPixmap = QPixmap::grabWindow(QApplication::desktop()->winId());

   updateScreenshotLabel();

   newScreenshotButton->setDisabled(false);    // 在执行截图时,使newScreenshotButton不可用

   if (hideThisWindowCheckBox->isChecked())    // 截图完时要将隐藏的主窗体显示回来(如果隐藏了)

       show();

}

//! [5]

原来程序就是使用了grabWindow来获取的截图

对于QApplication

QApplication::desktop()返回桌面,对于有多屏幕的桌面的可能不正确。可以获取它的返回值QDesktopWidget, 它有一些函数让你获取一些有用的信息,例如:availableGeometry() screenGeometry()

//! [6]

void Screenshot::updateCheckBox()

{

   if (delaySpinBox->value() == 0) {   // 若延迟时间为零时,CheckBox不可用并且为没打勾状态

       hideThisWindowCheckBox->setDisabled(true);

       hideThisWindowCheckBox->setChecked(false);

   }

   else                                // 否则为可用

       hideThisWindowCheckBox->setDisabled(false);

}

//! [6]


//! [7]

void Screenshot::createOptionsGroupBox()

{

   optionsGroupBox = new QGroupBox(tr("Options"));     // 组框

   delaySpinBox = new QSpinBox           // spinbox用于调整延迟时间

   delaySpinBox->setSuffix(tr(" s"));

   delaySpinBox->setMaximum(60);

   // 连接delaySpinBoxvalueChanged(int)信号和updateCheckBox()

   connect(delaySpinBoxSIGNAL(valueChanged(int)), thisSLOT(updateCheckBox()));


   // 用于提示的label

   delaySpinBoxLabel = new QLabel(tr("Screenshot Delay:"));

   // 是否隐藏的CheckBox

   hideThisWindowCheckBox = new QCheckBox(tr("Hide This Window"));

   // GridLayout布局管理label,spinBox,checkBox

   optionsGroupBoxLayout = new QGridLayout;

   optionsGroupBoxLayout->addWidget(delaySpinBoxLabel00);

   optionsGroupBoxLayout->addWidget(delaySpinBox01);

   optionsGroupBoxLayout->addWidget(hideThisWindowCheckBox1012);

   optionsGroupBox->setLayout(optionsGroupBoxLayout);  // 设置到组框groupBox

}

//! [7]


//! [8]

void Screenshot::createButtonsLayout()

{

   // buttonLayout里三个PushButton

   newScreenshotButton = createButton(tr("New Screenshot"),  // 自定义的一个创建函数

                                      thisSLOT(newScreenshot()));

   saveScreenshotButton = createButton(tr("Save Screenshot"),

                                       thisSLOT(saveScreenshot()));

   quitScreenshotButton = createButton(tr("Quit"), thisSLOT(close()));

   buttonsLayout = new QHBoxLayout;

   buttonsLayout->addStretch();    // 在最左边加入一个stretch占位

   buttonsLayout->addWidget(newScreenshotButton);

   buttonsLayout->addWidget(saveScreenshotButton);

   buttonsLayout->addWidget(quitScreenshotButton);

}

//! [8]


//! [9]

// 方便创建pushButton时初始化

QPushButton *Screenshot::createButton(const QString &text, QWidget *receiver,

                                     const char *member)

{

   QPushButton *button = new QPushButton(text);

   button->connect(button, SIGNAL(clicked()), receiver, member);

   return button;

}

//! [9]


//! [10]

void Screenshot::updateScreenshotLabel()

{

   // 更新screenshotLabel,放置一张缩放了的截图

   screenshotLabel->setPixmap(originalPixmap.scaled(screenshotLabel->size(),

                                                    Qt::KeepAspectRatio,

                                                    Qt::SmoothTransformation));

}

//! [10]

你可能感兴趣的:(C++,C++,qt,qt,qt)