主要通过qml实现listvie功能,主要包括右键菜单,滚动条,拖动改变内容等,c++ 与 qml之间的变量和函数的调用。
main.cpp
#include <QQuickItem>
#include <QQmlContext>
#include "testlistmodel.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
qmlRegisterType<TestListModel>("TestListModel", 1, 0, "TestListModel");
engine.load(QUrl(QStringLiteral("qrc:/ui1.qml")));
QObject* root = engine.rootObjects().first();
QString retVal;
QVariant message = "Hello from c++";
QVariant returnedValue;
QQmlProperty(root,"testmsg").write("hello,world");
qDebug()<<"Cpp get qml property height222"<<root->property("msg");
bool ret =QMetaObject::invokeMethod(root,"setSignalB",
Q_RETURN_ARG(QVariant,returnedValue),
Q_ARG(QVariant,message),
Q_ARG(QVariant,8));
qDebug()<<"returnedValue"<<returnedValue<<root<<ret;
return app.exec();
}
listview 的model 代码
TestListModel.h
#ifndef TESTLISTMODEL_H
#define TESTLISTMODEL_H
#include <QAbstractListModel>
typedef struct Student
{
int id;
QString name;
QString sex;
}pStudent;
class TestListModel : public QAbstractListModel
{
Q_OBJECT
public:
explicit TestListModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
virtual QHash<int, QByteArray> roleNames() const;
Qt::ItemFlags flags(const QModelIndex &index) const override;
Q_INVOKABLE void modifyItemText(int row1,int row2);
Q_INVOKABLE void add();
enum MyType{
ID=Qt::UserRole+1,
Name,
Sex
};
private:
QVector<Student> m_studentList;
signals:
void layoutChanged();
};
#endif // TESTLISTMODEL_H
TestListModel.cpp
#include "testlistmodel.h"
#include <QDebug>
TestListModel::TestListModel(QObject *parent)
: QAbstractListModel{parent}
{
for(int i=0;i<20;i++)
{
Student oneData;
oneData.id = i;
oneData.name = QString("张三%1").arg(i);
if(i%2==0)
{
oneData.sex = "female" ;
}
else
{
oneData.sex = "male" ;
}
//qDebug()<<"TestListModel"<<m_studentList.size();
m_studentList.append(oneData);
}
}
int TestListModel::rowCount(const QModelIndex &parent) const
{
//qDebug()<<"rowCount"<<m_studentList.size();
return m_studentList.size();
}
QVariant TestListModel::data(const QModelIndex &index, int role) const
{
// qDebug()<<"TestListModel::data11111111111"<<index.isValid();
QVariant var;
if ( !index.isValid() )
{
return QVariant();
}
int nRow = index.row();
int nColumn = index.column();
if(Qt::UserRole+1 == role)
{
var = QVariant::fromValue(m_studentList.at(nRow).id);
}
else if(Qt::UserRole+2 == role)
{
var = QVariant::fromValue(m_studentList.at(nRow).name);
// qDebug()<<"m_listData.at(nRow).name"<<m_listData.at(nRow).name;
}
else if(Qt::UserRole+3 == role)
{
var = QVariant::fromValue(m_studentList.at(nRow).sex);
// qDebug()<<"m_listData.at(nRow).name"<<m_listData.at(nRow).name;
}
return var;
}
QHash<int, QByteArray> TestListModel::roleNames() const
{
QHash<int, QByteArray> d;
d[MyType::ID]="id";
d[MyType::Name]="name";
d[MyType::Sex]="sex";
qDebug()<<"d .size"<<d.size();
return d;
}
Qt::ItemFlags TestListModel::flags(const QModelIndex &index) const
{
Q_UNUSED(index)
// if(index.column() ==1)
// {
// qDebug()<<"UserInfoModel::flags 1111";
// return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
// }
qDebug()<<"TestListModel::flags";
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
}
void TestListModel::modifyItemText(int row1, int row2)
{
m_studentList.swapItemsAt(row1,row2);
beginResetModel();
endResetModel();
}
void TestListModel::add()
{
Student student;
student.id = 123;
student.name = "love";
student.sex = "man";
m_studentList.push_back(student);
beginResetModel();
endResetModel();
emit layoutChanged();
}
ui.qml
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Layouts 1.2
import TestListModel 1.0
import QtQuick 2.12
import QtQuick 2.2
import QtQml.Models 2.2
//import QtQuick.Controls 2.12
//QtQuick.Controls 2.12 和QtQuick.Controls.Styles 1.4不匹配
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls 1.4
import QtQuick.Controls 2.12
import QtLocation 5.15
//import "CustomMenuItem.qml"
// import QtQuick.Controls 2.15
//import QtQuick.Controls 2.5
Window {
id:window
//anchors.centerIn: parent
width: 650;
height: 457
visible: true
flags: Qt.FramelessWindowHint | Qt.Dialog
property string testmsg: "GongJianBo1992"
Rectangle{
id:rect1;
anchors.fill: parent;
border.width: 1;
color: "transparent";
border.color: "red";
clip:true//这一属性设置表示如果他的子类超出了范围,那么就剪切掉,不让他显示和起作用
}
//无边框移动
MouseArea {
id: dragRegion
anchors.fill: parent
property point clickPos: "0,0"
onPressed: {
clickPos = Qt.point(mouse.x,mouse.y)
}
onReleased: {
clickPos = Qt.point(0,0)
}
onPositionChanged: {
//鼠标偏移量
var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
//如果mainwindow继承自QWidget,用setPos
window.setX(window.x+delta.x)
window.setY(window.y+delta.y)
}
}
Menu {
id: contextMenu
background: Rectangle {// @disable-check M16
anchors.fill:parent
implicitWidth: 200
implicitHeight: 30
color: "lightblue"
}
Action{
id:no1
text:"123"
onTriggered:
{
console.log("选项一被点击")
tableView.selectAllItem()
}
// @disable-check M16
}
Menu{
background: Rectangle {// @disable-check M16
anchors.fill:parent
implicitWidth: 200
implicitHeight: 30
color: "lightblue"
}
title:"love"
Action{
id:no4
text:"789"
onTriggered:
{
console.log("选项六被点击")
tableView.selectAllItem()
}
}
}
Action {
id:no2
text:"234"
onTriggered:
{
console.log("选项二被点击")
tableView.disselectAllItem()
}
}
MenuSeparator {
contentItem: Rectangle {// @disable-check M16
implicitWidth: 200
implicitHeight: 1
color: "#21be2b"
}
}
Action {
id:no3
text:"345"
onTriggered: console.log("选项三被点击")
}
delegate: MenuItem {// @disable-check M16
id: menuItem
height: 40// @disable-check M16
contentItem: Text{// @disable-check M16
text:menuItem.text
color: menuItem.highlighted? "gary": "blue"
}
background: Rectangle{// @disable-check M16
implicitWidth: 200
implicitHeight: 30
color: menuItem.highlighted? "purple":"lightblue"
}
arrow: Image {// @disable-check M16
id: arrowImage
x: parent.width - width
y: parent.height/2 -height/2
visible: menuItem.subMenu
source: "qrc:/Right arrow.png"
}
}
}
TestListModel{
id: myMode
onLayoutChanged:{
console.log("LayoutChanged")
}
}
// Page{
// x:listwidget.x
// y:listwidget.y
// width: listwidget.width
// height: listwidget.height
// background: Rectangle{
// anchors.fill: parent
// color: "white"
// border.width: 1
// border.color: "black"
// }
// }
Rectangle{
width: window.width-60+2
height: 300+2
border.color: "lightgreen"
border.width: 1
color: "transparent"
x:30
y:40
ListView {
id: listwidget
width: parent.width-2//window.width-60
height: parent.height-2// 300
x:1
y:1
interactive: false // @disable-check M16
model: myMode
clip: true //不写的话,滚动的时候,listview会有拖拽的感觉
//orientation: ListView.Vertical //垂直列表
ScrollBar.vertical: ScrollBar {
id: scrollBar
hoverEnabled: true
active: hovered || pressed
policy: ScrollBar.AlwaysOn
orientation: Qt.Vertical
size: 0.8
anchors.top: parent.top
anchors.right: parent.right
anchors.bottom: parent.bottom
contentItem: Rectangle {
implicitWidth: 6 //没指定的时候的宽度
implicitHeight: 100 //没有指定高度的时候
radius: width / 2
color: scrollBar.pressed ? "#81e889" : "#c2f4c6"
}
}
Rectangle{
id : dargRect
width: 100
height: 30
visible: false
color: "lightgray";
Text {
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
id: dargRectText
// text: "123"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
delegate: Item{
id:itemDrag1
width: window.width-60
height: 30
property int dragItemIndex: 0
property bool isHover: false
Rectangle {
width: window.width-60
height: 30
//radius: 5;
// border.width: 1
// border.color: "white"
color:isHover === true? "lightgreen":listwidget.currentIndex === index ? "lightblue" : "gray"
Text {
id:itemDrag2
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
// text: "123"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: id+":"+name+":"+sex
}
MouseArea {
id: mouseArea
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
hoverEnabled: true
onWheel: {// @disable-check M16
// 当滚轮被滚动时调用
// 事件参数wheel提供了滚动的方向和距离
if (wheel.angleDelta.y > 0) {
//console.log("向上滚动")
scrollBar.decrease();
}
else {
//console.log("向下滚动")
scrollBar.increase();
}
}
onEntered:
{
isHover = true
//console.log("onEntered" +isHover)
}
onExited:
{
isHover = false
//console.log("onExited" +isHover)
}
onClicked:
{
if (mouse.button === Qt.RightButton)//菜单
{
console.log("menu RightButton")
contextMenu.popup()
}
else
{
//var other_index = listwidget.indexAt(mouseArea.mouseX , mouseArea.mouseY );
listwidget.currentIndex = index // 点击时设置当前索引为该项的索引值
dragItemIndex = index;
console.log("onClicked"+index)
}
}
onPressAndHold: {
if(mouse.button === Qt.LeftButton)
{
console.log("onPressAndHold"+index)
listwidget.currentIndex = index
dargRect.x = mouseX +itemDrag1.x
dargRect.y = mouseY+itemDrag1.y
dragItemIndex = index;
dargRectText.text = itemDrag2.text
dargRect.visible = true
}
}
onReleased:{
if(dargRect.visible === true)
{
dargRect.visible = false
var other_index = listwidget.indexAt(mouseX +itemDrag1.x , mouseY+itemDrag1.y );
console.log("onReleased"+other_index)
if(dragItemIndex!==other_index)
{
var afterItem = listwidget.itemAtIndex(other_index );
// listwidget.myModel.get(other_index).text
myModel.modifyItemText(dragItemIndex,other_index)
//console.log("onReleased"+myModel)
}
}
}
onPositionChanged:{
//console.log("onPositionChanged111" + mouse.button)
if(mouse.button === Qt.LeftButton)
{
//console.log("onPositionChanged222")
var other_index = listwidget.indexAt(mouseX +itemDrag1.x , mouseY+itemDrag1.y );
listwidget.currentIndex = other_index;
dargRect.x = mouseX +itemDrag1.x
dargRect.y = mouseY+itemDrag1.y
}
}
}
}
}
}
}
Button {
id: button1
x: parent.width-80
y: parent.height-36
width:70
height:30
//text: qsTr("Button")
background:Rectangle // @disable-check M16
{
//anchors.fill: parent
border.color: "royalblue"
border.width: 1
color: button1.down ? "red" :(button1.hovered?"blue":"lightsteelblue")
}
Text {
text: "1213";
// anchors.fill: parent
anchors.centerIn: parent;
color: button1.hovered?"yellow":"red";
font.pixelSize: 13;
//font.weight: Font.DemiBold
}
Connections {
target: button1
function onClicked()
{
window.close();
}
}
}
function myQmlFunction( msg,index) {
console.log("Got message:", msg)
return "some return value"
}
function setSignalB(name, value){
console.log("setPoint"+" "+testmsg);
console.log("qml function processB",name,value);
myMode.add();
return value
}
}
运行结果