Как повернуть QPixmap без изменения размера

Как повернуть QPixmap без изменения размера Я использую этот код, но когда я поворачиваю изображение, он меняет размер изображения.

Заголовочный файл

#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

файл CPP

#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) );
}

Как повернуть QPixmap без изменения размера Я использую этот код, но когда я поворачиваю изображение, он меняет размер изображения в заголовочном файле.


person Sonicpath    schedule 02.12.2017    source источник
comment
Что вы имеете в виду, поясните лучше, вы могли бы разместить изображение того, что вы получаете и что вы хотите получить.   -  person eyllanesc    schedule 02.12.2017
comment
Я только что создал собственный класс для QDial для поддержки таблиц стилей для добавления фоновых изображений, теперь моя проблема заключается в том, что при повороте изображения в номеронабирателе с помощью этого кода изменяется размер изображения. Есть ли другой способ повернуть Qpixmap?   -  person Sonicpath    schedule 02.12.2017
comment
Покажите свой код, чтобы протестировать его и посмотреть, как его можно исправить.   -  person eyllanesc    schedule 02.12.2017
comment
вот мой код, и я использую поворотную кнопку png для ресурса   -  person Sonicpath    schedule 03.12.2017


Ответы (2)


Что касается вашего вопроса, вы можете просто использовать QPixmap::copy() для извлечения центральной части необходимого размера:

//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);

Но это было бы неэффективно (см. также примечание для QPixmap::transformed()). Я бы предпочел рисовать напрямую с помощью QPainter без создания промежуточных растровых изображений, особенно потому, что он у вас уже есть:

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);

Также рассмотрите возможность загрузки QPixmap при инициализации вашего виджета и его сохранения, а не выполнения этого в paintEvent (опять же ради эффективности).

Причина, по которой QPixmap::transformed() увеличивает размер при вращении, состоит в том, чтобы получить все изображение, включая края, потому что вы всегда можете извлечь меньшее изображение из большего, но не наоборот. У вас скорее всего круглая картинка, а вот для прямоугольной сразу видно.

person absolute.madness    schedule 03.12.2017

Метод, который Qdial использует для расчета фонового круга, таков:

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));

Итак, QRect br — это прямоугольник для фонового круга. Затем просто добавьте файл ресурсов Pixmap, используя эти координаты.

 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));

И вы получаете идеальное изображение с изменяемым размером и возможностью вращения внутри вашего циферблата.

person Sonicpath    schedule 04.12.2017