Applying QPropertyAnimation to QRect - c++

I've created a QRect object
QRect ellipse(10.0 , 10.0 , 10.0 , 10.0);
QPainter painter(this);
painter.setBrush(Qt::red);
painter.drawEllipse(ellipse);
Now I want to animate it using QPropertyAnimation, but since it can only be applied to QObject objects(as far as I get it), I need to somehow convert QRect into QObject. Is there a way to do it?

No need to create a class, you can use your own widget, you must add a new property.
Example:
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QPaintEvent>
#include <QWidget>
class Widget : public QWidget
{
Q_OBJECT
Q_PROPERTY(QRect nrect READ nRect WRITE setNRect)
public:
explicit Widget(QWidget *parent = 0);
~Widget();
QRect nRect() const;
void setNRect(const QRect &rect);
protected:
void paintEvent(QPaintEvent *event);
private:
QRect mRect;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include <QPainter>
#include <QPropertyAnimation>
Widget::Widget(QWidget *parent) :
QWidget(parent)
{
QPropertyAnimation *animation = new QPropertyAnimation(this, "nrect");
//animation->setEasingCurve(QEasingCurve::InBack);
animation->setDuration(1000);
animation->setStartValue(QRect(0, 0, 10, 10));
animation->setEndValue(QRect(0, 0, 200, 200));
animation->start();
connect(animation, &QPropertyAnimation::valueChanged, [=](){
update();
});
}
Widget::~Widget()
{
}
QRect Widget::nRect() const
{
return mRect;
}
void Widget::setNRect(const QRect &rect)
{
mRect = rect;
}
void Widget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QRect ellipse(mRect);
QPainter painter(this);
painter.setBrush(Qt::red);
painter.drawEllipse(ellipse);
}
code

Related

Circle user avatar issue

I want to make QLabel with the image circle:
Code:
QLabel *label = new QLabel(this);
QPixmap avatarPixmap(":/Icon/default_avatar.png");
label->setPixmap(avatarPixmap);
label->setStyleSheet("border: 0.5px solid red; border-radius: 50%; background-clip: padding;");
It only rounds the QLabel, not the image. How to fix it? Thanks.
Update:
The only way is to override the paintEvent for QLabel
Code:
void AccountImage::paintEvent(QPaintEvent *event)
{
QPixmap pixmap(":/Icon/default_avatar.png");
QBrush brush(pixmap);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setBrush(brush);
painter.drawRoundedRect(0, 0, width(), height(), 100, 100);
QLabel::paintEvent(event);
}
The image is rounded but not properly scaled. Any ideas?
try to set mask on the label like:
int w = // set the width here
int h = // set the height here
QRect *rct = new QRect(0, 0, w, h);
QRegion *reg = new QRegion(*rct, QRegion::Ellipse);
label->setMask(*reg);
see: http://doc.qt.io/archives/qt-4.8/qwidget.html#setMask
The solution by overriding QLabel paintEvent method.
Code:
void AccountImage::paintEvent(QPaintEvent *event)
{
QPixmap pixmap(":/Icon/my_avatar.png");
QPixmap scaled = pixmap.scaled(width(), height(), Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
QBrush brush(scaled);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setBrush(brush);
painter.drawRoundedRect(0, 0, width(), height(), 100, 100);
QLabel::paintEvent(event);
}
Result:

How can I re- size the QGraphicItem using mouse

I this code which creates rectangle sizeof(200x100) and ellipse sizeof(100,200) but now I need to change the size of rectangle and ellipse using mouse.how can I do this.
#include "widget.h"
#include "ui_widget.h"
#include "readsvg.h"
#include <QCursor>
#include <QFileDialog>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
scene = new QGraphicsScene(this);
ui->graphicsView->setScene(scene);
QBrush redBrush(Qt::red);
QBrush blueBrush(Qt::blue);
QPen blackPen(Qt::black);
blackPen.setWidth(6);
elipse = scene->addEllipse(20,20,100,100,blackPen,redBrush);
elipse->setFlag(QGraphicsItem::ItemIsMovable, true);
rect = scene->addRect(-20,-10,200,100,blackPen,blueBrush);
rect->setFlag(QGraphicsItem::ItemIsMovable, true);
rect->setFlag(QGraphicsItem::ItemIsSelectable,true);
}
Widget::~Widget()
{
delete ui;
}
This is my expected results.
or this

CompositionMode_Clear gives me a black rectangle

I've trying to draw a circle with the center transparent using Qt in paintEvent.
I have this code:
void CircleWidget::paintEvent(QPaintEvent * event)
{
QPainter painter;
QPixmap pix1(width(), height());
QPixmap pix2(width()/2, height()/2);
QBitmap mask1(pix1.size());
QBitmap mask2(pix2.size());
mask1.fill(Qt::color0);
mask2.fill(Qt::color0);
pix1.setMask(mask1);
pix2.setMask(mask2);
if (painter.begin(&pix1))
{
painter.setPen(Qt::NoPen);
painter.setRenderHint(QPainter::Antialiasing);
painter.setBrush(QBrush(QColor(0xff, 0x0, 0x0)));
painter.drawEllipse(0, 0, width(), height());
painter.end();
if (painter.begin(&pix2))
{
painter.setPen(Qt::NoPen);
painter.setRenderHint(QPainter::Antialiasing);
painter.setBrush(QBrush(QColor(0x0, 0xff, 0xff)));
painter.drawEllipse(0, 0, width()/2, height()/2);
painter.end();
if (painter.begin(this))
{
painter.drawPixmap(0, 0, pix1);
painter.setCompositionMode(QPainter::CompositionMode_Clear);
painter.drawPixmap(width()/4, height()/4, pix2);
painter.end();
}
}
}
}
But, the result is this:
Do you have any idea? Thanks a lot.

Why QPainter might reject to work inside paintEvent?

I have:
class QTextEditEnter : public QTextEdit
{
Q_OBJECT
public:
QTextEditEnter( QWidget *_parent ) : QTextEdit(_parent)
{
this -> setFrameStyle( QFrame::Sunken ); // Sunken!
}
protected:
virtual void keyPressEvent(QKeyEvent * event);
virtual void paintEvent(QPaintEvent *_event)
{
QTextEdit::paintEvent( _event );
QPainter pnt(this);
pnt.setPen( QColor( 0, 0, 0, 0xff ));
pnt.drawRect( 0, 0, width(), height());
}
signals:
void signalPressEnter();
};
that gives:
QPainter::begin: Widget painting can only begin as a result of a paintEvent
QPainter::setPen: Painter not active
QPainter::drawRects: Painter not active
QPainter::begin: Widget painting can only begin as a result of a paintEvent
QPainter::setPen: Painter not active
QPainter::drawRects: Painter not active
Why that could be?
Update
// QPainter( this )
// QTextEdit::paintEvent at the begining of custom PaintEvent
// RESULT: "QPainter::begin: Widget painting can only begin as a result of a paintEvent" ...
virtual void paintEvent(QPaintEvent *_event)
{
QTextEdit::paintEvent( _event );
QPainter pnt( this );
pnt.setPen( QColor( 0, 0, 0, 0xff ));
pnt.drawRect( 0, 0, width()-1, height()-1);
}
// QPainter ( viewport() )
// QTextEdit::paintEvent at the begining of custom PaintEvent
// RESULT: works.
virtual void paintEvent(QPaintEvent *_event)
{
QTextEdit::paintEvent( _event );
QPainter pnt( viewport() );
pnt.setPen( QColor( 0, 0, 0, 0xff ));
pnt.drawRect( 0, 0, width()-1, height()-1);
}
// *** BONUS ***
// QPainter( viewport() ) or QPainter ( this )
// QTextEdit::paintEvent after QPainter() constructor.
// RESULT: Segmentation fault.
virtual void paintEvent(QPaintEvent *_event)
{
QPainter pnt( viewport() );
pnt.setPen( QColor( 0, 0, 0, 0xff ));
QTextEdit::paintEvent( _event ); // WRONG PLACE!!!
pnt.drawRect( 0, 0, width()-1, height()-1);
}
Instead of
QPainter pnt(this);
try
QPainter pnt(viewport());
pnt.setPen(QColor( 0, 0, 0, 0xff ));
pnt.drawRect(viewport()->rect());
viewport() is the paintable area and could be whats causing the issue

How to create circle icon from image file?

In my customized QWidget paintEvent method, I want to draw a circle with a circle shaped image icon. The source image is loaded from file and then automatically casted into circle using QPainter composition. How to do it? Thank you!
void DotGraphView::paintNodes(QPainter & painter)
{
painter.setPen(Qt::blue);
painter.drawEllipse(x, y, 36, 36);
QPixmap icon("./image.png");
QImage fixedImage(64, 64, QImage::Format_ARGB32_Premultiplied);
QPainter imgPainter(&fixedImage);
imgPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
imgPainter.drawPixmap(0, 0, 64, 64, icon);
imgPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
imgPainter.setBrush(Qt::transparent);
imgPainter.drawEllipse(32, 32, 30, 30);
imgPainter.end();
painter.drawPixmap(x, y, 64, 64, QPixmap::fromImage(fixedImage));
}
The above code does not work. The output display is not a circle shaped image.
I don't know if I understood correctly, but this might do what you want:
#include <QtGui/QApplication>
#include <QLabel>
#include <QPixmap>
#include <QBitmap>
#include <QPainter>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Load the source image.
QPixmap original(QString("/path/here.jpg"));
if (original.isNull()) {
qFatal("Failed to load.");
return -1;
}
// Draw the mask.
QBitmap mask(original.size());
QPainter painter(&mask);
mask.fill(Qt::white);
painter.setBrush(Qt::black);
painter.drawEllipse(QPoint(mask.width()/2, mask.height()/2), 100, 100);
// Draw the final image.
original.setMask(mask);
// Show the result on the screen.
QLabel label;
label.setPixmap(original);
label.show();
return a.exec();
}
Cache the result in your QWidget subclass and blit to the screen the required bounding rect in your paint event when requested.
You can do this relatively simply with a clipping path:
QPainter painter(this);
painter.setPen(Qt::blue);
painter.drawEllipse(30, 30, 36, 36);
QPixmap icon("./image.png");
QImage fixedImage(64, 64, QImage::Format_ARGB32_Premultiplied);
fixedImage.fill(0); // Make sure you don't have garbage in there
QPainter imgPainter(&fixedImage);
QPainterPath clip;
clip.addEllipse(32, 32, 30, 30); // this is the shape we want to clip to
imgPainter.setClipPath(clip);
imgPainter.drawPixmap(0, 0, 64, 64, icon);
imgPainter.end();
painter.drawPixmap(0, 0, 64, 64, QPixmap::fromImage(fixedImage));
(I'd cache the pixmaps if you do this often.)