Reputation: 241
How to rotate a QPixmap without changing size I use this code but when I rotate the image it change the size of the image.
The header file
#ifndef CUSTOMDIAL_H
#define CUSTOMDIAL_H
#include <QDial>
class CustomDial : public QDial
{
Q_OBJECT
public:
CustomDial(QWidget * parent = nullptr);
private:
virtual void paintEvent(QPaintEvent*) override;
};
#endif
the CPP file
#include "Customdial.h"
#include <QGraphicsPixmapItem>
#include <QPainter>
#include <QColor>
#include <QPixmap>
CustomDial::CustomDial(QWidget* parent)
: QDial(parent)
{
// Default range
QDial::setRange(0,100);
}
void CustomDial::paintEvent(QPaintEvent*)
{
int a = QDial::sliderPosition();
QPainter painter(this);
//load pixmap
QPixmap pix(":/img/img/knob.png");
//rotate pixmap
QMatrix rm;
rm.rotate(a);
pix = pix.transformed(rm);
//draw pixmap
painter.drawPixmap(QPointF(0,0),
pix.scaled(QDial::height(),
QDial::height(),
Qt::KeepAspectRatio),
pix.rect().adjusted(1, 1, -1000, -1000) );
}
How to rotate a QPixmap without changing size I use this code but when I rotate the image it change the size of the image the header file
Upvotes: 0
Views: 8100
Reputation: 896
Concerning your question, you can just use QPixmap::copy() to extract the central part of the needed size:
//load pixmap
QPixmap pix(":/images/pixmap.png");
//rotate pixmap
QMatrix rm;
rm.rotate(a);
int pxw = pix.width(), pxh = pix.height();
pix = pix.transformed(rm);
pix = pix.copy((pix.width() - pxw)/2, (pix.height() - pxh)/2, pxw, pxh);
But that would be inefficient (see also note for QPixmap::transformed()). I would prefer drawing directly using QPainter without creating intermediary pixmaps especially because you already have it:
qreal scale = qMin(width(), height()) / qMax(pix.width(), pix.height());
QPointF center(width() / 2., height() / 2.); // widget center
// uncomment to trade performance for quality
// painter.setRenderHint(QPainter::SmoothPixmapTransform);
painter.translate(center);
painter.rotate(degrees);
painter.scale(scale, scale);
painter.drawPixmap(-pix.rect().center(), pix);
Also consider loading QPixmap on initialization of your widget and storing it rather that doing it in paintEvent (again for the sake of efficiency).
The reason that QPixmap::transformed() increases the size on rotation is to get the whole image including the edges because you can always extract a smaller image from the bigger one but not vice versa. You probably have a round picture but for rectangular it's immediately obvious.
Upvotes: 1
Reputation: 241
The method that Qdial is using to calculate the background circle is this
int width = option.rect.width();
int height = option.rect.height();
qreal r2 = qMin(width, height) / 2;
r2 -= r2/50;
const qreal d_ = r2 / 6;
const qreal dx = option.rect.x() + d_ + (width - 2 * r2) / 2 + 1;
const qreal dy = option.rect.y() + d_ + (height - 2 * r2) / 2 + 1;
QRectF br = QRectF(dx + 0.5, dy + 0.5,
int(r2 * 2 - 2 * d_ - 2),
int(r2 * 2 - 2 * d_ - 2));
So QRect br
is the rect for the background circle. Then just add the Pixmap resource file using those cordinates
int w=option.rect.width()/2;
int h=option.rect.height()/2;
painter.translate(w,h);
painter.rotate(a);
//draw pixmap
painter.drawPixmap(-br.width()/2,
-br.height()/2,
pix.scaled(br.width(),br.height(),Qt::KeepAspectRatio));
And you get a perfect resizable and rotatable image inside your dial
Upvotes: 0