1.说明
QQuickPaintedItem类提供了一种在QML场景图中使用QPainter API的方法。
QQuickPaintedItem本身作为Item,也可以在ListView中作为代理使用。
案例本身是官方的例子,但是使用的方式是用qml的插件方式,先修改成普通的注册类型使用。插件以后再学习。
2.程序截图
程序运行界面如图:
3.TextBalloon 类
3.1 TextBalloon.h
#ifndef TEXTBALLOON_H
#define TEXTBALLOON_H
#include <QQuickPaintedItem>
#include <QQuickItem>
#include <QtQml>
class TextBalloon : public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY(bool rightAligned READ isRightAligned WRITE setRightAligned NOTIFY rightAlignedChanged)
public:
TextBalloon(QQuickItem *parent = 0);
public:
virtual void paint(QPainter *painter) override;
bool isRightAligned() const;
void setRightAligned(bool newRightAligned);
const QColor &background() const;
void setBackground(const QColor &newBackground);
signals:
// QQuickPaintedItem interface
void rightAlignedChanged();
void backgroundChanged();
private:
bool m_rightAligned;
QColor m_background;
Q_PROPERTY(QColor background READ background WRITE setBackground NOTIFY backgroundChanged)
};
#endif // TEXTBALLOON_H
3.2 TextBalloon.cpp
#include "TextBalloon.h"
#include <QBrush>
#include <QPainter>
TextBalloon::TextBalloon(QQuickItem *parent)
:QQuickPaintedItem(parent)
,m_rightAligned(false)
,m_background("steelblue")
{
}
void TextBalloon::paint(QPainter *painter)
{
painter->setBrush(m_background);
painter->setPen(Qt::NoPen);
painter->setRenderHint(QPainter::Antialiasing);
QSizeF itemSize = size();
painter->drawRoundedRect(0, 0, itemSize.width(), itemSize.height() - 10, 10, 10);
if (m_rightAligned)
{
const QPointF points[3] = {
QPointF(itemSize.width() - 10.0, itemSize.height() - 10.0),
QPointF(itemSize.width() - 20.0, itemSize.height()),
QPointF(itemSize.width() - 30.0, itemSize.height() - 10.0),
};
painter->drawConvexPolygon(points, 3);
}
else
{
const QPointF points[3] = {
QPointF(10.0, itemSize.height() - 10.0),
QPointF(20.0, itemSize.height()),
QPointF(30.0, itemSize.height() - 10.0),
};
painter->drawConvexPolygon(points, 3);
}
}
bool TextBalloon::isRightAligned() const
{
return m_rightAligned;
}
void TextBalloon::setRightAligned(bool newRightAligned)
{
if (m_rightAligned == newRightAligned)
return;
m_rightAligned = newRightAligned;
emit rightAlignedChanged();
}
const QColor &TextBalloon::background() const
{
return m_background;
}
void TextBalloon::setBackground(const QColor &newBackground)
{
if (m_background == newBackground)
return;
m_background = newBackground;
emit backgroundChanged();
}
3.3 textballoons.qml
// textballoons.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQml.Models 2.15
import TextBalloon 1.0
Item {
height: 480
width: 320
// 消息显示栏
ListView{
id:listView
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: row.top
spacing:10
delegate: TextBalloon{
x: rightAligned ? listView.width - width : 0
width: msg.width
height: msg.implicitHeight + 10
rightAligned: index%2
background: "#1e6eff"
Label{
padding: 10
id: msg
text:message
color: "white"
width: implicitWidth > listView.width ? listView.width : implicitWidth
wrapMode: Label.Wrap
}
}
model: ListModel{id:listModel}
} // 消息显示栏 end
// 发送栏
Row{
id:row
height: 30
spacing: 10
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
// 消息输入框
Rectangle{
width: parent.width-50-parent.spacing
height: parent.height
border.color: "black"
TextEdit{
id : edit
text: "聊天内容xxxx"
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
}
} // 消息输入框 end
Button{
width: 50
height: parent.height
text: "发送"
property real index: 1
onClicked: {
index *= 10
listModel.append({"message":edit.text+index});
listView.positionViewAtEnd()
}
}
} // 发送栏 end
}
3.4 main.cpp
#include <QApplication>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickView>
#include "TextBalloon.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterType<TextBalloon>("TextBalloon",1,0,"TextBalloon");
QQuickView view;
view.setSource(QUrl(QStringLiteral("qrc:/painteditem/textballoons.qml")));
view.show();
return app.exec();
}