I added in a QDialog aQQuickWidget to load a .qml but its background color is white. My qml declares a Rectangle not filling all QQuickWidget surface. I need the not filled surface having the same background color of the dialog. What is the way to have a transparent background?
Floating cloud:
auto quickWidget = new QQuickWidget();
quickWidget->setWindowFlags(Qt::SplashScreen);
quickWidget->setAttribute(Qt::WA_AlwaysStackOnTop);
quickWidget->setAttribute(Qt::WA_TranslucentBackground);
quickWidget->setClearColor(Qt::transparent);
quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
quickWidget->setSource(QUrl("qrc:/cloud.qml"));
quickWidget->show();
cloud.qml
import QtQuick 2.0
Item {
id: root
width: 400
height: 300
Canvas {
id: cloud
anchors.fill: parent
onPaint: {
var ctx = getContext("2d");
ctx.beginPath();
var x = 100;
var y = 170;
ctx.arc(x, y, 60, Math.PI * 0.5, Math.PI * 1.5);
ctx.arc(x + 70, y - 60, 70, Math.PI * 1, Math.PI * 1.85);
ctx.arc(x + 152, y - 45, 50, Math.PI * 1.37, Math.PI * 1.91);
ctx.arc(x + 200, y, 60, Math.PI * 1.5, Math.PI * 0.5);
ctx.moveTo(x + 200, y + 60);
ctx.lineTo(x, y + 60);
ctx.strokeStyle = "#797874";
ctx.stroke();
ctx.fillStyle = "#8ED6FF";
ctx.fill();
}
}
}
It's explained in the QQuickWidget documentation : QQuickWidget Limitations
Putting other widgets underneath and making the QQuickWidget transparent will not lead to the expected results: the widgets underneath will not be visible. This is because in practice the QQuickWidget is drawn before all other regular, non-OpenGL widgets, and so see-through types of solutions are not feasible. Other type of layouts, like having widgets on top of the QQuickWidget, will function as expected.
When absolutely necessary, this limitation can be overcome by setting the Qt::WA_AlwaysStackOnTop attribute on the QQuickWidget. Be aware, however that this breaks stacking order. For example it will not be possible to have other widgets on top of the QQuickWidget, so it should only be used in situations where a semi-transparent QQuickWidget with other widgets visible underneath is required.
Use QQuickWidget::setClearColor(Qt::transparent) and set an alpha channel via the setFormat call.
project.pro
QT += core gui widgets qml quickwidgets
CONFIG += c++17
main.cpp
#include <QApplication>
#include <QObject>
#include <QDialog>
#include <QVBoxLayout>
#include <QtQuickWidgets/QQuickWidget>
/*****************************************************************************/
void show (QUrl component) {
QDialog* dialog = new QDialog();
dialog->setStyleSheet("background-color: green;");
QObject::connect(
QCoreApplication::instance(),
SIGNAL(aboutToQuit()),
dialog,
SLOT(deleteLater())
);
/*QObject::connect(dialog,&QObject::destroyed,[](){
qDebug() << "destroyed";
});*/
QQuickWidget* content = new QQuickWidget(component, dialog);
content->setResizeMode(QQuickWidget::SizeRootObjectToView);
content->setAttribute(Qt::WA_AlwaysStackOnTop);
content->setClearColor(Qt::transparent);
dialog->show();
}
/*****************************************************************************/
int main(int argc, char *argv[]) {
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication a(argc, argv);
show(QStringLiteral("qrc:/qml/Button.qml"));
show(QStringLiteral("qrc:/qml/Button.qml"));
show(QStringLiteral("qrc:/qml/Button.qml"));
show(QStringLiteral("qrc:/qml/Button.qml"));
return a.exec();
}
/*****************************************************************************/
Button.qml
import QtQuick 2.12
import QtQuick.Controls 2.5
Button {
height: 100
width: 100
text: "lol"
}
result
also try gradient background
dialog->setStyleSheet(
"background-color: qlineargradient(spread:pad,x1:0,y1:1,x2:0,y2:0," \
" stop:0 rgba(34, 34, 44, 255)," \
" stop:1 rgba(56, 55, 72, 255)" \
");"
);
Related
I am new to qml but I want to add a circle gauge to the QQuickWidget by referring to the dashboard of the QT example.
Below is my codes.
guagetest.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets quickwidgets
CONFIG += c++11
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
RESOURCES += \
dashboard.qrc
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->quickWidget->setSource(QUrl("qrc:/qml/qml/test.qml"));
ui->quickWidget->show();
}
MainWindow::~MainWindow()
{
delete ui;
}
test.qml
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Extras 1.4
Item {
id: container
width: parent.width
height: parent.height
anchors.centerIn: parent.Center
Row {
id: gaugeRow
spacing: container.width * 0.2
anchors.centerIn: parent
CircularGauge {
id: speedometer
value: valueSource.kph
anchors.verticalCenter: parent.verticalCenter
maximumValue: 280
// We set the width to the height, because the height will always be
// the more limited factor. Also, all circular controls letterbox
// their contents to ensure that they remain circular. However, we
// don't want to extra space on the left and right of our gauges,
// because they're laid out horizontally, and that would create
// large horizontal gaps between gauges on wide screens.
width: height
height: container.height * 0.8
style: DashboardGaugeStyle {}
}
}
}
DashboardGaugeStyle.qml
import QtQuick 2.2
import QtQuick.Controls.Styles 1.4
CircularGaugeStyle {
tickmarkInset: toPixels(0.04) // gauge graduation radius
minorTickmarkInset: tickmarkInset
labelStepSize: 20 // gauge graduation text
labelInset: toPixels(0.23) // gauge graduation text position
property real xCenter: outerRadius
property real yCenter: outerRadius
property real needleLength: outerRadius - tickmarkInset * 1.25
property real needleTipWidth: toPixels(0.02)
property real needleBaseWidth: toPixels(0.06)
property bool halfGauge: false
function toPixels(percentage) {
return percentage * outerRadius;
}
function degToRad(degrees) {
return degrees * (Math.PI / 180);
}
function radToDeg(radians) {
return radians * (180 / Math.PI);
}
function paintBackground(ctx) {
if (halfGauge) {
ctx.beginPath();
ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height / 2);
ctx.clip();
}
ctx.beginPath();
ctx.fillStyle = "black";
ctx.ellipse(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.fill();
ctx.beginPath();
ctx.lineWidth = tickmarkInset;
ctx.strokeStyle = "black";
ctx.arc(xCenter, yCenter, outerRadius - ctx.lineWidth / 2, outerRadius -ctx.lineWidth / 2, 0, Math.PI * 2);
ctx.stroke();
ctx.beginPath();
ctx.lineWidth = tickmarkInset / 2;
ctx.strokeStyle = "#222";
ctx.arc(xCenter, yCenter, outerRadius - ctx.lineWidth / 2, outerRadius -ctx.lineWidth / 2, 0, Math.PI * 2);
ctx.stroke();
ctx.beginPath();
var gradient = ctx.createRadialGradient(xCenter, yCenter, 0, xCenter, yCenter, outerRadius * 1.5);
gradient.addColorStop(0, Qt.rgba(1, 1, 1, 0));
gradient.addColorStop(0.7, Qt.rgba(1, 1, 1, 0.13));
gradient.addColorStop(1, Qt.rgba(1, 1, 1, 1));
ctx.fillStyle = gradient;
ctx.arc(xCenter, yCenter, outerRadius - tickmarkInset, outerRadius - tickmarkInset, 0, Math.PI * 2);
ctx.fill();
}
background: Canvas {
onPaint: {
var ctx = getContext("2d");
ctx.reset();
paintBackground(ctx);
}
Text {
id: speedText
font.pixelSize: toPixels(0.3)
text: kphInt
color: "white"
horizontalAlignment: Text.AlignRight
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.verticalCenter
anchors.topMargin: toPixels(0.1)
readonly property int kphInt: control.value
}
Text {
text: "km/h"
color: "white"
font.pixelSize: toPixels(0.09)
anchors.top: speedText.bottom
anchors.horizontalCenter: parent.horizontalCenter
}
}
needle: Canvas {
implicitWidth: needleBaseWidth
implicitHeight: needleLength
property real xCenter: width / 2
property real yCenter: height / 2
onPaint: {
var ctx = getContext("2d");
ctx.reset();
ctx.beginPath();
ctx.moveTo(xCenter, height);
ctx.lineTo(xCenter - needleBaseWidth / 2, height - needleBaseWidth / 2);
ctx.lineTo(xCenter - needleTipWidth / 2, 0);
ctx.lineTo(xCenter, yCenter - needleLength);
ctx.lineTo(xCenter, 0);
ctx.closePath();
ctx.fillStyle = Qt.rgba(0.66, 0, 0, 0.66);
ctx.fill();
ctx.beginPath();
ctx.moveTo(xCenter, height)
ctx.lineTo(width, height - needleBaseWidth / 2);
ctx.lineTo(xCenter + needleTipWidth / 2, 0);
ctx.lineTo(xCenter, 0);
ctx.closePath();
ctx.fillStyle = Qt.lighter(Qt.rgba(0.66, 0, 0, 0.66));
ctx.fill();
}
}
foreground: null
}
When I compile, the following message appears.
qrc:/qml/qml/test.qml:9: TypeError: Cannot read property 'width' of null
qrc:/qml/qml/test.qml:10: TypeError: Cannot read property 'height' of null
qrc:/qml/qml/test.qml:20: ReferenceError: valueSource is not defined
qrc:/qml/qml/test.qml:11: TypeError: Cannot read property 'Center' of null
I want to know why that message comes out and how to solve it.
and How can i change background color of QQuickWidget?
Please help me.
Root object needs an initial size. And no need to center in parent, cause there is no parent. Let's say size is 500x300.
Item {
id: container
width: 500
height: 300
Or if you don't want to give a constant size, but to make size exactly to fit content childrenRect can be used. Make sure your content size does not depend on root and has a valid width and height before use it. And it might cause "binding loop detected for width/height." warnings.
Item {
id: container
width: childrenRect.width
height: childrenRect.height
And if you want your scene to resize respect to QQuickWidget's size dynamically set resize mode.
ui->quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
Let's get to coloring point. To change root item's color we can use Rectangle.color property. So change root object from Item to Rectangle. Let's make background red.
Rectangle {
id: container
width: childrenRect.width
height: childrenRect.height
color: "red"
Or if you want to change window color of QQuickWidget, set the palette. But since your scene going to cover it, I doubt that is what you need.
auto palette = ui->quickWidget->palette();
palette.setColor(QPalette::Window, QColor(Qt::red));
ui->quickWidget->setPalette(palette);
And you have one more problem:
qrc:/qml/qml/test.qml:20: ReferenceError: valueSource is not defined
I have no idea what valueSource is, either make sure you have it or get rid of it.
Assume you have created the following custom QGraphicsRectItem in C++:
class MyCustomItem : public QGraphicsRectItem
{
public:
MyCustomItem(MyCustomItem* a_Parent = 0);
virtual ~MyCustomItem();
// specific methods
private:
// specific data
};
Assume also that you have defined in a QML script an ApplicationWindow:
// main.qml
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.0
ApplicationWindow {
id: myWindow
title: qsTr("My Window")
width: 640
height: 480
visible: true
}
The simple task I would like to do is to display an instance of MyCustomItem in that ApplicationWindow. I wanted to do the following:
// part of main.cpp
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
MyCustomItem* myItem;
engine.rootContext()->setContextProperty("MyCustomItem", myItem);
return app.exec();
}
But of course this doesn't work, because MyCustomItem is neither a QObject nor a QVariant. I don't want my item to be anything else than a QGraphicsRectItem. Isn't that possible to display that graphics item? That should be simple as hell, shouldn't it? Is there a way with QDeclarativeItem or something? I can't find how to solve this problem, that's very frustrating. Would I implement my application with "normal" Qt, the problem would already be solved, because in this case you have a scene, and the scene has a member method addItem() and I don't need to do complicated stuff to add my custom graphics item to my scene. Do I have to wrap this item in a QDeclarativeItem or a QObject in order to get the thing done? That would be so awful, in my opinion. Aren't there better options?
EDIT
Can that be that QGraphicsRectItem is not the right class to inherit from and that something like QQuickPaintedItem (as suggested in the comments) would be more appropriate?
I can't speak for Qt 4, but in Qt 5, you have several options for custom drawing:
QQuickPaintedItem
A QPainter-based QQuickItem. This sounds the closest to what you want. A snippet from the documentation of one of the examples:
void TextBalloon::paint(QPainter *painter)
{
QBrush brush(QColor("#007430"));
painter->setBrush(brush);
painter->setPen(Qt::NoPen);
painter->setRenderHint(QPainter::Antialiasing);
painter->drawRoundedRect(0, 0, boundingRect().width(), boundingRect().height() - 10, 10, 10);
if (rightAligned)
{
const QPointF points[3] = {
QPointF(boundingRect().width() - 10.0, boundingRect().height() - 10.0),
QPointF(boundingRect().width() - 20.0, boundingRect().height()),
QPointF(boundingRect().width() - 30.0, boundingRect().height() - 10.0),
};
painter->drawConvexPolygon(points, 3);
}
else
{
const QPointF points[3] = {
QPointF(10.0, boundingRect().height() - 10.0),
QPointF(20.0, boundingRect().height()),
QPointF(30.0, boundingRect().height() - 10.0),
};
painter->drawConvexPolygon(points, 3);
}
}
Canvas
JavaScript-based drawing QML type with an HTML5-like API. A snippet from one of the examples:
Canvas {
id: canvas
width: 320
height: 250
antialiasing: true
property color strokeStyle: Qt.darker(fillStyle, 1.2)
property color fillStyle: "#6400aa"
property int lineWidth: 2
property int nSize: nCtrl.value
property real radius: rCtrl.value
property bool fill: true
property bool stroke: false
property real px: width/2
property real py: height/2 + 10
property real alpha: 1.0
onRadiusChanged: requestPaint();
onLineWidthChanged: requestPaint();
onNSizeChanged: requestPaint();
onFillChanged: requestPaint();
onStrokeChanged: requestPaint();
onPaint: squcirle();
function squcirle() {
var ctx = canvas.getContext("2d");
var N = canvas.nSize;
var R = canvas.radius;
N=Math.abs(N);
var M=N;
if (N>100) M=100;
if (N<0.00000000001) M=0.00000000001;
ctx.save();
ctx.globalAlpha =canvas.alpha;
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.strokeStyle = canvas.strokeStyle;
ctx.fillStyle = canvas.fillStyle;
ctx.lineWidth = canvas.lineWidth;
ctx.beginPath();
var i = 0, x, y;
for (i=0; i<(2*R+1); i++){
x = Math.round(i-R) + canvas.px;
y = Math.round(Math.pow(Math.abs(Math.pow(R,M)-Math.pow(Math.abs(i-R),M)),1/M)) + canvas.py;
if (i == 0)
ctx.moveTo(x, y);
else
ctx.lineTo(x, y);
}
for (i=(2*R); i<(4*R+1); i++){
x =Math.round(3*R-i)+canvas.px;
y = Math.round(-Math.pow(Math.abs(Math.pow(R,M)-Math.pow(Math.abs(3*R-i),M)),1/M)) + canvas.py;
ctx.lineTo(x, y);
}
ctx.closePath();
if (canvas.stroke) {
ctx.stroke();
}
if (canvas.fill) {
ctx.fill();
}
ctx.restore();
}
}
QSGGeometryNode
As mentioned in this answer, you could take advantage of the Qt Quick Scene Graph. A snippet from one of the examples:
QSGNode *BezierCurve::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
QSGGeometryNode *node = 0;
QSGGeometry *geometry = 0;
if (!oldNode) {
node = new QSGGeometryNode;
geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), m_segmentCount);
geometry->setLineWidth(2);
geometry->setDrawingMode(GL_LINE_STRIP);
node->setGeometry(geometry);
node->setFlag(QSGNode::OwnsGeometry);
QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
material->setColor(QColor(255, 0, 0));
node->setMaterial(material);
node->setFlag(QSGNode::OwnsMaterial);
} else {
node = static_cast<QSGGeometryNode *>(oldNode);
geometry = node->geometry();
geometry->allocate(m_segmentCount);
}
QRectF bounds = boundingRect();
QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D();
for (int i = 0; i < m_segmentCount; ++i) {
qreal t = i / qreal(m_segmentCount - 1);
qreal invt = 1 - t;
QPointF pos = invt * invt * invt * m_p1
+ 3 * invt * invt * t * m_p2
+ 3 * invt * t * t * m_p3
+ t * t * t * m_p4;
float x = bounds.x() + pos.x() * bounds.width();
float y = bounds.y() + pos.y() * bounds.height();
vertices[i].set(x, y);
}
node->markDirty(QSGNode::DirtyGeometry);
return node;
}
QQuickWidget
If you really want to use QGraphicsItem subclasses, you could go the opposite direction, and have a widget-based app that contains certain "Qt Quick Widgets", though this is not optimal (see Qt Weekly #16: QQuickWidget for more information).
My environment is the following:
Qt 5.4, build from source with -platform win32-msvc2013 -opengl desktop -no-icu -skip webkit
Visual Studio 2013
Windows 7 x64
Consider the following setup (A QScrollArea containing a centered widget with fixed size):
QScrollArea scrollArea;
scrollArea.setAlignment(Qt::AlignCenter);
scrollArea.setWidgetResizable(false);
QWidget scrollAreaWidgetContents;
scrollArea.setWidget(scrollAreaWidgetContents);
Now, I want to resize that widget within my program like the following:
int w = 200, h = 200;
scrollAreaWidgetContents.setGeometry(0, 0, w, h);
And here comes the strange behavior:
If w and h are equal to the current width and height (i.e. nothing changes), the widget jumps to the upper left corner.
If w and h are different from the current width and height, the widgets stays at its centered position and changes its size correctly.
I have written a little demo application that demonstrates the issue. If you click the pushButton_Stay button, the widgets jumps to the upper left corner.
#include <QtWidgets/QApplication>
#include <QPushButton>
#include <QVBoxLayout>
#include <QScrollArea>
QScrollArea *scrollArea;
QWidget *scrollAreaWidgetContents;
QPushButton *pushButton_Up;
QPushButton *pushButton_Down;
QPushButton *pushButton_Stay;
QVBoxLayout *layout;
int w = 200, h = 200;
void sizeUp() {
w += 10;
h += 10;
scrollAreaWidgetContents->setGeometry(0, 0, w, h);
}
void sizeDown() {
w -= 10;
h -= 10;
scrollAreaWidgetContents->setGeometry(0, 0, w, h);
}
void sizeStay() {
scrollAreaWidgetContents->setGeometry(0, 0, w, h);
}
int main(int argv, char **args)
{
QApplication app(argv, args);
// Scroll area
scrollArea = new QScrollArea;
scrollArea->setWidgetResizable(false);
scrollArea->setAlignment(Qt::AlignCenter);
scrollAreaWidgetContents = new QWidget();
scrollAreaWidgetContents->setGeometry(QRect(0, 0, w, h));
scrollAreaWidgetContents->setAutoFillBackground(true);
QPalette Pal(scrollAreaWidgetContents->palette());
Pal.setColor(QPalette::Background, Qt::black);
scrollAreaWidgetContents->setPalette(Pal);
scrollArea->setWidget(scrollAreaWidgetContents);
// Buttons
pushButton_Up = new QPushButton(scrollAreaWidgetContents);
pushButton_Up->setGeometry(QRect(85, 50, 31, 23));
pushButton_Up->setText("+");
pushButton_Down = new QPushButton(scrollAreaWidgetContents);
pushButton_Down->setGeometry(QRect(85, 110, 31, 23));
pushButton_Down->setText("-");
pushButton_Stay = new QPushButton(scrollAreaWidgetContents);
pushButton_Stay->setGeometry(QRect(85, 80, 31, 23));
pushButton_Stay->setText("0");
QObject::connect(pushButton_Up, &QPushButton::clicked, sizeUp);
QObject::connect(pushButton_Stay, &QPushButton::clicked, sizeStay);
QObject::connect(pushButton_Down, &QPushButton::clicked, sizeDown);
// Central layout
layout = new QVBoxLayout;
layout->addWidget(scrollArea);
// Main window
QWidget window;
window.setGeometry(200, 200, 400, 400);
window.setLayout(layout);
window.show();
return app.exec();
}
Clicking the pushButton_Up button:
Clicking the pushButton_Stay button:
Questions:
What's going wrong here?
Is it a bug? An if and yes, can anyone confirm it?
If it's not a bug, how can I make it that the widget always stays centered?
What's going wrong here?
Is it a bug? An if and yes, can anyone confirm it?
It seems the second call of setGeometry with the same arguments use different origin, and the coordinates (0, 0) make the widget move to top-left corner. You can use other coordinates such as setGeometry(100, 50, w, h) to see the difference.
Here is the source code of QWidget::setGeometry:
if (testAttribute(Qt::WA_WState_Created)) {
d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true);
d->setDirtyOpaqueRegion();
} else {
data->crect.setTopLeft(r.topLeft());
// ^^^^^^^^^ Could be the reason why (0, 0) move to top-left
data->crect.setSize(r.size().boundedTo(maximumSize()).expandedTo(minimumSize()));
setAttribute(Qt::WA_PendingMoveEvent);
setAttribute(Qt::WA_PendingResizeEvent);
}
Personally I think it's a bug, but more evidences need to be provided until we can confirm it.
If it's not a bug, how can I make it that the widget always stays
centered?
Actually you don't have to call setGeometry if you just want to resize the widget. Use resize instead:
void sizeStay() {
scrollAreaWidgetContents->resize(w, h);
}
It solves the problem in your case.
I'm trying to scale an object about the mouse cursor. I'm getting the mouse position easily enough, and I can scale the object no problem using item->setScale(n). However, I'm not sure how to actually incorporate the translation to account for the arbitrary point.
Is there a way to set the scale center? If not, how should I go about doing this?
This is what I have so far for my zoom in:
center = this->mapFromParent(center);
qDebug() << center;
this->setTransformOriginPoint(center);
QTransform transform;
transform = transform.scale(transform.m11() * 1.05, transform.m22() * 1.05);
this->setTransform(transform, true);
this->setTransformOriginPoint(0, 0);
Take a look at QGraphicsItem::setTransformOriginPoint(). It takes the position in item coordinates, so you'll probably have to map the mouse position to item coordinates.
I think this seems to be working as you expect:
class Scene : public QGraphicsScene
{
public:
QGraphicsItem* item;
Scene(QObject* parent = nullptr)
: QGraphicsScene(parent)
{
setSceneRect(0, 0, 500, 500);
item = addRect(200, 200, 100, 100, QPen(Qt::black), QBrush(Qt::red));
}
void wheelEvent(QGraphicsSceneWheelEvent* event)
{
/*Scale 0.2 each turn of the wheel (which is usually 120.0 eights of degrees)*/
qreal scaleFactor = 1.0 + event->delta() * 0.2 / 120.0;
item->setTransformOriginPoint(item->mapFromScene(event->scenePos()));
item->setScale(item->scale() * scaleFactor);
}
};
int main(int argc, char ** argv)
{
QApplication a(argc, argv);
Scene* scene = new Scene;
QGraphicsView view(scene);
view.resize(600, 600);
view.show();
return a.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.