QML 實現 PathView 主要分下面幾步
1 注意幾個關鍵函數的實現
//向View 傳輸當前索引
int GetCurrentIndex(){return currentIndex;}
void SetCurrentIndex(const int curIndex) {currentIndex = curIndex; emit CurrentIndexChanged();}
2 // 必須要實現的虛函數
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const;
//插入element 時
void QMyModel::InsertElement()
{
QMyElement element(nullptr);
QString key = QString::number(qrand() %10000);
element.donorName = "Test element ";
element.IPAddress = "0.0.0.0: Test " + key;
elementMap.insert(key,element);
int i = GetMapKeyIndex(elementMap, key);
beginInsertRows(QModelIndex(), i, i);
endInsertRows();
SetCurrentIndex(i);
}
更新element 時 dataChanged(modeStart, modeEnd);
void QMyModel::ResetData(int i)
{
QModelIndex modeStart = createIndex(i, -1);
QModelIndex modeEnd = createIndex(i, -1);
dataChanged(modeStart, modeEnd);
SetCurrentIndex(i);
}
3 注意 main.qml 中
Component {
id:delegate
} 對應 PathView 中 delegate 屬性
PathView {
id: pathView;
anchors.fill: parent
currentIndex: MyModel.GetCurrentIndex;
x: 500
y: 0
width: 1000;
height: 900;
model: MyModel
delegate: delegate
4 注意 main函數中 MyModel 和 QMyModel 對應
QMyModel model;
gMyModel = &model;
QtQuick2ApplicationViewer viewer;
QQmlContext *ctxt = viewer.rootContext();
ctxt->setContextProperty("MyModel", &model);
Qmymodel.h 文件
定義QMyModel 類
#ifndef QMYMODEL_H
#define QMYMODEL_H
#include <QAbstractListModel>
#include <QColor>
#include "QMyElement.h"
#include <QMap>
int GetMapKeyIndex(QMap<QString, QMyElement> &map, QString key);
class QMyModel : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(int GetCurrentIndex READ GetCurrentIndex WRITE SetCurrentIndex NOTIFY CurrentIndexChanged)
public:
enum LineInfo_Roles{
DeviceID =Qt::UserRole + 1,
DonorID,
DonorName,
OperatorID,
OperatorName,
Index,
IPAddress,
Port
};
QMyModel(QObject *parent = 0);
~QMyModel();
//向View 傳輸當前索引
int GetCurrentIndex(){return currentIndex;}
void SetCurrentIndex(const int curIndex) {currentIndex = curIndex; emit CurrentIndexChanged();}
// 必須要實現的虛函數
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const;
private:
QVector<QString> m_chatItem;
QString m_Name;
QColor m_color;
int currentIndex;
public:
//ThriftUdpServer tUdpServer;
public:
QList<QMyElement> elementList;
QMap<QString, QMyElement> elementMap;
signals:
void ResetDataSignal(int i);
void InsertElementSignal(int i);
void CurrentIndexChanged();
public slots:
void ResetData(int i);
void InsertElement();
void InsertElement(int i);
void RemoveElement(int i);
};
#endif // QMYMODEL_H
實現QMyModel 類 Qmymodel.cpp
#include "qmymodel.h"
QMyModel::QMyModel(QObject *parent)
: QAbstractListModel(parent)
{
//tUdpServer.Init();
//tUdpServer.RunServer();
connect(this, SIGNAL(ResetDataSignal(int)), this, SLOT(ResetData(int)));
connect(this, SIGNAL(InsertElementSignal(int)), this, SLOT(InsertElement(int)));
}
QMyModel::~QMyModel()
{
}
void QMyModel::setName(const QString &name)
{
}
void QMyModel::setColor(const QColor &color)
{
}
int QMyModel::rowCount(const QModelIndex &parent /*= QModelIndex()*/) const
{
return elementMap.size();
}
QHash<int, QByteArray> QMyModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[DeviceID] = "DeviceID";
roles[DonorID] = "DonorID";
roles[DonorName]= "DonorName";
roles[OperatorID]= "OperatorID";
roles[OperatorName]= "OperatorName";
roles[Index]= "Index";
roles[IPAddress]= "IPAddress";
roles[Port]= "Port";
return roles;
}
QVariant QMyModel::data(const QModelIndex &index, int role /*= Qt::DisplayRole*/) const
{
//
QList<QString> keysList = elementMap.keys();
if (keysList.isEmpty())
{
return QVariant();
}
QString key = keysList[index.row()];
QMyElement element = elementMap[key];
switch(role)
{
case DeviceID:
return element.deviceID;
case DonorID:
return element.donorID;
case DonorName:
return element.donorName;
case OperatorID:
return element.operatorID;
case OperatorName:
return element.operatorName;
case Index:
return element.index;
case IPAddress:
return element.IPAddress;
case Port:
return element.port;
}
return QVariant();
}
void QMyModel::ResetData(int i)
{
QModelIndex modeStart = createIndex(i, -1);
QModelIndex modeEnd = createIndex(i, -1);
dataChanged(modeStart, modeEnd);
SetCurrentIndex(i);
}
int GetMapKeyIndex(QMap<QString, QMyElement> &map, QString key)
{
QList<QString> keylist = map.keys();
int i = 0;
int keyIndex = -1;
while(i < keylist.size())
{
if (key.compare(keylist[i]) == 0)
{
keyIndex = i;
break;
}
i++;
}
return keyIndex;
}
/// Test methon
void QMyModel::InsertElement()
{
QMyElement element(nullptr);
QString key = QString::number(qrand() %10000);
element.donorName = "Test element ";
element.IPAddress = "0.0.0.0: Test " + key;
elementMap.insert(key,element);
int i = GetMapKeyIndex(elementMap, key);
beginInsertRows(QModelIndex(), i, i);
endInsertRows();
SetCurrentIndex(i);
printf("currentIndex %d \n", i);
}
void QMyModel::InsertElement(int i)
{
beginInsertRows(QModelIndex(), i, i);
endInsertRows();
SetCurrentIndex(i);
}
void QMyModel::RemoveElement(int i)
{
if (i < 0)
{
return;
}
beginRemoveRows(QModelIndex(), i, i);
endRemoveRows();
QList<QString> keysList = elementMap.keys();
if (keysList.isEmpty())
{
return ;
}
QString key = keysList[i];
QMyElement element = elementMap[key];
QMap<QString, QMyElement>::Iterator it = elementMap.find(key);
elementMap.erase(it);
SetCurrentIndex(i-1);
}
定義PathView 注意 model:MyModel
main.Qml
import QtQuick 2.0
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.2
Rectangle {
id : root
width: 1600
height: 900
property int fontSize: 18;
property int rW: 600;
property int rH: 450;
property int sX: 20;
property int sY: 20;
Keys.onEscapePressed: {
Qt.quit();
}
//color: "lightskyblue"
gradient: Gradient {
GradientStop { position: 0.0; color: Qt.rgba(Math.random() , Math.random(), Math.random(), 1);}
GradientStop { position: 0.5; color: "#0000DD";}
GradientStop { position: 1.0; color: Qt.rgba(Math.random() , Math.random(), Math.random(), 1); }
}
Component {
id: delegate
Rectangle{
id: wrapper
//id : rect
width: rW
height: rH
//color: Qt.rgba(Math.random() , Math.random(), Math.random(), 1);
gradient: Gradient {
GradientStop { position: 0.0; color: Qt.rgba(Math.random() , Math.random(), Math.random(), 1);}
GradientStop { position: 0.5; color: "#0000DD";}
GradientStop { position: 1.0; color: Qt.rgba(Math.random() , Math.random(), Math.random(), 1); }
}
border.width: 5
border.color: wrapper.PathView.isCurrentItem ? "red" : "lightgray";
z: PathView.zOrder;
opacity: PathView.itemAlpha;
scale: PathView.itemScale;
MouseArea {
anchors.fill: parent
onClicked: {
pathView.currentIndex = index;
console.log("mouse clicked ", pathView.currentIndex);
}
}
//左側
Column{
spacing: rH *0.03;
x: rW * 0.05;
y: rH *0.05;
//左側第一行
Row {
spacing: rW * 0.03
Rectangle{
width: rW * 0.15;
height: rH * 0.1;
color: "#3A87F1"
radius: 5;
Text{
anchors.horizontalCenter: parent.horizontalCenter;
anchors.verticalCenter: parent.verticalCenter;
text: "PROTOCOL\nText";
font.pixelSize: fontSize;
color: "yellow"
font.bold: true
}
}
Rectangle{
width: rW * 0.20;
height: rH * 0.1;
color: "#3A87F1"
radius: 5;
Text{
anchors.horizontalCenter: parent.horizontalCenter;
anchors.verticalCenter: parent.verticalCenter;
text: "PLASMA\nText";
font.pixelSize: fontSize;
color: "yellow"
font.bold: true
}
}
Rectangle{
width: rW * 0.15;
height: rH * 0.1;
color: "#3A87F1"
radius: 5;
Text{
anchors.horizontalCenter: parent.horizontalCenter;
anchors.verticalCenter: parent.verticalCenter;
text: "CYCLE\nText";
font.pixelSize: fontSize;
color: "yellow"
font.bold: true
}
}
}
//左側第二行
Rectangle{
width: rW *0.56;
height: rH *0.3;
color: "#EEEEEE"
radius: 5;
Text{
//anchors.horizontalCenter: parent.horizontalCenter;
x: rW * 0.05;
anchors.verticalCenter: parent.verticalCenter;
text: DeviceID + "\n\n" + IPAddress + " : " + Port;
font.pixelSize: fontSize + 6;
color: "blue"
font.bold: true
}
}
//左側第三行
Rectangle{
width: rW *0.56;
height: rH *0.15;
color: "#9ABCF3"
radius: 5;
Column{
x: rW *0.01;
y: rH *0.01;
//spacing: rH*0.02;
Rectangle{
width: rW *0.54
height: rH *0.065
border.width: rW *0.001;
border.color: "#ffffff"
color : "#9ABCF3"
Text{
//anchors.horizontalCenter: parent.horizontalCenter;
//anchors.verticalCenter: parent.verticalCenter;
x: rW *0.01;
y: rH *0.01;
text: DonorName + " " + DonorID;
font.pixelSize: fontSize;
color: "yellow"
font.bold: true
}
}
RowLayout {
spacing: 0
Rectangle{
width: rW *0.27
height: rH *0.065
border.width: rW *0.001;
border.color: "#ffffff"
color : "#9ABCF3"
Text{
//anchors.horizontalCenter: parent.horizontalCenter;
//anchors.verticalCenter: parent.verticalCenter;
x: rW *0.01;
y: rH *0.01;
text: "PVB(ml)";
font.pixelSize: fontSize;
color: "yellow"
font.bold: true
}
}
Rectangle{
width: rW *0.27
height: rH *0.065
border.width: rW *0.001;
border.color: "#ffffff"
color : "#9ABCF3"
Text{
//anchors.horizontalCenter: parent.horizontalCenter;
//anchors.verticalCenter: parent.verticalCenter;
x: rW *0.01;
y: rH *0.01;
text: "SCV(ml)";
font.pixelSize: fontSize;
color: "yellow"
font.bold: true
}
}
}
}
}
//左側第四行
Rectangle{
width: rW *0.56;
height: rH *0.25;
color: "#9ABCF3"
radius: 5;
//左側四行 1列
Column{
x: rW *0.01;
y: rH *0.01;
//spacing: rH*0.02;
Rectangle{
width: rW *0.27
height: rH *0.0725
border.width: rW *0.001;
border.color: "#ffffff"
color : "#9ABCF3"
Text{
anchors.horizontalCenter: parent.horizontalCenter;
//anchors.verticalCenter: parent.verticalCenter;
x: rW *0.01;
y: rH *0.01;
text: "PUMP";
font.pixelSize: fontSize+6;
color: "yellow"
font.bold: true
}
}
RowLayout {
spacing: 0
Rectangle{
width: rW *0.135
height: rH *0.0725
border.width: rW *0.001;
border.color: "#ffffff"
color : "#9ABCF3"
Text{
//anchors.horizontalCenter: parent.horizontalCenter;
//anchors.verticalCenter: parent.verticalCenter;
x: rW *0.01;
y: rH *0.01;
text: "Draw";
font.pixelSize: fontSize;
color: "yellow"
font.bold: true
}
}
Rectangle{
width: rW *0.135
height: rH *0.0725
border.width: rW *0.001;
border.color: "#ffffff"
color : "#9ABCF3"
Text{
//anchors.horizontalCenter: parent.horizontalCenter;
//anchors.verticalCenter: parent.verticalCenter;
x: rW *0.01;
y: rH *0.01;
text: "Return";
font.pixelSize: fontSize;
color: "yellow"
font.bold: true
}
}
}
RowLayout {
spacing: 0
Rectangle{
width: rW *0.135
height: rH *0.0725
border.width: rW *0.001;
border.color: "#ffffff"
color : "#9ABCF3"
Text{
//anchors.horizontalCenter: parent.horizontalCenter;
//anchors.verticalCenter: parent.verticalCenter;
x: rW *0.01;
y: rH *0.01;
text: "Value";
font.pixelSize: fontSize;
color: "yellow"
font.bold: true
}
}
Rectangle{
width: rW *0.135
height: rH *0.0725
border.width: rW *0.001;
border.color: "#ffffff"
color : "#9ABCF3"
Text{
//anchors.horizontalCenter: parent.horizontalCenter;
//anchors.verticalCenter: parent.verticalCenter;
x: rW *0.01;
y: rH *0.01;
text: "Value";
font.pixelSize: fontSize;
color: "yellow"
font.bold: true
}
}
}
}
//左側四行 2列
Column{
x: rW *0.28;
y: rH *0.01;
RowLayout {
spacing: 0
Rectangle{
width: rW *0.135
height: rH *0.15
border.width: rW *0.001;
border.color: "#ffffff"
color : "#9ABCF3"
Text{
anchors.horizontalCenter: parent.horizontalCenter;
anchors.verticalCenter: parent.verticalCenter;
x: rW *0.01;
y: rH *0.01;
text: "Value";
font.pixelSize: fontSize;
color: "yellow"
font.bold: true
}
}
Rectangle{
width: rW *0.135
height: rH *0.15
border.width: rW *0.001;
border.color: "#ffffff"
color : "#9ABCF3"
Text{
anchors.horizontalCenter: parent.horizontalCenter;
anchors.verticalCenter: parent.verticalCenter;
text: "Value";
font.pixelSize: fontSize;
color: "yellow"
font.bold: true
}
}
}
RowLayout {
spacing: 0
Rectangle{
width: rW *0.135
height: rH *0.0725
border.width: rW *0.001;
border.color: "#ffffff"
color : "#9ABCF3"
Text{
anchors.horizontalCenter: parent.horizontalCenter;
anchors.verticalCenter: parent.verticalCenter;
text: "Value";
font.pixelSize: fontSize;
color: "yellow"
font.bold: true
}
}
Rectangle{
width: rW *0.135
height: rH *0.0725
border.width: rW *0.001;
border.color: "#ffffff"
color : "#9ABCF3"
Text{
anchors.horizontalCenter: parent.horizontalCenter;
anchors.verticalCenter: parent.verticalCenter;
text: "Value";
font.pixelSize: fontSize;
color: "yellow"
font.bold: true
}
}
}
}
}
}
//右側
Column{
spacing: rH *0.03;
x: rW * 0.65;
y: rH *0.05;
Rectangle{
width: rW * 0.30;
height: rH * 0.43;
color: "#EEEEEE"
radius: 5;
Text{
anchors.horizontalCenter: parent.horizontalCenter;
anchors.verticalCenter: parent.verticalCenter;
text: "PLASMA\nText";
font.pixelSize: fontSize;
color: "blue"
font.bold: true
}
}
Rectangle{
width: rW * 0.30;
height: rH * 0.43;
color: "#EEEEEE"
radius: 5;
Text{
anchors.horizontalCenter: parent.horizontalCenter;
anchors.verticalCenter: parent.verticalCenter;
text: "PLASMA\nText";
font.pixelSize: fontSize;
color: "blue"
font.bold: true
}
}
}
}
}
PathView {
id: pathView;
anchors.fill: parent
currentIndex: MyModel.GetCurrentIndex;
x: 500
y: 0
width: 1000;
height: 900;
model: MyModel
delegate: delegate
preferredHighlightBegin: 0.49;
preferredHighlightEnd: 0.51;
focus: true;
Keys.onLeftPressed: decrementCurrentIndex();
Keys.onRightPressed: incrementCurrentIndex();
path: Path{
startX: pathView.width/2;
startY: 30;
PathAttribute { name: "zOrder"; value: 0 }
PathAttribute { name: "itemAlpha"; value: 0.5 }
PathAttribute { name: "itemScale"; value: 0.3 }
PathArc {
relativeX: 0;
y: pathView.height - rH/1.5;
radiusX: pathView.width/4;
radiusY: pathView.width/4;
useLargeArc:true
}
PathAttribute { name: "zOrder"; value: 50 }
PathAttribute { name: "itemAlpha"; value: 1.0 }
PathAttribute { name: "itemScale"; value: 1.0 }
PathArc {
x: pathView.width/2;
y: 0
radiusX: pathView.width/4;
radiusY: pathView.width/4;
useLargeArc:true
}
PathAttribute { name: "zOrder"; value: 0 }
PathAttribute { name: "itemAlpha"; value: 0.5 }
PathAttribute { name: "itemScale"; value: 0.3 }
}
}
}