1
votes

Drawing on a widget in Qt is simple. First you create a QPixmap, assign a QPainter to it, draw with the QPainter, and at the end set the pixmap to the widget. For example,

QPixmap pixmap(ui->label->width(), ui->label->height());
pixmap.fill(background_color);
QPainter painter(&pixmap)
painter.setpen(foreground_color);
//painter.drawLine(....) etc.
ui->label->setPixmap(pixmap);

So far so good.

However, what if the pixmap is very large, and I have to change a very small portion of it very often? In my case I profiled it to be my bottleneck. Instead of creating a new pixmap and copying the old onto it, we can load the existing pixmap and only make the necessary changes to it. However, it is also still very slow.

Pixmap pixmap = *(ui->label->pixmap());  // takes almost zero time
QPainter painter(&pixmap);               // takes up 40% of the time
//draw stuff with painter                // takes almost zero time
ui->label->setPixmap(pixmap);            // takes up 60% of the time

Even if I re-use the painter so that I don't have to create it again every time, I still have to call setPixMap(pixmap), otherwise the image is not refreshed.

Is there a way around it?

Must I embed an OpenGL window or something similar, or is there a way with just using native Qt classes? Note, that the change in the image is very small and takes up an insignificant amount of time, it's the redrawing of the whole pixmap which is time-consuming. As I don't know beforehand where I'll be making the changes, splitting the pixmap up onto multiple small labels would be very complicated.

1
Please update the question with more information on what you're doing. As it is, we can only make assumptions, which we've ascertained are not correct. - TheDarkKnight
@TheDarkKnight : what information are you interested in? My problem is that calling setPixmap can take up to several hundred ms even if I only changed a few pixels in the pixmap, and I'm looking for a way to refresh the displayed image either without calling setPixmap, or in any other way which shouldn't take that much time. The problem is not necessarily when and how often the change is needed, but the individual update time itself is a problem. - vsz

1 Answers

1
votes

If you're using a large QLabel, then it would be better using a QGraphicsScene and QGraphicsView.

The scene allows you to add items, and the view is a widget which is like a window looking into the scene.

You could start by adding a QGraphicsPixmapItem, but I think you'd be better off deriving from QGraphicsItem, storing a QPixmap and rendering the image in its paint function.

Here's an example of the derived class header

class MyImage : public QGraphicsItem
{
    public:
        MyImage(QGraphicsItem* parent);

        QRectF boundingRect();

        void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0);

     protected:
         void QGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent * event)

     private:
         QPixmap m_pixmap;
}

In the paint function, use the QPainter to draw m_pixmap;