Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt, QTransform rotation

I'm trying to draw text "on cylinder". It means, that I have five rows of text. Top row is rotated by the X axis for 10 degrees. The second for 5 degrees. The middle is not rotated at all. The four's row is rotated for -5 degrees. The five's is rotated for -10 degrees. Rows 1, 2, 3 draws OK, but something is wrong with 4,5 rows. What am I doing wrong ? I provides an image for understanding a problem and code snippet:

for( int i = 0; i < iterationsCount; ++i )
{
    const QRect r( x2, y2, textWidth, itemHeight );

    const QString text = sections.at( section ).values.at( index );

    int rsc = 0;


    p->save();

    rsc = widgetHeight / 2 - y;

    p->setTransform(QTransform().rotate(rsc, Qt::XAxis));


    if( type == Section::DaySectionShort ||
        type == Section::DaySectionLong )
    {


        QStringList values = text.split( QLatin1Char( ' ' ) );

        p->setPen(
            lighterColor( opt.palette.color( QPalette::WindowText ), 75 ) );
        p->drawText( r, Qt::AlignLeft | Qt::TextSingleLine, values.at( 0 ) );

        p->setPen( opt.palette.color( QPalette::WindowText ) );
        p->drawText( r, Qt::AlignLeft | Qt::TextSingleLine, values.at( 1 ) );
    }
    else
    {
       p->drawText( r, Qt::AlignLeft | Qt::TextSingleLine, text );
    }

    p->setTransform(QTransform().rotate(-rsc, Qt::XAxis));

    index = nextIndex( index, sections.at( section ).values.size() );
    y += itemHeight + itemTopMargin;

    p->restore();
}

My problem

like image 635
Дмитрий Дяков Avatar asked Dec 02 '25 10:12

Дмитрий Дяков


1 Answers

As you have not provided a minimal complete code that reproduces the problem, I cannot guess what is wrong there. But the most probable reason is incorrect rsc calculation. At least the following draft works:

#include <QtCore>
#include <QtGui>
#include <QtWidgets>

class MyWidget: public QWidget
{
public:
    MyWidget(QWidget *parent = nullptr)
        : QWidget(parent)
    {
        QFont f = font();
        f.setPointSize(15);
        setFont(f);
    }

protected:
    void paintEvent(QPaintEvent *event) override
    {
        QWidget::paintEvent(event);
        QPainter p(this);

        const int itemHeight = fontMetrics().height();
        const int itemTopMargin = 15;
        const int xOffset = 15;
        int y = itemHeight;

        for (size_t i = 0; i < 5; ++i) {
            // The angle is in range [-40, 40]. Remove " * 4" for [-10, 10].
            const int rsc = (10 - 5 * i) * 4;
            qDebug() << i << ":\t" << rsc << "\t" << y;

            /*
                Rotation must be performed relative to central point of the
                drawn item. Transformations below are applied in reverse order.
                At first translate item to make it's center in (0, 0). At
                second rotate it relative to X axis. At third move the item to
                desired position.
            */
            QTransform transform;
            transform.translate(xOffset, y + itemHeight / 2);
            transform.rotate(rsc, Qt::XAxis);
            transform.translate(0, - itemHeight / 2);
            p.setTransform(transform);

            p.drawText(QPoint(), QString("(Item no. %1)").arg(i + 1));

            y += itemHeight + itemTopMargin;
        }
    }
};

int main(int argc, char **argv)
{
    QApplication app(argc, argv);

    MyWidget widget;
    widget.setMaximumSize(200, 250);
    widget.show();

    return app.exec();
}

The transformation used here is complicated because of need to rotate each item relative to it's central y, not y = 0. This also may be the case.

Font and angles are increased to see considered effects better.

like image 131
ilotXXI Avatar answered Dec 05 '25 01:12

ilotXXI



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!