定期使用QPainter绘图

时间:2017-05-26 12:00:24

标签: c++ qt

我正在尝试通过QPainter在Qt中创建一个简单的动画,目前我已经可以在我的窗口中绘制,但我无法弄清楚如何定期绘制相同的东西。

这是我目前的代码:

int main(int argc, char *argv[]){
QApplication a (argc, argv);
QLabel l;
Qpicture pi;
Qpainter p(&pi);
Qpen pen;
/*
Some ellipses and lines using p.drawLine and p.drawEllipse
*/
p.end();
l.setPicture(pi);
l.show();

return a.exec();

我已经尝试创建一个线程,但是我无法在main之外创建一个QApplication,如果我尝试将我的画家,标签,图片和笔放到一个线程中,那么它将无法编译,因为它们是私有的:

void PrintThread ( QLabel * l, QPicture * pi, Qpainter * p, QPen * pen){
    /*
    print lines and ellipses
    */
}

int main(int argc, char *argv[]){
QApplication a (argc, argv);
    QLabel l;
    Qpicture pi;
    Qpainter p(&pi);
    Qpen pen;
std::thread doPaint (PrintThread, l, pi, p, pen);
doPaint.join();

每隔X毫秒使用Qpainter绘制任何东西(线/椭圆)的示例代码怎么样?

2 个答案:

答案 0 :(得分:2)

这种疯狂的疾病正在发生,人们会自动将定期/定时任务与多线程相关联。你不需要那种 - 只需使用一个计时器:

// https://github.com/KubaO/stackoverflown/tree/master/questions/picture-async-44201102
#include <QtWidgets>
#include <QtConcurrent>

class PictureSource : public QObject {
   Q_OBJECT
public:
   QPicture draw() {
      QPicture pic;
      QPainter p(&pic);
      p.rotate(QTime::currentTime().msec()*360./1000.);
      p.drawLine(0, 0, 50, 50);
      pic.setBoundingRect({-50, -50, 100, 100});
      emit pictureChanged(pic);
      return pic;
   }
   Q_SIGNAL void pictureChanged(const QPicture &);
};
Q_DECLARE_METATYPE(QPicture)

int main(int argc, char ** argv) {
   QApplication app{argc, argv};
   qRegisterMetaType<QPicture>();
   QLabel label;
   PictureSource source;
   QObject::connect(&source, &PictureSource::pictureChanged,
                    &label, &QLabel::setPicture);
   source.draw();
   label.show();
   QTimer timer;
   timer.start(50); // every 50 ms
   QObject::connect(&timer, &QTimer::timeout, &source, &PictureSource::draw);
   return app.exec();
}
#include "main.moc"

现在 - 如果您认为需要 - 您可以从线程池中的工作线程中进行绘制。用以下内容替换连接:

  QObject::connect(&timer, &QTimer::timeout, [&source]{
    auto pool = QThreadPool::globalInstance();
    QtConcurrent::run(pool, [&source]{ source.draw(); });
  });

确保draw()是线程安全的,或者您没有在没有正确同步的情况下从主线程同时修改source对象。

答案 1 :(得分:0)

我最终选择了干净解决方案,增加了对阅读按键的支持:

的main.cpp

#include <QtWidgets>
#include <QApplication>
#include "screen.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    screen Screen;

    // size of your choice
    Screen.setFixedSize(1024,576);

    Screen.show();

    return a.exec();
}

screen.h

#ifndef SCREEN_H
#define SCREEN_H

#include <QWidget>
#include <QLabel>

class screen : public QLabel
{
    Q_OBJECT

public:
    screen();
    void keyPressEvent(QKeyEvent *);
    void keyReleaseEvent(QKeyEvent *);
public slots:
    void tick();
};

#endif // SCREEN_H

screen.cpp

#include "screen.h"

#include <QtWidgets>
#include <QTimer>

QPen pen;
QPicture pic;
QPainter p;

screen::screen(){

    QTimer * timer = new QTimer();
    connect(timer,SIGNAL(timeout()),this,SLOT(tick()));

    timer->start(16);
}
void screen::keyPressEvent(QKeyEvent *event)
{
    // event for key pressed
}

void screen::keyReleaseEvent(QKeyEvent *event)
{
    // event for key released
}

void screen::tick(){
    p.begin(&pic);

    // start draw



    // finish draw

    p.end();
    this->setPicture(pic);
}