[QT, C++] QLabel rotieren

[Moepi]1

Lt. Commander
Registriert
Jan. 2002
Beiträge
1.233
MIt folgender Funktion lasse ich ein QLabel um die eigene Achse rotieren:
Code:
SimField::SimField(int commands[], QWidget *parent)
        : QWidget(parent)
{
        setFixedSize(450, 450);
        setPalette(QPalette(QColor(250, 250, 200)));
        setAutoFillBackground(true);

        mylabel = new QLabel(this);
        mylabel->resize(32,32);
        image = QPixmap("resources/uparrow.png");
        mylabel->setPixmap(image);
        mylabel->move(200, 200);
        mylabel->show();

        connect(&update_timer, SIGNAL(timeout()), this, SLOT(updateSimField()));

        update_timer.setInterval(10);
        update_timer.start();
}

void SimField::updateSimField()
{
        matrix.rotate(1);
        mylabel->setPixmap(image.transformed(matrix));
}

Das klappt auch ganz gut, aber leider eiert der Pfeil. Das Problem liegt wohl am QT Koordinatensystem. Für das QLabel mylabel ist praktisch der Urpsrung (0/0) die linke obere Ecke des Labels. Da das Image ja auf das Label gezeichnet wird, eiert das Ding, wie ein Quadrat das um die linke obere Ecke gedreht wird. Alle 90° erreicht es die Position, die es haben sollte.
Ich müsste also QT jetzt beibringen, dass (nur) für dieses Label, der Nullpunkt an den QT-Koordinate 16/16 sein soll (da der Pfeil ne Auflösung von 32x32 Pixel hat).

Mit matrix.translate(16,16) habe ich es bereits versucht - hat nicht geklappt :(
Hat jemand noch ne Idee?
 
also ich mein bei C++ ist 0,0 die linke untere ecke nicht die oben links, zumindest bei MFC. ich vertu mich da auch andauernd

sachma wie die funktionen rotate und so funktionieren , hab schon nen jahr nixmehr mit c++ gemacht aber vielleicht kann ich trotzdem helfen
 
Zuletzt bearbeitet von einem Moderator: (Doppelpost zusammengeführt)
(0,0) ist links oben, da es um QT geht. Und wie rotate geht, hat nicht viel mit C zu tun, weil auch das QT ist :P
 
Hmm versuch mal 2 verschienden Matrizen zu verwenden. Eine für die Rotation und eine für die Translation. Die multiplizierst du zu einer 3ten Matrix (translation*rotation) mit der du
dann die Operation auf das Bitmap durchführst.

Edit: So ich hab das mal selbst ausprobliert ... tja ohne vorherige Translation in den Mittelpunkt, dann Rotation und dann wieder Translation in die Originalposition ist das durchaus problematisch zu realisieren. Das ist schlecht das die Translation nicht funktioniert, wir aber damit zusammenhängen das es in einem Bitmap keine negativen Koordinaten gibt. Man muss das Bitmap irgentwie auf ein Element bringen mit dem dies möglich ist. Der Träger wird dann zentriert bevor er rotiert wird und aus dem Ergebnis muss dann ein Bitmap erstellt werden, welches dann auch das Label gezeichnet wird.
 
Zuletzt bearbeitet:
raiden schrieb:
Hmm versuch mal 2 verschienden Matrizen zu verwenden. Eine für die Rotation und eine für die Translation. Die multiplizierst du zu einer 3ten Matrix (translation*rotation) mit der du
dann die Operation auf das Bitmap durchführst.

Edit: So ich hab das mal selbst ausprobliert ... tja ohne vorherige Translation in den Mittelpunkt, dann Rotation und dann wieder Translation in die Originalposition ist das durchaus problematisch zu realisieren. Das ist schlecht das die Translation nicht funktioniert, wir aber damit zusammenhängen das es in einem Bitmap keine negativen Koordinaten gibt. Man muss das Bitmap irgentwie auf ein Element bringen mit dem dies möglich ist. Der Träger wird dann zentriert bevor er rotiert wird und aus dem Ergebnis muss dann ein Bitmap erstellt werden, welches dann auch das Label gezeichnet wird.

Danke für Deine Mühe. Ich seh, ich hab mir da was aufgehalst. Ich denke ich werde auf die QPainter ausweichen. Dann zeichne ich halt keinen schönen Pfeil sondern ein Dreieck. Das kann ich dann wenigstens drehen wie ich will. Da gibts auch ein par Tutorials dazu.
Fürn Testzweck ist es egal. Vielleicht hab ich damit mehr Glück.

Falls noch jemandem was einfällt, immer gern... :) - und frohe Ostern!
 
Ok so sollte das ganze Funktionieren.
Das wackeln entsteht dadurch das wenn du den Pfeil rotierierst das Bild breiter/höher wird.

Code:
#ifndef QTTEST_H
#define QTTEST_H

#include <QtGui/QMainWindow>
#include <QPixmap>
#include <QLabel>
#include <QTimer>
#include <QMatrix>
#include <QPainter>

class QTTest : public QMainWindow
{
    Q_OBJECT

public:
    QTTest(QWidget *parent = 0, Qt::WFlags flags = 0);
    ~QTTest();

protected:
	QPixmap image;
	QPixmap *rotated_image;
	QLabel *mylabel;
	QTimer update_timer;
	int rotation;
public slots:
	void update();

};

#endif // QTTEST_H

Code:
#include "qttest.h"

QTTest::QTTest(QWidget *parent, Qt::WFlags flags)
    : QMainWindow(parent, flags)
{
    setFixedSize(32, 32);
    this->setBackgroundColor(QColor(255, 255, 255));
    setPalette(QPalette(QColor(250, 250, 200)));
    setAutoFillBackground(true);

    mylabel = new QLabel(this);
    mylabel->setBaseSize(32,32);
    mylabel->resize(32,32); 
    image = QPixmap("uparrow.png");
    
    mylabel->move(0, 0);
    mylabel->show();

    rotated_image = new QPixmap(32,32);
	
    connect(&update_timer, SIGNAL(timeout()), this, SLOT(update()));

    update_timer.setInterval(10);
    update_timer.start();
}

QTTest::~QTTest()
{

}

void QTTest::update()
{
	QPainter painter(rotated_image);
	QPointF center(image.width()/2.0, image.height()/2.0);

	rotation = ++rotation % 360;
	
	painter.fillRect(rotated_image->rect(), QBrush(QColor(255, 255, 255, 255)));

	painter.translate(center);
	painter.rotate(rotation);
	painter.translate(-center);
	
	painter.drawPixmap(0,0,image);

	mylabel->setPixmap(*rotated_image);
}
 
Ich hab das ganze heute Nachmittag mit der QPainter Klasse gemacht. Läuft gut und ist recht kurz *fg*:

Code:
void SimField::paintEvent(QPaintEvent * /* event */)
{
        QPainter painter(this);
        painter.translate(x,y);
        painter.setRenderHint(QPainter::SmoothPixmapTransform);
        painter.rotate(direction);
        painter.drawImage(QRect(-16,-16,32,32), QImage("resources/uparrow.png"));
}

(x/y) ist der aktuelle Koordinatenpunkt, an dem gezeichnet werden soll. Das PNG Bild hat ne Auflösung von 32x32 Pixel. Daher schiebe ich es in der letzten Zeile um je -16. Damit hab ich den Koordinateursprung, wo ich ihn haben will.
Die Variable "direction" gibt den Winkel an, um das das Ding gedreht werden soll. Mit update() in ner anderen Methode kann ich damit das Ding aktualisieren - läuft prächtig :)

Danke Dir nochmal!
 
Zurück
Oben