如何使 QGraphicsView 背景每秒以 R-G-B 闪烁

How to make a QGraphicsView background blinking in R - G - B every second

正如标题所说,我正在尝试让我的 QGraphicsView 以红色闪烁 1 秒,以绿色闪烁 1 秒,以蓝色闪烁 1 秒,然后循环重新开始。在过去几天做了很多研究之后,我没有太多运气,因为主要问题是我不确定我是否需要继承 QGraphicsView 以获得我正在寻找的效果。我遇到了一些我在下面插入的参考资料,说对于这类问题 QPropertyAnimation 似乎是正确的方向。尽管设置 QTimer 也是一种选择。

下面是可验证的小例子。我写了最少的代码:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QPropertyAnimation>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    QGraphicsView *mView;
    QGraphicsScene *mScene;
    QPropertyAnimation *mAnimation;
};
#endif // MAINWINDOW_H

**mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTimer>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    mView = new QGraphicsView();
    mScene = new QGraphicsScene();
    ui->graphicsView->setScene(mScene);
    // Starting with a gray background
    ui->graphicsView->setBackgroundBrush(QColor(Qt::gray));

    // Setting a timer that changes the color every second
    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(update()));
    timer->start(1000);

}

MainWindow::~MainWindow()
{
    delete ui;
}

mygraphicsview.h

#ifndef MYGRAPHICSVIEW_H
#define MYGRAPHICSVIEW_H
#include <QGraphicsView>
class MyGraphicsView : public QGraphicsView
{
public:
    MyGraphicsView();
};

#endif // MYGRAPHICSVIEW_H

**mygraphicsview.cpp

#include "mygraphicsview.h"

MyGraphicsView::MyGraphicsView()
{}

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

如果你想看 .ui 我也分享文件:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>277</width>
    <height>228</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QGridLayout" name="gridLayout">
    <item row="0" column="0">
     <widget class="QGraphicsView" name="graphicsView"/>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>277</width>
     <height>22</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

我一直在研究让 QGraphicsView 以红色闪烁 1 秒,以绿色闪烁 1 秒,以蓝色闪烁 1 秒,然后循环重新开始的可能性。

我能找到的提供完整示例的唯一来源是 PyQt,对此我并不熟悉。来源是 and also .

我从这些例子中得到的最重要的线索是,特别是最后一个,使用了 QStateQStateMachine。不过,我对 Qt 的这两个功能一点都不熟悉,因此我有点挣扎。

我还遇到了 this 部分示例,这样做的好处是我学会了如何设置 QTimer 对 1s 间隔闪烁有用。

也因为我处理的是QGraphicsView,感觉应该用void paintEvent(QPaintEvent *) override

非常感谢您指出正确的方向并解决了这个问题。

这里使用QPropertyAnimation是个问题,因为支持的类型列表是:

Int, UInt, Double, Float, QLine, QLineF, QPoint
QPointF, QSize, QSizeF, QRect, QRectF, QColor

如果您查看 QGraphicsView class 层次结构的可用属性

QWidget properties
QFrame properties
QAbstractScrollArea properties
QGraphicsView properties

没有有趣的属性传递给 QPropertyAnimation 因为 QPaletteQString 不支持与 setPalette()styleSheet() 一起玩没有变量可以直接改变背景颜色


一个解决办法是subclass QGraphicsView:
graphicsview.h:

#ifndef GRAPHICSVIEW_H
#define GRAPHICSVIEW_H

#include <QGraphicsView>
#include <QTimer>

class GraphicsView : public QGraphicsView
{
    Q_OBJECT
public:
    GraphicsView(QWidget *parent = nullptr);

protected:
    void paintEvent(QPaintEvent *evt) override;

private slots:
    void changeBackgroundColor();

private:
    int color_index;
    QTimer timer;
    const QColor colors[3] = { Qt::red, Qt::green, Qt::blue };

};

#endif // GRAPHICSVIEW_H

graphicsview.cpp:

#include "graphicsview.h"

GraphicsView::GraphicsView(QWidget *parent)
    : QGraphicsView(parent)
{
    color_index = -1;
    connect(&timer, SIGNAL(timeout()), this, SLOT(changeBackgroundColor()));
    timer.start(1000);
}

void GraphicsView::paintEvent(QPaintEvent *evt)
{
    QGraphicsView::paintEvent(evt);

    QPainter painter(viewport());
    painter.fillRect(viewport()->rect(), colors[color_index]);
}

void GraphicsView::changeBackgroundColor()
{
    if (color_index == 2){
        color_index = 0;
    } else {
        color_index++;
    }
    viewport()->update(rect());
}