К моему огромному огорчению в QML не оказалось линии для рисования. Ну да не беда, нарисуем своими руками :)
Итак, все описание сделаем в одном заголовочном файле, дабы не засорять проект. Описание линии:
Всё это размещаете в файле line.h, который добавляете в проект.
В файле проекта добавляем:
В начало QML файла подключаем нашу компоненту:
import CustomComponents 1.0
Ну и рисуем где-нибудь линию:
Line
Итак, все описание сделаем в одном заголовочном файле, дабы не засорять проект. Описание линии:
#ifndef LINE_H #define LINE_H #include <QDeclarativeItem> #include <QPainter> class Line : public QDeclarativeItem { Q_OBJECT Q_PROPERTY(int x1 READ x1 WRITE setX1 NOTIFY x1Changed) Q_PROPERTY(int y1 READ y1 WRITE setY1 NOTIFY y1Changed) Q_PROPERTY(int x2 READ x2 WRITE setX2 NOTIFY x2Changed) Q_PROPERTY(int y2 READ y2 WRITE setY2 NOTIFY y2Changed) Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) Q_PROPERTY(int penWidth READ penWidth WRITE setPenWidth NOTIFY penWidthChanged) public: Line(QDeclarativeItem *parent = 0) : QDeclarativeItem(parent), m_x1(0), m_y1(0), m_x2(0), m_y2(0), m_color(Qt::black), m_penWidth(1) { // Important, otherwise the paint method is never called setFlag(QGraphicsItem::ItemHasNoContents, false); } void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { QPen pen(m_color, m_penWidth); painter->setPen(pen); if(smooth() == true) { painter->setRenderHint(QPainter::Antialiasing, true); } int x = qMin(m_x1, m_x2) - m_penWidth/2; int y = qMin(m_y1, m_y2) - m_penWidth/2; painter->drawLine(m_x1 - x, m_y1 - y, m_x2 - x, m_y2 - y); } // Get methods int x1() const { return m_x1; } int y1() const { return m_y1; } int x2() const { return m_x2; } int y2() const { return m_y2; } QColor color() const { return m_color; } int penWidth() const { return m_penWidth; } // Set methods void setX1(int x1) { if(m_x1 == x1) return; m_x1 = x1; updateSize(); emit x1Changed(); update(); } void setY1(int y1) { if(m_y1 == y1) return; m_y1 = y1; updateSize(); emit y1Changed(); update(); } void setX2(int x2) { if(m_x2 == x2) return; m_x2 = x2; updateSize(); emit x2Changed(); update(); } void setY2(int y2) { if(m_y2 == y2) return; m_y2 = y2; updateSize(); emit x2Changed(); update(); } void setColor(const QColor &color) { if(m_color == color) return; m_color = color; emit colorChanged(); update(); } void setPenWidth(int newWidth) { if(m_penWidth == newWidth) return; m_penWidth = newWidth; updateSize(); emit penWidthChanged(); update(); } signals: void x1Changed(); void y1Changed(); void x2Changed(); void y2Changed(); void colorChanged(); void penWidthChanged(); protected: void updateSize() { setX(qMin(m_x1, m_x2) - m_penWidth/2); setY(qMin(m_y1, m_y2) - m_penWidth/2); setWidth(qAbs(m_x2 - m_x1) + m_penWidth); setHeight(qAbs(m_y2 - m_y1) + m_penWidth); } protected: int m_x1; int m_y1; int m_x2; int m_y2; QColor m_color; int m_penWidth; }; QML_DECLARE_TYPE(Line) #endif // LINE_H#ifndef LINE_H #define LINE_H #include <QDeclarativeItem> #include <QPainter> class Line : public QDeclarativeItem { Q_OBJECT Q_PROPERTY(int x1 READ x1 WRITE setX1 NOTIFY x1Changed) Q_PROPERTY(int y1 READ y1 WRITE setY1 NOTIFY y1Changed) Q_PROPERTY(int x2 READ x2 WRITE setX2 NOTIFY x2Changed) Q_PROPERTY(int y2 READ y2 WRITE setY2 NOTIFY y2Changed) Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) Q_PROPERTY(int penWidth READ penWidth WRITE setPenWidth NOTIFY penWidthChanged) public: Line(QDeclarativeItem *parent = 0) : QDeclarativeItem(parent), m_x1(0), m_y1(0), m_x2(0), m_y2(0), m_color(Qt::black), m_penWidth(1) { // Important, otherwise the paint method is never called setFlag(QGraphicsItem::ItemHasNoContents, false); } void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { QPen pen(m_color, m_penWidth); painter->setPen(pen); if(smooth() == true) { painter->setRenderHint(QPainter::Antialiasing, true); } int x = qMin(m_x1, m_x2) - m_penWidth/2; int y = qMin(m_y1, m_y2) - m_penWidth/2; painter->drawLine(m_x1 - x, m_y1 - y, m_x2 - x, m_y2 - y); } // Get methods int x1() const { return m_x1; } int y1() const { return m_y1; } int x2() const { return m_x2; } int y2() const { return m_y2; } QColor color() const { return m_color; } int penWidth() const { return m_penWidth; } // Set methods void setX1(int x1) { if(m_x1 == x1) return; m_x1 = x1; updateSize(); emit x1Changed(); update(); } void setY1(int y1) { if(m_y1 == y1) return; m_y1 = y1; updateSize(); emit y1Changed(); update(); } void setX2(int x2) { if(m_x2 == x2) return; m_x2 = x2; updateSize(); emit x2Changed(); update(); } void setY2(int y2) { if(m_y2 == y2) return; m_y2 = y2; updateSize(); emit x2Changed(); update(); } void setColor(const QColor &color) { if(m_color == color) return; m_color = color; emit colorChanged(); update(); } void setPenWidth(int newWidth) { if(m_penWidth == newWidth) return; m_penWidth = newWidth; updateSize(); emit penWidthChanged(); update(); } signals: void x1Changed(); void y1Changed(); void x2Changed(); void y2Changed(); void colorChanged(); void penWidthChanged(); protected: void updateSize() { setX(qMin(m_x1, m_x2) - m_penWidth/2); setY(qMin(m_y1, m_y2) - m_penWidth/2); setWidth(qAbs(m_x2 - m_x1) + m_penWidth); setHeight(qAbs(m_y2 - m_y1) + m_penWidth); } protected: int m_x1; int m_y1; int m_x2; int m_y2; QColor m_color; int m_penWidth; }; QML_DECLARE_TYPE(Line) #endif // LINE_H
Всё это размещаете в файле line.h, который добавляете в проект.
В файле проекта добавляем:
QT += declarativeВместе с добавленными библиотеками и нашей линией, main.cpp станет выглядеть так:
#include <QtGui/QApplication> #include <QColor> #include <QDeclarativeView> #include "qmlapplicationviewer.h" #include "line.h" Q_DECL_EXPORT int main(int argc, char *argv[]) { QScopedPointer<QApplication> app(createApplication(argc, argv)); qmlRegisterType<Line>("CustomComponents", 1, 0, "Line"); QmlApplicationViewer viewer; viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto); viewer.setMainQmlFile(QLatin1String("qml/KnowledgeWeb/main.qml")); viewer.showExpanded(); return app->exec(); }Ну и на последок, остаётся дело за малым - нарисовать какую-нибудь линию.
В начало QML файла подключаем нашу компоненту:
import CustomComponents 1.0
Ну и рисуем где-нибудь линию:
Line
{ x1: 0 y1: 0 x2: 100 y2: 100 penWidth: 2 color: "darkRed" }Вуаля :)
Круто. Спасибо
ОтветитьУдалитьуже не работает:(
ОтветитьУдалить// немного обновил код к версии QtQuick 2.x
ОтветитьУдалить// автору все равно спасибо за код, он был опорой, может кому будет еще полезен так что вот:)
#ifndef QMLLINE_H
#define QMLLINE_H
#include
#include
#include
#include
class QmlLine : public QQuickPaintedItem
{
Q_OBJECT
Q_DISABLE_COPY(QmlLine)
Q_PROPERTY(int x1 READ x1 WRITE setX1 NOTIFY x1Changed)
Q_PROPERTY(int y1 READ y1 WRITE setY1 NOTIFY y1Changed)
Q_PROPERTY(int x2 READ x2 WRITE setX2 NOTIFY x2Changed)
Q_PROPERTY(int y2 READ y2 WRITE setY2 NOTIFY y2Changed)
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
Q_PROPERTY(int penWidth READ penWidth WRITE setPenWidth NOTIFY penWidthChanged)
public:
QmlLine() : m_x1(0), m_y1(0), m_x2(0), m_y2(0),
m_color(Qt::black), m_penWidth(1)
{
// Important, otherwise the paint method is never called
this->setFlag(ItemHasContents, true);
}
void paint(QPainter *painter)
{
QPen pen(m_color, m_penWidth);
painter->setPen(pen);
if(smooth() == true) {
painter->setRenderHint(QPainter::Antialiasing, true);
}
int x = qMin(m_x1, m_x2) - m_penWidth/2;
int y = qMin(m_y1, m_y2) - m_penWidth/2;
painter->drawLine(m_x1 - x, m_y1 - y, m_x2 - x, m_y2 - y);
}
// Get methods
int x1() const { return m_x1; }
int y1() const { return m_y1; }
int x2() const { return m_x2; }
int y2() const { return m_y2; }
QColor color() const { return m_color; }
int penWidth() const { return m_penWidth; }
// Set methods
void setX1(int x1) {
if(m_x1 == x1) return;
m_x1 = x1;
updateSize();
emit x1Changed();
update();
}
void setY1(int y1) {
if(m_y1 == y1) return;
m_y1 = y1;
updateSize();
emit y1Changed();
update();
}
void setX2(int x2) {
if(m_x2 == x2) return;
m_x2 = x2;
updateSize();
emit x2Changed();
update();
}
void setY2(int y2) {
if(m_y2 == y2) return;
m_y2 = y2;
updateSize();
emit x2Changed();
update();
}
void setColor(const QColor &color) {
if(m_color == color) return;
m_color = color;
emit colorChanged();
update();
}
void setPenWidth(int newWidth) {
if(m_penWidth == newWidth) return;
m_penWidth = newWidth;
updateSize();
emit penWidthChanged();
update();
}
signals:
void x1Changed();
void y1Changed();
void x2Changed();
void y2Changed();
void colorChanged();
void penWidthChanged();
protected:
void updateSize() {
setX(qMin(m_x1, m_x2) - m_penWidth/2);
setY(qMin(m_y1, m_y2) - m_penWidth/2);
setWidth(qAbs(m_x2 - m_x1) + m_penWidth);
setHeight(qAbs(m_y2 - m_y1) + m_penWidth);
}
protected:
int m_x1;
int m_y1;
int m_x2;
int m_y2;
QColor m_color;
int m_penWidth;
public:
static void declare() {
qmlRegisterType("LineComponent", 1, 0, "Line");
}
};
#endif // QMLLINE_H
опа! тут в коментариях теги запрещены поэтому в инклюдах следующее:
ОтветитьУдалить#include "QObject"
#include "QtQml"
#include "QPainter"
#include "QQuickPaintedItem"
потом внизу:
qmlRegisterType[QmlLine]("LineComponent", 1, 0, "Line");
где скобки [] заменить на контейнерные
Этот комментарий был удален автором.
Удалитьа в main.cpp
ОтветитьУдалитьпросто:
//...<-тут все инклюды
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
QmlLine::declare(); //<- первый способ
//qmlRegisterType[QmlLine]("LineComponent", 1, 0, "Line"); //<- второй способ
// ...
engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
return app.exec();
}
и последний фикс в классе, там не учитывается то что края при большой толщине линии будут срезаться, поэтому такой фикс нужно сделать:
ОтветитьУдалитьvoid paint(QPainter *painter)
{
QPen pen(m_color, m_penWidth);
painter->setPen(pen);
if(smooth() == true) {
painter->setRenderHint(QPainter::Antialiasing, true);
}
int x = qMin(m_x1, m_x2) - m_penWidth/2;
int y = qMin(m_y1, m_y2) - m_penWidth/2;
float A = m_penWidth/2.0; // <--
float delta = A*qSin(45); // <--
painter->drawLine(m_x1 - x + delta, m_y1 - y + delta, m_x2 - x - delta, m_y2 - y - delta); // <--
}
но это если надо:)
ОтветитьУдалить