简体   繁体   English

定期使用QPainter绘图

[英]Drawing using QPainter periodically

I'm attempting to create a simple animation in Qt through QPainter, currently i've been able to draw in my window, but i'm unable to figure out how i could draw the same thing periodically. 我试图通过QPainter在Qt中创建一个简单的动画,目前我已经能够在窗口中绘制,但是我无法弄清楚如何定期绘制相同的东西。

Here's my current code: 这是我当前的代码:

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();

I've tried creating a thread, but i can't create a QApplication outside of main and if i try to give my painter, label, picture and pen to a thread, then it won't compile as they are private: 我尝试创建一个线程,但是我不能在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();

How would a sample code that draws anything (lines/ellipses) using Qpainter every X milliseconds look like? 每隔X毫秒使用Qpainter绘制任何内容(线条/椭圆)的示例代码会如何?

There's this crazy disease going on, where people automatically associate periodic/timed task with multithreading. 有一种疯狂的疾病正在发生,人们自动将定期/定时任务与多线程相关联。 You need nothing of the sort - just use a timer: 您不需要任何种类-只需使用计时器即可:

// 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"

Now - if you think you need to - you can do the drawing in a worker thread from the thread pool. 现在-如果您认为需要-您可以在线程池中的工作线程中绘制图形。 Replace the connection with: 将连接替换为:

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

Ensure that draw() is thread-safe, or that you otherwise don't modify the source object concurrently from the main thread without proper synchronization. 确保draw()是线程安全的,否则请不要在没有正确同步的情况下从主线程并发修改source对象。

I eventually worked out on a clean solution, adding support for reading keypresses aswell: 我最终制定了一个干净的解决方案,并增加了对按键读取的支持:

main.cpp 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 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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM