I want to draw a filled ellipse in QT that would not change its size when zooming in and out. For now I have the following:
QPen pen = painter->pen();
pen.setCosmetic(true);
pen.setWidth(5);
painter->setPen(pen);
QBrush brush = painter->brush();
brush.setStyle(Qt::SolidPattern);
painter->setBrush(brush);
painter->drawEllipse(p, 2, 2);
When I zoom out a gap between the boundary and the filling appear. So it looks like 2 concentric circles. And when I zoom in the filling overgrows the boundary and the disk gets bigger and bigger. Any idea how to fix this? Thanks!
I would instead look to the ItemIgnoresTransformations flag, which will make the item itself "cosmetic", rather than just the pen. Here's a working example:
#include <QtGui>
class NonScalingItem : public QGraphicsItem
{
public:
NonScalingItem()
{ setFlag(ItemIgnoresTransformations, true); }
QRectF boundingRect() const
{ return QRectF(-5, -5, 10, 10); }
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QPen pen = painter->pen();
pen.setCosmetic(true);
pen.setWidth(5);
pen.setColor(QColor(Qt::red));
painter->setPen(pen);
QBrush brush = painter->brush();
brush.setStyle(Qt::SolidPattern);
painter->setBrush(brush);
painter->drawEllipse(QPointF(0, 0), 10, 10);
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QGraphicsScene *scene = new QGraphicsScene;
QGraphicsView *view = new QGraphicsView;
NonScalingItem *item = new NonScalingItem;
scene->addItem(item);
view->setScene(scene);
/* The item will remain unchanged regardless of whether
or not you comment out the following line: */
view->scale(2000, 2000);
view->show();
return app.exec();
}
Related
I have a QWidget with a QPushButton, at the same time, this QWidget is embedded into a QGraphicsItem, which is inside a QGraphicsScene.
I need to draw a line between two of those QGraphicsItems pointing to the QPushButton. For that, I need to get the position of the QPushButton. It looks like this:
I tried getting the position of the QPushButton inside the constructor of the QGraphicsItem, but it returns 0,0. I guess this is the position of the button inside the QWidget. I guess what I need is a way to get the position on the screen.
Minimal Example: Simplified as much as possible.
QWidget:
NodeFrame::NodeFrame()
{
setFixedSize(200,80);
setStyleSheet("QFrame { background-color: #2e4076; }");
// Creates and add a QPushButton to the frame.
// I need the position of this button on the QGraohicsScene
auto button = new QPushButton("B");
button->setFixedSize(40,20);
auto layout = new QHBoxLayout();
layout->addWidget(button);
setLayout(layout);
}
QGraphicsItem:
class Node : public QGraphicsItem
{
public:
Node();
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
};
Node::Node()
{
setFlag(ItemIsMovable);
// Create a GraphicsProxyWidget to insert the nodeFrame into the scene
auto proxyWidget = new QGraphicsProxyWidget(this);
auto frame = new NodeFrame();
proxyWidget->setWidget(frame);
// Center the widget(frame) at the center of the QGraphicsItem
proxyWidget->setPos(boundingRect().center() - proxyWidget->boundingRect().center());
}
QRectF Node::boundingRect() const
{
return QRectF(-10, -10, 280, 150);
}
void Node::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
QPainterPath path;
path.addRoundedRect(boundingRect(), 10, 10);
painter->drawPath(path);
}
Main:
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
// Create scene and view
auto scene = new QGraphicsScene();
auto view = new QGraphicsView(scene);
view->setMinimumSize(800, 800);
// Create the QGraphicsItem and add it to the scene
auto item = new Node();
scene->addItem(item);
item->setPos(-50, -50);
// Show the the view
view->show();
return app.exec();
}
In nodeframe.cpp I add one function getButtonRect() :
#ifndef NODEFRAME_H
#define NODEFRAME_H
#include <QWidget>
#include <QPushButton>
#include <QRect>
class NodeFrame: public QWidget
{
public:
NodeFrame();
QRect getButtonRect();
private:
QPushButton *button;
QHBoxLayout *layout;
};
#endif // NODEFRAME_H
nodeframe.cpp
#include "nodeframe.h"
NodeFrame::NodeFrame()
{
setFixedSize(200, 80);
setStyleSheet("QFrame { background-color: #2e4076; }");
// Creates and add a QPushButton to the frame.
// I need the position of this button on the QGraohicsScene
button = new QPushButton("B");
button->setFixedSize(40, 20);
layout = new QHBoxLayout();
layout->addWidget(button);
setLayout(layout);
}
QRect NodeFrame::getButtonRect()
{
return layout->itemAt(0)->geometry();
}
and in Node pass this function to main.cpp because QGraphicsView is there:
node.cpp:
#include "node.h"
#include <QGraphicsProxyWidget>
#include <QPainter>
Node::Node()
{
setFlag(ItemIsMovable);
// Create a GraphicsProxyWidget to insert the nodeFrame into the scene
auto proxyWidget = new QGraphicsProxyWidget(this);
frame = new NodeFrame();
proxyWidget->setWidget(frame);
// Center the widget(frame) at the center of the QGraphicsItem
proxyWidget->setPos(boundingRect().center() - proxyWidget->boundingRect().center());
}
QRectF Node::boundingRect() const
{
return QRectF(-10, -10, 280, 150);
}
void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QPainterPath path;
path.addRoundedRect(boundingRect(), 10, 10);
painter->drawPath(path);
}
QRect Node::getButtonRect()
{
return frame->getButtonRect();
}
main.cpp
#include "node.h"
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// Create scene and view
auto scene = new QGraphicsScene();
auto view = new QGraphicsView(scene);
view->setMinimumSize(800, 800);
// Create the QGraphicsItem and add it to the scene
auto item = new Node();
scene->addItem(item);
item->setPos(0, 0);
// qDebug() << "RECT bottomLeft= " << view->mapToScene(item->getButtonRect().bottomLeft());
// qDebug() << "RECT bottomRight= " << view->mapToScene(item->getButtonRect().bottomRight());
// qDebug() << "RECT topLeft= " << view->mapToScene(item->getButtonRect().topLeft());
// qDebug() << "RECT topRight= " << view->mapToScene(item->getButtonRect().topRight());
auto btnRect = item->getButtonRect();
auto ellipse = new QGraphicsEllipseItem(QRect(view->mapToGlobal(btnRect.center()).x(), view->mapToGlobal(btnRect.center()).y(), 40, 40));
qDebug() << "Center" << view->mapToGlobal(btnRect.center());
scene->addItem(ellipse);
// Show the the view
view->show();
return app.exec();
}
The question is simple ! I want something like this. Either using QPainter class or using Qt Graphics Framework:
There are several ways to do this using a QPainterPath specified here.
Here is the second example from that page:
#include <QtGui>
#include <cmath>
class Widget : public QWidget
{
public:
Widget ()
: QWidget() { }
private:
void paintEvent ( QPaintEvent *)
{
QString hw("hello world");
int drawWidth = width() / 100;
QPainter painter(this);
QPen pen = painter.pen();
pen.setWidth(drawWidth);
pen.setColor(Qt::darkGreen);
painter.setPen(pen);
QPainterPath path(QPointF(0.0, 0.0));
QPointF c1(width()*0.2,height()*0.8);
QPointF c2(width()*0.8,height()*0.2);
path.cubicTo(c1,c2,QPointF(width(),height()));
//draw the bezier curve
painter.drawPath(path);
//Make the painter ready to draw chars
QFont font = painter.font();
font.setPixelSize(drawWidth*2);
painter.setFont(font);
pen.setColor(Qt::red);
painter.setPen(pen);
qreal percentIncrease = (qreal) 1/(hw.size()+1);
qreal percent = 0;
for ( int i = 0; i < hw.size(); i++ ) {
percent += percentIncrease;
QPointF point = path.pointAtPercent(percent);
qreal angle = path.angleAtPercent(percent); // Clockwise is negative
painter.save();
// Move the virtual origin to the point on the curve
painter.translate(point);
// Rotate to match the angle of the curve
// Clockwise is positive so we negate the angle from above
painter.rotate(-angle);
// Draw a line width above the origin to move the text above the line
// and let Qt do the transformations
painter.drawText(QPoint(0, -pen.width()),QString(hw[i]));
painter.restore();
}
}
};
int main(int argc, char **argv)
{
QApplication app(argc, argv);
Widget widget;
widget.show();
return app.exec();
}
I have a QPainter, and a rectangle.
i'd like to draw a QLineEdit control, empty. Just to draw it, not to have a live control. How do I do that? I have tried QStyle::drawPrimitive to no avail. nothing gets drawn.
QStyleOption option1;
option1.init(contactsView); // contactView is the parent QListView
option1.rect = option.rect; // option.rect is the rectangle to be drawn on.
contactsView->style()->drawPrimitive(QStyle::PE_FrameLineEdit, &option1, painter, contactsView);
Naturally, i'd like the drawn dummy to look native in Windows and OSX.
Your code is pretty close, but you would have to initialize the style from a fake QLineEdit. The following is based on QLineEdit::paintEvent and QLineEdit::initStyleOption.
#include <QtGui>
class FakeLineEditWidget : public QWidget {
public:
explicit FakeLineEditWidget(QWidget *parent = NULL) : QWidget(parent) {}
protected:
void paintEvent(QPaintEvent *) {
QPainter painter(this);
QLineEdit dummy;
QStyleOptionFrameV2 panel;
panel.initFrom(&dummy);
panel.rect = QRect(10, 10, 100, 30); // QFontMetric could provide height.
panel.lineWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth,
&panel,
&dummy);
panel.midLineWidth = 0;
panel.state |= QStyle::State_Sunken;
panel.features = QStyleOptionFrameV2::None;
style()->drawPrimitive(QStyle::PE_PanelLineEdit, &panel, &painter, this);
}
};
int main(int argc, char **argv) {
QApplication app(argc, argv);
FakeLineEditWidget w;
w.setFixedSize(300, 100);
w.show();
return app.exec();
}
I am facing problem for drawing line and text with different color using QPainter. I am using the following piece of code to achieve this but it's not working. Both lines and texts are drawn using the color set for drawing Text.
void MyWidget::drawHorLinesWithText(QPainter & painter, const QRect & rect)
{
for(int i=0; i < 5; i++)
{
QPen penHLines(QColor("#0e5a77"), 1, Qt::DotLine, Qt::FlatCap, Qt::RoundJoin);
painter.setPen(penHLines);
painter.drawLine(10, 50 - (5*(i+1)), 200, 50 - (5*(i+1)));
QString strNumber = QString::number((2)*(i+1));
painter.setFont(QFont("Arial", 8, QFont::Bold));
//QBrush brush(QColor("#00e0fc"));
//painter.setBrush(brush);
QPen penHText(QColor("#00e0fc"));//Here lines are also drawn using this color
painter.setPen(penHText);
painter.drawText(5, 50 - (5*(i+1)) - 10), 20, 30, Qt::AlignHCenter | Qt::AlignVCenter,
strNumber);
}
}
How would I set different colors for drawing lines and Texts. Any suggestions. Thanks.
This works for me with Qt 5.3; perhaps it was a bug in the version you were using?
#include <QtWidgets>
class Widget : public QWidget
{
public:
Widget() {
resize(200, 200);
}
void paintEvent(QPaintEvent *) {
QPainter painter(this);
for(int i=0; i < 5; i++)
{
QPen penHLines(QColor("#0e5a77"), 10, Qt::DotLine, Qt::FlatCap, Qt::RoundJoin);
painter.setPen(penHLines);
painter.drawLine(10, 50 - (5*(i+1)), 200, 50 - (5*(i+1)));
QString strNumber = QString::number((2)*(i+1));
painter.setFont(QFont("Arial", 8, QFont::Bold));
QPen penHText(QColor("#00e0fc"));
painter.setPen(penHText);
painter.drawText(5, 50 - (5*(i+1)) - 10, 20, 30, Qt::AlignHCenter | Qt::AlignVCenter, strNumber);
}
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Widget w;
w.show();
return app.exec();
}
I increased the line width to 10 to see what's going on:
QPainter draw text using QBrush, not QPen. Text is rendered with glyph strokes then filled with current brush. Current pen only controls lines and strokes.
I'm having a Qt application with a main window that has five buttons aligned in a vertical order.
They all have the same size.
All I want to do is to increase the font size of the button label when the app goes fullscreen.
I would really appreciate a solution that does not need too much code ... was hoping that this was something that could be done in Qt Designer, but I couldn't find a way how to.
Any suggestions?
Best,
guitarflow
I can't think of any way to do it in designer, but it's really not too much code. Here's a quick-and-dirty proof of concept. You'd want to take into account margins (using QStyle::pixelMetrics and the like), but you get the idea.
#include <QtGui>
class FontAdjustingButton : public QPushButton {
public:
explicit FontAdjustingButton(QWidget *parent = NULL) : QPushButton(parent) {
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
}
protected:
void resizeEvent(QResizeEvent *event) {
int button_margin = style()->pixelMetric(QStyle::PM_ButtonMargin);
QFont f = font();
f.setPixelSize(event->size().height() - button_margin * 2);
setFont(f);
}
};
int main(int argc, char **argv) {
QApplication app(argc, argv);
QWidget w;
QVBoxLayout *layout = new QVBoxLayout;
for (int i = 0; i < 5; ++i) {
FontAdjustingButton *btn = new FontAdjustingButton;
btn->setText(QString("Hello, world %1").arg(i));
layout->addWidget(btn);
}
w.setLayout(layout);
w.show();
return app.exec();
}