Now, if the application is tested, the image should be printed on the screen! Yeah!
Now, it is time to add some functionality to this screen, like rotating and zooming.
Adding Rotate Functions
To rotate the image to the left and right, two actions are needed. These will be arranged in a sub menu.
void ImageScreen::createActions()
{
_rotateLeftAction = new QAction("Left", this);
connect(_rotateLeftAction, SIGNAL(triggered()),
this, SLOT(onRotateRight()));
_rotateRightAction = new QAction("Right", this);
connect(_rotateRightAction, SIGNAL(triggered()),
}
The rotate left and rotate right actions are connected to the onRotateLeft and onRotateRight slots. In the rotate slots, the rotation by 90 degres counter clockwise or clockwise is changed and an update is triggered.
To see the actions in the menu, they have to be added to the options menu. The left and right rotation actions will appear in the rotate sub-menu.
void ImageScreen::createMenu()
{
QMenu* menu = QSoftMenuBar::menuFor(this);
QMenu* rotateMenu = menu->addMenu("Rotate");
rotateMenu->addAction(_rotateLeftAction);
rotateMenu->addAction(_rotateRightAction);
QMenu* zoomMenu = menu->addMenu("Zoom");
}
The onRotateLeft/Right methods are quite simple.
void ImageScreen::onRotateLeft()
{
_rotation -= 90.0;
update();
}
void ImageScreen::onRotateRight()
{
_rotation += 90.0;
update();
}
The _rotation field is a qreal field, which holds our current rotation. Every time the roation is called, 90 degres is added/substracted on the rotation. The _rotation field must be initialized to 0 in the constructor.
Now the paintEvent method needs some changes in order to reflect the rotation.
void ImageScreen::paintEvent(QPaintEvent* event)
{
_image = new QImage(_content.file());
int x = width()/2-_image->width()/2;
int y = height()/2-_image->height()/2;
int x2 = width()/2;
int y2 = height()/2;
QPointF c(x2, y2);
QPainter painter(this);
painter.translate(c);
painter.rotate(_rotation);
painter.translate(-c);
painter.drawImage(QPoint(x, y), *_image);
painter.end();
}
The translate() methods are used to translate every x-y coordinates to the center of the widget. Otherwise the image would rotate around the top-left corner ( QPoint(0,0) ). Now, the image can be rotated with the rotate method. The second translate() call translates every call back to the top left corner of the now rotated x-y coordinate system. The image is then painted on the top-left corner of this coordination system.
Instead of calculating the center of the screen manually, the QRect.center() method of the QWidget.rect() could also have been used. This would also be the preferred way. The documentation provides useful information about the translation and rotation.
After a compilation, the application can be run. Now the rotate actions are available from the rotate menu in the options menu of the image screen.
Zooming in and out
The zoom functionality is similarly structured to the rotate functionality. The creation of the zoom in and out actions and the addition to a zoom sub-menu are left to the reader.
The implementation of the zoom in/out functions just add/substract a 0.5 value to the zoom level.
void ImageScreen::onZoomOut()
{
_zoom -= 0.5;
update();
}
void ImageScreen::onZoomIn()
{
_zoom += 0.5;
update();
}
Again the _zoom field is a qreal, which needs to be initialized in the constructor to 1 this time.
In the paint method, the zooming functionalities are added by modifying the scale.
void ImageScreen::paintEvent(QPaintEvent* event)
{
...
QPainter painter(this);
painter.translate(c);
painter.rotate(_rotation);
painter.scale(_zoom, _zoom);
painter.translate(-c);
...
}
We scale the image symetrically by width and height.
Now, in the options menu of the image screen, the Zoom sub-menu with in and out sub-menu items is available. Pressing the In action should zoom in the image by 50%.
Summary
This part of the tutorial has described how to paint an image on the screen and how to use the rotate, scale and translate functionalities of the painter. The painter is a very powerful object. Moreover, some repeating patterns in designing screens for mobile phones have been shown. These patterns will repeat for each screen. The screens are lazily created and added to our stacked widget. Currently if a screen is created, it will only be destroyed when the application closes.
Note: The images in paintEvent will never be destroyed. if(_image) delete _image should be added in the front of the paintEvent method to get rid of an old image.
The next part will introduce some actions to the list screen, like rename and delete.
Prev|Top|Start Page|Next