Hi,
I intend to create a custom scatterplot using the graphics view/scene/item framework.
I am stuck with adding a feature that animates the scale of a custom ellipse item if selected.
There should be two ways for selecting the item: by rubber band selection and/or by left mouse click.
I have two questions:
- Why does the property animation not start if the:
- animate function is in the constructor?
- item is selected with the rubberband selection?
Please feel free to comment on the general structure (choises of classes or animation approach or for ex.) of the programm as well.
I am very new to Qt programming and still a bit overwhelmed by it.
Here is my code:
#ifndef MYELLIPSE_H
#define MYELLIPSE_H
#include <QPainter>
#include <QGraphicsObject>
#include <QPropertyAnimation>
#include <QGraphicsSceneMouseEvent>
#This class is a simple ellipse that should change it's color and start to animate it's scale once selected
#and stop if "unselected". It should be selectable with either a mousclick on it, or if in the rectangle of a rubberband.
#I chose the QGraphicsObject as the base class, because it works well with the
#QPropertAnmiation class
#I am aware of the QGraphicsItemAnimation, but it came to my attention that
#it became obsolete and is not supprted anymore.
class myEllipse : public QGraphicsObject
{
Q_OBJECT
public:
myEllipse
(QRectF red
): rect
(rec
) {
setFlag(ItemIsSelectable, true);
setAcceptHoverEvents(true);
_hover = false;
_pressed = false;
#Does not work.
#However if I put the animate function into the
#mousePressedEvent it animates if I click with the mouse on it,
#but not if it's selected with the rubber band.
#What I don't understand is that since it changes it's color when selected with the
#rubberband why it does not start the animation.
if (this->isSelected()) {
animate();
}
#constructor end
}
~myEllipse(){}
QRectF boundingRect
() const { return rect;
}
#This is working fine. Wheather I hover or click with the mouse over it
#or put it in the rectangle of a rubber band, it alsways changes it's color.
#Hence I assume that all three selection mode should be working.
if (isSelected() || _hover)
{
painter->setPen(Qt::darkGray);
} else {
painter->setPen(Qt::black);
}
painter->drawEllipse(rect);
}
protected:
#change color of pen if hover over
#change color of pen back to black
#select item and start animation
_pressed = true;
if (ev->MouseButtonPress)
{
setSelected(true);
#animate();
}
}
private:
bool _hover;
bool _pressed;
void animate(){
QPropertyAnimation *animation = new QPropertyAnimation(this, "scale");
animation->setDuration(1000);
animation->setStartValue(0.0);
animation->setEndValue(1.0);
animation->setLoopCount(10);
animation->start();
}
};
#endif // MYELLIPSE_H
#ifndef MYELLIPSE_H
#define MYELLIPSE_H
#include <QPainter>
#include <QGraphicsObject>
#include <QPropertyAnimation>
#include <QGraphicsSceneMouseEvent>
#This class is a simple ellipse that should change it's color and start to animate it's scale once selected
#and stop if "unselected". It should be selectable with either a mousclick on it, or if in the rectangle of a rubberband.
#I chose the QGraphicsObject as the base class, because it works well with the
#QPropertAnmiation class
#I am aware of the QGraphicsItemAnimation, but it came to my attention that
#it became obsolete and is not supprted anymore.
class myEllipse : public QGraphicsObject
{
Q_OBJECT
public:
myEllipse(QRectF red): rect(rec)
{
setFlag(ItemIsSelectable, true);
setAcceptHoverEvents(true);
_hover = false;
_pressed = false;
#Does not work.
#However if I put the animate function into the
#mousePressedEvent it animates if I click with the mouse on it,
#but not if it's selected with the rubber band.
#What I don't understand is that since it changes it's color when selected with the
#rubberband why it does not start the animation.
if (this->isSelected()) {
animate();
}
#constructor end
}
~myEllipse(){}
QRectF boundingRect() const { return rect; }
void paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget) {
#This is working fine. Wheather I hover or click with the mouse over it
#or put it in the rectangle of a rubber band, it alsways changes it's color.
#Hence I assume that all three selection mode should be working.
if (isSelected() || _hover)
{
painter->setPen(Qt::darkGray);
} else {
painter->setPen(Qt::black);
}
painter->drawEllipse(rect);
}
protected:
#change color of pen if hover over
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *) { _hover = true; update(); }
#change color of pen back to black
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *) { _hover = false; update(); }
#select item and start animation
virtual void mousePressEvent(QGraphicsSceneMouseEvent *){
_pressed = true;
if (ev->MouseButtonPress)
{
setSelected(true);
#animate();
}
}
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *){ _pressed = false; update(); }
private:
QRectF rect;
bool _hover;
bool _pressed;
void animate(){
QPropertyAnimation *animation = new QPropertyAnimation(this, "scale");
animation->setDuration(1000);
animation->setStartValue(0.0);
animation->setEndValue(1.0);
animation->setLoopCount(10);
animation->start();
}
};
#endif // MYELLIPSE_H
To copy to clipboard, switch view to plain text mode
And the mainWindow:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QGraphicsScene>
#include <QStandardItemModel>
#include <QStringList>
#include <QList>
#include "myellipse.h"
namespace Ui {
class MainWindow;
}
#The ui contains a tableView and a graphicsview item
{
Q_OBJECT
public:
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setupModel();
ui->tableView->setModel(model);
ui->graphicsView_2->setScene(myOtherScene);
setUpOtherScene();
}
~MainWindow();
private:
Ui::MainWindow *ui;
#Adds one custom graphics item from a standartitem model to the scene
void setUpOtherScene(){
int row = 0;
myEllipse
*ellipse
= new myEllipse
(QRectF(-10*(model
->data
(model
->index
(row,
1)).
toDouble()),
-10*(model->data(model->index(row,2)).toDouble()),
15, 15));
myOtherScene->addItem(ellipse);
}
#Create a table with Four categories (A,B,C,D) in the first column and random ints from 1 to 10
#in the second and third column.
void setupModel(){
myList << "A" << "B" << "C" << "D";
for (int row
= 0; row < model
->rowCount
(QModelIndex());
++row
) { myList[row]);
qrand()%10);
qrand()%10);
}
}
};
#endif // MAINWINDOW_H
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QGraphicsScene>
#include <QStandardItemModel>
#include <QStringList>
#include <QList>
#include "myellipse.h"
namespace Ui {
class MainWindow;
}
#The ui contains a tableView and a graphicsview item
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0): QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setupModel();
ui->tableView->setModel(model);
myOtherScene = new QGraphicsScene(this);
ui->graphicsView_2->setDragMode(QGraphicsView::RubberBandDrag);
ui->graphicsView_2->setScene(myOtherScene);
setUpOtherScene();
}
~MainWindow();
private:
Ui::MainWindow *ui;
QStringList myList;
QAbstractItemModel *model;
QGraphicsScene *myOtherScene;
#Adds one custom graphics item from a standartitem model to the scene
void setUpOtherScene(){
int row = 0;
myEllipse *ellipse = new myEllipse(QRectF(-10*(model->data(model->index(row,1)).toDouble()),
-10*(model->data(model->index(row,2)).toDouble()),
15, 15));
myOtherScene->addItem(ellipse);
}
#Create a table with Four categories (A,B,C,D) in the first column and random ints from 1 to 10
#in the second and third column.
void setupModel(){
myList << "A" << "B" << "C" << "D";
model = new QStandardItemModel(4,3,this);
for (int row = 0; row < model->rowCount(QModelIndex()); ++row) {
model->setData(model->index(row, 0, QModelIndex()),
myList[row]);
model->setData(model->index(row, 1, QModelIndex()),
qrand()%10);
model->setData(model->index(row, 2, QModelIndex()),
qrand()%10);
}
}
};
#endif // MAINWINDOW_H
To copy to clipboard, switch view to plain text mode
I tried to get this working for days now, with some success but I need some help to make it over the finish line.
Thank you many times.
Bookmarks