The realization of the screenshot function in QT

Source: Internet
Author: User

Feed

Requirement: Load a picture and display it, zoom in and out, you can capture a rectangle of the picture and save it.

Originally thought quite simple a function, actually still is a little small complex.

The simplest QT Image browser can refer to the QT demo:image Viewer Example

Take a look at the final implementation:







Load display of pictures

It is necessary to implement a Qimageviewer class that inherits from Qwidget.

Pictures with Qpixmap to load and display, there are three members are the image of the zoom factor, whether the picture has been loaded, whether the viewer has been initialized, is in the clipping state.

Private:qpixmap m_pixmap;float scalling;bool isloaded;bool isintialised;bool iscropping;

The scalling value is the scale used to record the picture.

As long as the image is redefined paintevent, the M_pixmap will be drawn on it.

void Qimageviewer::p aintevent (qpaintevent *event) {qwidget::p aintevent (event), if (M_pixmap.isnull ()) {return;} qpainter painter (this); if (isLoaded) {painter.setrenderhint (qpainter::smoothpixmaptransform); Qsize pixsize = M_pixmap.size ();//for canvas ' s size not change when window ' s size change.if (!isinitialised) {qsize Initial Size = Event->rect (). Size (), scaling = 1.0 * initialsize.width ()/Pixsize.width (); isinitialised = true;} Pixsize.scale (Scaling * pixsize, qt::keepaspectratio); This->setminimumsize (pixsize); Qpoint Topleft;topleft.setx ((This->width ()-pixsize.width ())/2); Topleft.sety ((This->height ()- Pixsize.height ())/2);p Ainter.drawpixmap (TopLeft, m_pixmap.scaled (Pixsize, Qt::keepaspectratio, Qt:: smoothtransformation));}}

The idea is simple, first choose to enter the cropping mode (you can add an action in the menu or a shortcut key), and then drag a rectangle on the picture, and finally press ENTER, the interception is complete, Ctrl + s save.

The main use is the Qpixmap::copy (Qrect rect) method.


The first step is to implement a Croprect class that records the truncated rectangle.

#ifndef croprect_h#define croprect_h#include <QPoint> #include <qpainter>class croprect{public:croprect ( {}~croprect () {}void Setstart (Qpoint s) {start = s;} void SetEnd (Qpoint e) {end = e;} Qpoint startPoint () const{return start;} Qpoint endPoint () const{return end;} void Reset () {Qpoint P (0,0); start = P;end = P;} qsize& size () Const{return qsize (width (), height ());} int height () const{return qabs (StartPoint (). Y ()-EndPoint (). Y ());} int width () const{return qabs (StartPoint (). x ()-EndPoint (). x ());} Private:qpoint start; Qpoint end;}; #endif//Croprect_h


Note that both start and end are relative to the current position of the image being captured, i.e. the coordinates of the upper-left corner of the picture are the origin of the croprect.


Then two auxiliary methods are implemented in Qimageviewer.

Because the picture is not exactly filled with the form, so in the setting of the Crop box, the mouse if there is no point in the picture, it should not be cropped, so you should first determine whether a point on the screen is on the picture.

BOOL Qimageviewer::iscontainpoint (Qpoint &p) {qsize s = m_pixmap.size (); S.scale (Scaling * s, qt::keepaspectratio); /if pixmap bigger than current Window.if ((S.height () > This->rect (). Height ()) && (S.width () > This->r ECT (). Width ())) {return true;} Qpoint Topleft;topleft.setx ((This->width ()-s.width ())/2); Topleft.sety ((This->height ()-s.height ())/2); Qrect rect (topleft, s); return Rect.contains (P);}

The second way is to map the position of the mouse to the position on the picture, because it is primarily about manipulating the picture.

There are four cases of picture size and window size, the first is that the height and width of the picture are greater than the form.


The logic is to add the red and green parts, to get the position of the point for the current picture (scaled), and then divide it by scalling.


There is also a picture in the window completely inside


In this case, the red minus the green part, the point for the current picture (scaled) position, and finally divided by scalling. There are two simple cases that do not unfold, the specific code is as follows:

Qpoint Qimageviewer::maptopixmap (Qpoint &screenpoint) {qsize pixmapsize = m_pixmap.size ();p Ixmapsize.scale ( Scaling * pixmapsize, qt::keepaspectratio);//get the position of Screenpoint to the pixmap in show. Qpoint tmppos;if (Pixmapsize.width () > This->width () && pixmapsize.height () > This->height ()) { Tmppos.setx (Pixmapsize.width ()-(This->width ()-screenpoint.x ()); Tmppos.sety (Pixmapsize.height ()-(this-> Height ()-screenpoint.y ()));} else if (Pixmapsize.width () < This->width () && pixmapsize.height () > This->height ()) {Tmppos.setx ( Screenpoint.x ()-(This->width ()-pixmapsize.width ())/2); Tmppos.sety (Pixmapsize.height ()-(This->height ()- Screenpoint.y ()));} else if (Pixmapsize.width () > This->width () && pixmapsize.height () < This->height ()) {Tmppos.setx ( Pixmapsize.width ()-(This->width ()-screenpoint.x ()); Tmppos.sety (Screenpoint.y ()-(This->height ()- Pixmapsize.height ())/2);} Else{qpoint Topleft;topLeft.setx ((This->width ()-pixmapsize.width ())/2); Topleft.sety ((This->height ()-pixmapsize.height ())/2); Tmppos.setx (Screenpoint.x ()-topleft.x ()); Tmppos.sety (Screenpoint.y ()-topleft.y ());} Return the position to the real Pixmap.*/return Qpoint (tmppos.x ()/Scaling, tmppos.y ()/scaling);}


Here took an opportunistic approach, that is, using the Qpoint.setx () and Qpoint.sety () method if the transmission is negative, then it is equal to pass in 0, so less than 0 of the judgment.


Next is the corresponding mouse event to determine the size of the cropping box

void Qimageviewer::mousepressevent (Qmouseevent *event) {if (event->buttons () = = Qt::leftbutton) && Iscontainpoint (Event->pos ()) && iscropping) {Croprect.setstart (Maptopixmap ())); Croprect.setend (Maptopixmap (Event->pos ())); isstartingcrop = True;}} void Qimageviewer::mousemoveevent (Qmouseevent *event) {if (event->buttons () = = Qt::leftbutton) && Isstartingcrop) {if (Iscontainpoint (Event->pos ())) {Croprect.setend (Maptopixmap ()); Update ();}}} void Qimageviewer::mousereleaseevent (Qmouseevent *e) {qrect rect (Croprect.startpoint (), Croprect.endpoint ()); Isstartingcrop = false;}


Crop box Drawing related code, here also according to the relative position of startpoint and endpoint, there are several situations need to pay attention to. The more cool dynamic ant line can be referenced by:draw ant line in Qt

if (iscropping) {qdebug () << croprect.width () << croprect.height ();//painter.setpen (Qt::d arkgreen); Qpen Pen;pen.setbrush (qt::red);p En.setstyle (Qt::D ashline);p en.setwidth (1);p Ainter.setpen (pen);//start Point in the Left to the end Point.if (Croprect.startpoint (). x () < Croprect.endpoint (). x ()) {if (Croprect.startpoint (). Y () < Croprect.endpoint (). Y ()) {//start point in the top to the end Point.painter.drawRect (topleft.x () + Croprect.startpoint (). X () * Scaling, TOPLEFT.Y () + Croprect.startpoint (). Y () * scaling, croprect.width () * Scaling, croprect.height () * scaling) ;} Else{//start the bottom to the end Point.painter.drawRect (topleft.x () + Croprect.startpoint (). x () * Scaling, TOPL Eft.y () + Croprect.endpoint (). Y () * scaling, croprect.width () * Scaling, croprect.height () * scaling);}} Else{if (Croprect.startpoint (). Y () > Croprect.endpoint (). Y ()) {Painter.drawrect (Topleft.x () + croprect.endpoint () . x () * Scaling, TOPLEFT.Y () + Croprect.endpoint (). Y () * Scaling, Croprect. Width () * scaling, croprect.height () * scaling);} Else{painter.drawrect (Topleft.x () + Croprect.endpoint (). x () * Scaling, TOPLEFT.Y () + Croprect.startpoint (). Y () * Scaling, croprect.width () * Scaling, croprect.height () * scaling);}}}


And finally, it's cropped .

void Qimageviewer::cropfinished () {Qrect crop (croprect.startpoint (), Qsize (Croprect.width (), Croprect.height ())); Qpixmap cropped = m_pixmap.copy (crop); m_pixmap = Cropped;croprect.reset (); iscropping = False;this->update ();}

Finish the call.

The realization of the function in QT

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.