问题
As the title says I am trying to have my QGraphicsView
blinking 1 second in red, 1 second in green and 1 second in blue and after that the loop start over again. After doing a lot of research in the past couple of days I didn't have a lot of luck as the main problem is that I am not sure I need to subclass QGraphicsView
to obtain the effect I am looking for. I came across some references that I inserted below saying that for this type of problems QPropertyAnimation
seems to be the right direction. Although setting a QTimer
could also be a choice.
Below the small verifiable example. I wrote minimal code:
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();
}
In case you would like to see the .ui
I am also sharing the file:
<?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>
I have been researching the possibility to have a QGraphicsView
blinking 1 second in red, 1 second in green and 1 second in blue and after that the loop start over again.
The only source I was able to find providing a complete example was in PyQt
, for which I am not familiar with. The source is here and also this one.
The most important clue I got out of these examples is that, in particluar the last one, uses QState
and QStateMachine
. I am not familiar at all with these two features of Qt
though and am struggling a little bit because of that.
Also I came across this partial example, and the good thing of this is that I learned how to set the QTimer
useful for the 1s interval blinking.
Also because I am dealing with a QGraphicsView
I have the feeling that void paintEvent(QPaintEvent *) override
should be used.
Thank you very much for pointing in the right direction and solve this issue.
回答1:
Use QPropertyAnimation
is a problem here because the list of supported type is:
Int, UInt, Double, Float, QLine, QLineF, QPoint
QPointF, QSize, QSizeF, QRect, QRectF, QColor
And if you look the available properties of the QGraphicsView
class hierarchy
QWidget
propertiesQFrame
propertiesQAbstractScrollArea
propertiesQGraphicsView
properties
There is no interesting properties to pass to the QPropertyAnimation
because QPalette
and QString
is not supported to play with setPalette()
and styleSheet()
and there is no variable to directly change the background color.
A solution is to 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());
}
来源:https://stackoverflow.com/questions/61532355/how-to-make-a-qgraphicsview-background-blinking-in-r-g-b-every-second