Qt Graphics: the painting of a QImage is very pixelated - qt

I'm drawing my game's board using QPainter and QImage but it's very pixelated and I don't understand why.
Pixelated board:
Actual pictures used:
Code:
Loading of the picture part:
QImage desert_pic = QImage(":/images/graphics/pi.png");
c_mapicons.insert({type, desert_pic});
Painting part:
QRectF source(0.0, 0.0, 500.0, 500.0);
painter->drawImage(boundingRect(), c_mapicons.at(m_gameobject->getType()), source);
The pictures are 500x500 png files.
What I've tried (with no success):
Using svg files
Using QPixmap instead of QImage
QPainter::RenderHint(QPainter::Antialiasing)
QPainter::RenderHint(QPainter::SmoothPixmapTransform)
How can I get my pictures to appear smooth like in the second screenshot?

I managed to solve the problem by resizing to the size of my tiles before painting. More details here: Qt resize image with best quality

If you are willing to use SVGs, here's a way to do it:
In your .pro-File: QT += core gui svg
header
#include <QtSvg>
class Board: public QGraphicsItem{
public:
Board();
~Board();
QRectF boundingRect() const override;
void paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget = nullptr) override;
QGraphicsSvgItem *item;
};
cpp
Board::Board(){
item = new QGraphicsSvgItem("folder/icon.svg");
item->setParentItem(this);
item-> ... /// set Pos() and so on here
}
You can set Antialiasing in your QGraphicsView as well, then all items will take the effect: QGraphicsView::setRenderHint(QPainter::Antialiasing)

Related

How can I load a QPaintedTextureImage into a QTextureMaterial?

I am using Qt3D to create a 360 deg panorama viewer where the image in equirectangular format is loaded over the mesh of a sphere with negative radius. The problem is that I need to load the texture from memory, instead of a file.
In order to achieve that, I developed a custom QPaintedTextureImage with paint() overloaded to draw from a QImage. It works, but only when plugged into a QDiffuseMapMaterial. Since I don't want any light effect (just the original color of the pixels) it seems that QTextureMaterial would be the right choice, but I don't know how to do that.
Any idea?
Got it!
class MyQPaintedTextureImage : public Qt3DRender::QPaintedTextureImage
{
private:
QImage image;
public:
void setImage(QImage &i){
image = i;
setSize(i.size());
}
virtual void paint(QPainter *painter) override{
painter->drawImage(0, 0, image);
}
};
And then:
auto *image = new MyQPaintedTextureImage;
image->setImage(i);
auto *planeMaterial = new Qt3DExtras::QTextureMaterial;
planeMaterial->texture()->addTextureImage(image);
m_sphereEntity->addComponent(planeMaterial);

Qt: How to draw a QRect on top of a QGraphicsVideoItem?

I have a subclass of a QGraphicsObject. In this class, I use a QMediaPlayer with a QGraphicsVideoItem to play a video. I am trying to draw on top of the video.
class MyClass : public QGraphicsObject
{
Q_OBJECT;
public slots:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
public:
QGraphicsVideoItem *_movie_item;
QMediaPlayer *_movie_player;
}
In the paint method, I want to draw a red rectangle on top of _movie_item. To try to do this, I call:
void MyClass::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
_movie_item->setVisible(true);
_movie_item->play();
painter->fillRect(startx, starty, size, size, Qt::red);
}
The red rectangle gets drawn in the appropriate place, but it is always underneath the _movie_item.
Is there a way to draw a rectangle on top of the _movie_item without creating another QGraphicsItem, like:
QGraphicsRectItem *_rect = new QGraphicsRectItem(_movie_item)
Thanks.
Using QGraphicsItem::ItemStacksBehindParent flag may help.
From the docs:
The item is stacked behind its parent. By default, child items are
stacked on top of the parent item. But setting this flag, the child
will be stacked behind it. This flag is useful for drop shadow effects
and for decoration objects that follow the parent item's geometry
without drawing on top of it. This flag was introduced in Qt 4.5.
_movie_item->setFlag(QGraphicsItem::ItemStacksBehindParent);

QwtPlot - How to customize the footer?

What is the meaning of the label in the yellow rectangle? How to remove (hide) it?
I'm working with Qwt 6.0.1 and Qt 4.8.6
I've found, looking deep in the code, that the label is not part of a standard QwtPlot. It's a custom label and it's created using the following method of the QwtText class:
void draw( QPainter *painter, const QRectF &rect ) const;
Pseudo-code:
void MyQwtPlot::drawCustomLabel()
{
QPainter painter(this);
QwtText label(<label-text>);
label.draw(&painter, QRectF(<label-position>));
painter.end();
}
where MyQwtPlot is a class that extends QwtPlot.
I've solved commenting the drawCustomLabel method in my implementation.

Paint a QGraphicsItem to a QImage without needing a scene/view

So here's what I'm trying to do - Using a custom QGraphicsItem, I have my QPainter setup to paint into a QImage, which I then save to a file (or just keep the QImage in memory until I need it).
The issue I've found is that QGraphicsItem::paint() is only called if the QGraphcsItem belongs to a scene, the scene belongs to a view, AND the view and scene are not hidden.
Here's the code outside my project for testing purposes:
MyQGfx Class
void MyQGfx::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
qDebug() << "begin of paint function";
QRectF rec = boundingRect();
QImage image(boundingRect().size().toSize(),
QImage::Format_ARGB32_Premultiplied);
image.fill(0);
// construct a dedicated offline painter for this image
QPainter imagePainter(&image);
imagePainter.translate(-boundingRect().topLeft());
// paint the item using imagePainter
imagePainter.setPen(Qt::blue);
imagePainter.setBrush(Qt::green);
imagePainter.drawEllipse(-50, -50, 100, 100);
imagePainter.end();
if(image.save("C://plot.jpg"))
{
qDebug() << "written";
}
else {
qDebug() << "not written";
}
}
MainWindow Class
....
QGraphicsView* view = new QGraphicsView(this);
QGraphicsScene* scene = new QGraphicsScene(this);
view->setScene(scene);
MyQGfx* gfx = new MyQGfx();
scene->addItem(gfx);
gfx->update();
....
This all works fine, but I don't want a view/scene necessary, as it would be displayed on the mainwindow - is there any way around this?
Can't you just create a custom method accepting a QPainter, one painting on a QImage and one on your item?

setpixel of QGraphicsScene in Qt

It's simple to draw line or ellipse just by using scene.addellipse(), etc.
QGraphicsScene scene(0,0,800,600);
QGraphicsView view(&scene);
scene.addText("Hello, world!");
QPen pen(Qt::green);
scene.addLine(0,0,200,200,pen);
scene.addEllipse(400,300,100,100,pen);
view.show();
now what should i do to set some pixel color? may i use a widget like qimage? by the way performance is an issue for me.thanks
I think that performing pixel manipulation on a QImage would slow down your application quite a lot. A good alternative is to subclasse QGraphicsItem in a new class, something like QGraphicsPixelItem, and implement the paint function like this:
// code untested
void QGraphicsPixelItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0)
{
painter->save();
foreach(const QPoint& p, pointList) {
// set your pen color etc.
painter->drawPoint(p);
}
painter->restore();
}
where pointList is some kind of container that you use to store the position of the pixels you want to draw.

Resources