PDA

View Full Version : QPainter doesn't seem to draw QImage



Denarius
3rd March 2009, 07:27
Hello,
I want to draw a QImage based off of a PNG file.
It compiles fine, but it doesn't show my PNG file.

Here's the piece of code I use:

The .h


#ifndef DRAWINGMAP_H
#define DRAWINGMAP_H

#include <QtGui/QWidget>
#include "ui_drawingmap.h"
#include <QtCore/QList>
#include <QtGui/QImage>

struct myPos2D
{
int x;
int y;
int yaw;
};

class DrawingMap : public QWidget
{
Q_OBJECT

public:
DrawingMap(QWidget *parent = 0);
~DrawingMap();

public slots:
void setPos(int x , int y , int yaw);
void setRobotDiameter(int diameter);

protected:
void paintEvent(QPaintEvent *event);


private:
Ui::DrawingMapClass ui;

int x_pos, y_pos, yaw;
int robotDiameter;
int zoom;

QImage robotImage;

QList<myPos2D> positionList;

};

#endif // DRAWINGMAP_H



The .cpp


#include "drawingmap.h"

#include <QtGui/QPainter>

DrawingMap::DrawingMap(QWidget *parent)
: QWidget(parent)
{
x_pos = y_pos = yaw = 0;
robotDiameter = 10;
zoom = 1;

ui.setupUi(this);
}

DrawingMap::~DrawingMap()
{

}

void DrawingMap::paintEvent(QPaintEvent * /* event */)
{
myPos2D newPos; //this is a struct with int x, int y, int yaw

newPos.x = x_pos;
newPos.y = y_pos;
newPos.yaw = yaw;

int oldX = 0, oldY = 0;

positionList.append(newPos); //This is a QList

QPainter painter(this);

painter.setPen(Qt::SolidLine);
painter.setPen(Qt::red);

painter.translate(rect().width()/2, rect().height()/2);

//draw the robot trail
for(int i = 0; i < positionList.size(); i++)
{
//draw trail
painter.drawLine(oldX * zoom , oldY * zoom, positionList.at(i).x * zoom, positionList.at(i).y * zoom);

//remember old positions
oldX = positionList.at(i).x;
oldY = positionList.at(i).y;
}

painter.setPen(Qt::NoPen);
painter.setBrush(Qt::blue);

//Get and correct image
robotImage = QImage("myPNGfile.png"); //robotImage is a QImage
robotImage.convertToFormat(QImage::Format_ARGB32_P remultiplied ,Qt::ColorOnly);
//robotImage.createMaskFromColor(0x00000000,Qt::Mask OutColor); // make black transparent

//Go to correct position
painter.translate(x_pos * zoom, y_pos * zoom);
painter.rotate(yaw);
//draw the robot
painter.drawImage(0 , 0 , robotImage);

/*
painter.drawPie(QRect((-robotDiameter/2) * zoom, (-robotDiameter/2) * zoom, robotDiameter * zoom, robotDiameter * zoom), 0, 360 * 16);
painter.setPen(Qt::SolidLine);
painter.drawLine(0 , 0, 0 , (robotDiameter + robotDiameter/4) * zoom );
*/
}

void DrawingMap::setPos(int x , int y , int ya)
{
x_pos = x;
y_pos = y;
yaw = ya;

update();
}

void DrawingMap::setRobotDiameter(int diameter)
{
zoom = diameter;
update();
}



The .h from the .ui file Qt spit out


/************************************************** ******************************
** Form generated from reading ui file 'drawingmap.ui'
**
** Created: Mon Mar 2 11:22:28 2009
** by: Qt User Interface Compiler version 4.4.3
**
** WARNING! All changes made in this file will be lost when recompiling ui file!
************************************************** ******************************/

#ifndef UI_DRAWINGMAP_H
#define UI_DRAWINGMAP_H

#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QWidget>

QT_BEGIN_NAMESPACE

class Ui_DrawingMapClass
{
public:

void setupUi(QWidget *DrawingMapClass)
{
if (DrawingMapClass->objectName().isEmpty())
DrawingMapClass->setObjectName(QString::fromUtf8("DrawingMapClass"));
DrawingMapClass->resize(400, 300);

retranslateUi(DrawingMapClass);

QMetaObject::connectSlotsByName(DrawingMapClass);
} // setupUi

void retranslateUi(QWidget *DrawingMapClass)
{
DrawingMapClass->setWindowTitle(QApplication::translate("DrawingMapClass", "DrawingMap", 0, QApplication::UnicodeUTF8));
Q_UNUSED(DrawingMapClass);
} // retranslateUi

};

namespace Ui {
class DrawingMapClass: public Ui_DrawingMapClass {};
} // namespace Ui

QT_END_NAMESPACE

#endif // UI_DRAWINGMAP_H



The slots are used so that I can change the robot position and direction.
This QWidget is inserted in another QWidget which is the main window in my program.
I inserted my custom QWidget with Qt Designer and promoted the widget.
So it should be all standard Qt Designer code

It paints the Lines just fine.
And the very simple representation of the robot as well, that is the blue dot I commented out of the program.

caduel
3rd March 2009, 07:51
have you checked that/if
a) the image is found (maybe its in a subdirectory or in a resource (":/...") )
b) your Qt supports png
c) the file is a png (not a gif just named png... happened to me once ;-)


side note: for performance reasons I would move the loading/converting of the image out of the paintEvent (maybe into the widget's constructor)

Denarius
3rd March 2009, 08:01
have you checked that/if
a) the image is found (maybe its in a subdirectory or in a resource (":/...") )
b) your Qt supports png
c) the file is a png (not a gif just named png... happened to me once ;-)


side note: for performance reasons I would move the loading/converting of the image out of the paintEvent (maybe into the widget's constructor)

a) yes it's found. otherwise it would give me a compiler error stating that it didn't find the image. ;)
b) How do you check this? :o
The Qt api states that it supports PNG files, so would this be the answer?
c) the file extension is .png So I'm pretty shure it's a png ;)
I also tried the GIF extension etc. But no luck, same problem

i'll do the performance later. I just want the image to draw first.

Denarius
3rd March 2009, 08:20
Ahw,
I found the problem.
i had to put a ./ before the whole path

talk2amulya
3rd March 2009, 08:58
so caduel was right :) image file wasnt found..u r using a qrc file so it wont give a compilation error if the file isnt found..all will be done at compile time

Denarius
3rd March 2009, 09:21
new problem.

I've changed the code for drawing the image file to this:


//Correct image
robotImage.convertToFormat(QImage::Format_ARGB32_P remultiplied ,Qt::AutoColor);
//robotImage.createMaskFromColor(0x00000000,Qt::Mask OutColor); // make black transparent
robotImage.scaled(robotDiameter * zoom, robotDiameter * zoom , Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
int offset_x = -robotImage.width() / 2;
int offset_y = -robotImage.height() / 2;

//Go to correct position
painter.translate(x_pos * zoom, y_pos * zoom);
painter.rotate(yaw);
//draw the robot
painter.drawImage(offset_x , offset_y , robotImage, 0 , 0 , robotImage.width() * zoom , robotImage.height() * zoom);


But it doesn't resize or rescale the image.
Or am I missing something?:confused:

P.S.
I loaded the image in the constructor now. Thanks for the suggestion :D

^NyAw^
3rd March 2009, 10:35
Hi,

You are scaling the image but you don't store the returning image of the method to any variable:



robotImage.scaled(robotDiameter * zoom, robotDiameter * zoom , Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);

to:



QImage qScaledImage = robotImage.scaled(robotDiameter * zoom, robotDiameter * zoom , Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);

Then you have to paint "qScaledImage"

Denarius
3rd March 2009, 14:12
Hi,

You are scaling the image but you don't store the returning image of the method to any variable:



robotImage.scaled(robotDiameter * zoom, robotDiameter * zoom , Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);

to:



QImage qScaledImage = robotImage.scaled(robotDiameter * zoom, robotDiameter * zoom , Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);

Then you have to paint "qScaledImage"

This worked like a charm.
Thank you very much