How to drawing a shapes in QtextEdit - qt

I currently working on a text editor using Qtextedit and I want to Draw a shapes like triangle, square and ellipseā€¦ etc in the editor to Richness the document.
So I was wondering if is it possible to do this with Qtextedit and only Qtextedit.
Actually I am new to Qt so any ideas any tutorial any links would be highly appreciated
Thanks in advance and sorry for my english.
Best regards.

Sure it's possible, if I understand you correctly. All you need is just implement your own TextEdit derived from QTextEdit and reimplement paintEvent()
For example:
QMyTextEdit.h
class QMyTextEdit : public QTextEdit
{
public:
QMyTextEdit(QWidget *parent = 0);
protected:
void paintEvent(QPaintEvent * event);
};
QMyTextEdit.cpp
QMyTextEdit::QMyTextEdit(QWidget *parent) :
QTextEdit(parent)
{
}
void QMyTextEdit::paintEvent(QPaintEvent *event)
{
QTextEdit::paintEvent(event);
QPainter painter(viewport());
QPen pen;
pen.setColor(Qt::blue);
pen.setWidth(2);
painter.setPen(pen);
painter.setRenderHint(QPainter::Antialiasing, true);
QPoint center = viewport()->rect().center();
painter.drawRect(center.x() - 10,center.y() - 10,20,20);
}

Related

How to draw something with QPainter when the button is pushed

I am working on my project from programming and I need to draw, for example, a circle every time the pushButton is pressed using QPainter. This is the first problem, and the second one here is that I need some information to be sent to the drawing function too, for example, int vector, and being able to draw so many circles, as there are elements in the vector with radii of the elements itself. I have found some code based on signals and slots.
The sender:
public:
Listener(QObject *p = 0) : QObject(p) {
QTimer * t = new QTimer(this);
t->setInterval(200);
connect(t, SIGNAL(timeout()), this, SLOT(sendData()));
t->start();
}
signals:
void dataAvaiable(int, int);
public slots:
void sendData() {
emit dataAvaiable(qrand() % 200, qrand() % 200);
}
The reciever:
void receiveData(int x, int y) {
QPainter painter(this);
QPen pen(Qt::white, 5);
painter.setRenderHint(QPainter::HighQualityAntialiasing);
painter.setPen(pen);
QPoint point(x, y);
painter.drawEllipse(x, y, 100, 100);
data.append(point);
}
The connection itself in main.cpp
QObject::connect(&l, SIGNAL(dataAvaiable(int,int)), &w, SLOT(receiveData(int,int)));
But the code doesn't suit for my exact task with buttons and doesn't even want to draw anythig, just any circle at all. Howewer, in debugger the code executes properly, and I am relatively new to Qt and C++ so I can't figure out by myself, where the problem is and how to solve my task.Can someone please do a minimal of code or simply explain to me, where exactly the problem is? Need to solve the problem as soon as possible. Thank you.
Upd: any possible solution with or without QPainter would be good now.
Qt Forum users gave me an answer.
Quote:
From the QPainter class description:
Warning: When the paintdevice is a widget, QPainter can only be used inside a
paintEvent() function or in a function called by paintEvent().
You can force calling paintEvent() by invoking update(), so you must connect the onclicked() signal of your button to the update() slot of the widget you're drawing on.
For your second problem, the data can be a member variable.
Here's an example:
// mywidget.h
#include <QVector>
#include <QPoint>
// other includes and the constructor...
protected:
virtual void paintEvent(QPaintEvent *event);
private slots:
void onButtonClicked();
private:
QPushButton* mButton;
QVector<QPoint> mCirclesData;
// mywidget.cpp
MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{
mButton = new QPushButton(this);
// customise your button...
connect(mButton, &QPushButton::clicked, this, &MyWidget::onButtonClicked);
}
//...
void MyWidget::onButtonClicked(){
int x = qrand() % 200, y = x;
mCirclesData << QPoint(x,y);
update(); // force calling paintEvent
}
void MyWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
QPen pen(Qt::white, 5);
painter.setRenderHint(QPainter::HighQualityAntialiasing);
painter.setPen(pen);
painter.drawEllipse(mCirclesData.last().x(), mCirclesData.last().y(), 100, 100);
}
``

QOpenGLWidget and transparency

I have small problem with QOpenGLWidget and its background color.
When I want to create semi-transparent rect on my custom QOpenGLWidget using QPainter there are 2 different results:
If MyCustomWidget have parent - on every update rect's color multiplies (and after few repaints it is opaque, like previous painting result not cleaned)
If MyCustomWidget doesn't have parent - color doesn't repaints each time
Here is code example for QPainter:
class Widget : public QOpenGLWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0)
: QOpenGLWidget(parent)
{
resize(800, 600);
Test *test = new Test(this);
}
~Widget(){}
protected:
void paintEvent(QPaintEvent *) {}
protected:
void initializeGL() {
if(paintEngine()->type() != QPaintEngine::OpenGL &&
paintEngine()->type() != QPaintEngine::OpenGL2)
qDebug() << "ERROR. Type is: " << paintEngine()->type();
}
void resizeGL(int, int) {}
void paintGL() {
QPainter p;
p.begin(this);
{
p.fillRect(rect(), Qt::white);
}
p.end();
}
private:
class Test : public QOpenGLWidget
{
public:
Test(QWidget *parent = 0) : QOpenGLWidget(parent) {
resize(100, 100);
}
protected:
void paintEvent(QPaintEvent *) {
QPainter p(this);
p.fillRect(rect(), QColor(125, 125, 125, 255/10));
}
};
};
Also by default it has black background (I don't know how to fix it. setAttribute(Qt::WA_TranslucentBackground) doesn't helps).
Also, when I'm trying to clear color using glClear it ignores alpha (both on QOpenGLWidget with parent and not). Here is Test class from previous code, but now it is using opengl to clear color:
class Test : public QOpenGLWidget
{
public:
Test(QWidget *parent = 0) : QOpenGLWidget(parent) {
resize(100, 100);
}
void initializeGL() {
QOpenGLFunctions *f = context()->functions();
f->glClearColor(0.0f, 1.0f, 0.0f, 0.1f);
}
void paintGL() {
QOpenGLFunctions *f = context()->functions();
f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
};
How can I fix this problems?
I'm using Qt 5.5.0, Windows 10, MinGW 4.9.2
Xeed is correct when saying the QOpenGLWidget is painted first.
I'm not an expert but I think I found the solution. You need to set a widget attribute to always make the widget stacked on top (think of the widgets as layers on the window). Here is a link to where I got the following information:
P.S. As mentioned in the QQuickWidget post, there is a limitation regarding semi-transparency when using QQuickWidget or QOpenGLWidget as child widgets. For applications that absolutely need this, Qt 5.4 offers a workaround: the newly introduced Qt::WA_AlwaysStackOnTop widget attribute. This, at the expense of breaking the stacking order for other types of layouts, makes it possible to have a semi-transparent QQuickWidget or QOpenGLWidget with other widgets visible underneath. Of course, if the intention is only to make other applications on the desktop visible underneath, then the Qt::WA_TranslucentBackground attribute is sufficient
Solution in Python:
set attribute of OpenGL widget
setAttribute(Qt.WA_AlwaysStackOnTop)
Now the OpenGL widget is considered 'on top' in the window. Use 'glClearColor' function and specify the alpha channel to be zero (0.0).
glClearColor(0.0, 0.0, 0.0, 0.0)
I'm not sure how to write that in other languages but this worked for me. The OpenGL widget no longer has the default black background. It is transparent! Hope this helps.
As far as I know the QOpenGLWidget is always drawn first. Therefore you cannot show any widgets layered below. I'm currently looking into the same issue. I'll report back, when I find any solution.
I've had similar issue with QOpenGLWidget not repainting correctly in transparent areas and decided to switch to QOpenGLWindow wrapped inside QWidget::createWindowContainer()

QwtPlot - How to customize the footer?

What is the meaning of the label in the yellow rectangle? How to remove (hide) it?
I'm working with Qwt 6.0.1 and Qt 4.8.6
I've found, looking deep in the code, that the label is not part of a standard QwtPlot. It's a custom label and it's created using the following method of the QwtText class:
void draw( QPainter *painter, const QRectF &rect ) const;
Pseudo-code:
void MyQwtPlot::drawCustomLabel()
{
QPainter painter(this);
QwtText label(<label-text>);
label.draw(&painter, QRectF(<label-position>));
painter.end();
}
where MyQwtPlot is a class that extends QwtPlot.
I've solved commenting the drawCustomLabel method in my implementation.

How to animate the outline of a QGraphicsItem in real time?

I am designing a timer with Qt. With QGraphicsEllipseItem, I drew a circle and now I need to animate the QPen around this circle (change color) every second. I found QGraphicsPathItem, but I need some examples on how to move forward. Can anyone show me an example?
You have two problems:
QGraphicsEllipseItem is not a QObject so QPropertyAnimation can't be used directly on this item
QGraphicsItemAnimation doesn't cover property you want to animate.
What you can do?
IMO best approach is to provide some custom QObject on which you could do this animation. You can inherit QObject or use fake QGraphicsObject (which is a QObject).
class ShapeItemPenAnimator : public QGraphicsObject {
Q_OBJECT
private:
QAbstractGraphicsShapeItem *mParent;
QPropertyAnimation *mAnimation;
public:
QPROPERTY(QColor penColor
READ penColor
WRITE setPenColor)
explicit ShapeItemPenAnimator(QAbstractGraphicsShapeItem * parent)
: QGraphicsObject(parent)
, mParent(parent) {
setFlags(QGraphicsItem::ItemHasNoContents);
mAnimation = new QPropertyAnimation(this, "penColor", this);
}
QColor penColor() const {
return mParent->pen().color();
}
public slots:
void setPenColor(const QColor &color) {
QPen pen(mParent->pen());
pen.setColor(color);
mParent->setPen(pen);
}
public:
void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0) {
}
QRectF boundingRect() const {
return QRectF();
}
QPropertyAnimation *animation() const {
return mAnimation;
}
}
Now you just attach this object to your QGraphicsEllipseItem and set animation you need.
// yourEllipse
ShapeItemPenAnimator *animator = new ShapeItemPenAnimator(yourEllipse);
animator->animation()->setEndValue(....);
animator->animation()->setStartValue(....);
animator->animation()->setDuration(....);
animator->animation()->setEasingCurve(....);
There are several classes helping with animations of QGraphicsItem in Qt. I suggest looking into QGraphicsItemAnimation and QPropertyAnimation. You can use the second one to animate the color of an item. Here is an example of using QPropertyAnimation:
How to make Qt widgets fade in or fade out?

Problem with drawing focus frame in Qt

I'm trying to create custom widget inheriting QFrame. All works fine, but I'm unable to draw the focus rectangle around my widget. Below is the sample code I use for drawing:
frame.h
class Frame : public QFrame {
Q_OBJECT
public:
Frame(QWidget *parent = 0);
~Frame();
protected:
void paintEvent(QPaintEvent *event);
private:
Ui::Frame *ui;
};
frame.cpp
Frame::Frame(QWidget *parent) :
QFrame(parent),
ui(new Ui::Frame)
{
ui->setupUi(this);
setFocusPolicy(Qt::ClickFocus);
}
Frame::~Frame()
{
delete ui;
}
void Frame::paintEvent(QPaintEvent *event)
{
QFrame::paintEvent(event);
if (hasFocus()) {
QStylePainter painter(this);
QStyleOptionFocusRect option;
option.initFrom(this);
option.backgroundColor = palette().dark().color();
painter.drawPrimitive(QStyle::PE_FrameFocusRect, option);
}
}
What I mean by 'unable to draw focus frame' is that when you click a standard widget that accepts focus (let's say QLineEdit), it has a blue rectangle drawn around it. When I click my widget there is no such rectangle drawn. Are there any more things I should do besides setting focusPolicy on my widget?
It might have something to do with the style your app is using. When I try your code with the "gtk" and "cleanlooks" style, no focus rectangle is drawn. With "plastique" and "windows" it is. Since I'm on Linux, I cannot test "windowsxp" and "macintosh". Try running with the -style option and see what happens.
try also
setFocusPolicy(Qt::StrongFocus);
setAttribute( Qt::WA_MacShowFocusRect);

Resources