Rafał Apriasz
Rafał Apriasz

Reputation: 63

Continuously drawing object using Qt and C++

I have one problem which I can't solve using the Internet. I have label and I set pixmap on it. I put it on main window (widget) where is button (QPushButton) too. I want to do that:

  1. If I click on the button then on this pixmap will be drawn circles continuously
  2. If I click this button for second then drawing must be stopped by function pause()

The second one is easy, it's empty slot:

void pause() {}

But at first I've tried to use loop

while(true)
    draw();

but it crashed a program (loop).

Any idea how to solve it?

Upvotes: 0

Views: 360

Answers (2)

dtech
dtech

Reputation: 49329

You should never block the main thread. This will cause the OS to consider your application has hanged. In fact it is a good practice to move any code, whose execution takes more than 50 milliseconds to another thread to keep the main thread responsive, especially in the case of Qt, where it is also the GUI thread.

You should use an event driven approach, which will not block the thread.

class YourClass : public QObject { // QObject or derived
    Q_OBJECT
public:
    YourClass() { connect(&timer, &Timer::timeout, this, &YourClass::draw); }
public slots:
    void start() { timer.start(33); }
    void pause() { timer.stop(); }
private:
    QTimer timer;
    void draw() { ... }
};

When start() is invoked, draw() will be called every 33 miliseconds. pause() will effectively stop that until start() is invoked again. You can control the rate at which draw() is invoked by adjusting the timer's interval, by default it is 0, which in the case of drawing is overkill, you should adjust for a desired framers per second. In the example above, the it is 33 milliseconds, or roughly 30 FPS.

Upvotes: 4

LogicStuff
LogicStuff

Reputation: 19617

You should then call draw() with some time interval, instead of halting the whole GUI thread with it.

For that, there's QTimer:

QTimer timer; // should be a member, a pointer optionally - you then do new Qtimer(this);
connect(&timer, &QTimer::timeout, draw);
timer.start(500); // in milliseconds
// assuming you are calling this from member function of QObject-deriving class
// and draw is a non-member function

If you know to do the connections, you can connect it to anything...

The same can be done with QThread and putting it to sleep in that loop.

Anyhow, I don't get how an empty pause() stops the drawing. Aren't you halting your application again? Just do timer.stop();.

Upvotes: 2

Related Questions