【QT】QML—— ListView添加固定表头的方法

在qt中构建界面时经常会对多个数据进行排列显示,可以使用qml提供的ListView组件来快速的构建一个列表模型来进行列表内容的分组显示;
通常的步骤是定义一个简单的ListView列表。创建一个Model并填入数据到其中;

Rectangle {
	id:rootRect;
	width:600;
	height:200;
	color:"grey";

	ListView {
		id:listView;
		width:parent.width;
		height:parent.height;
		clip:true; //对超出划定边界的数据进行裁剪
		delegate:modelItem; //自定义列表内容的组件,属性是Component
		//构建一个Model,也可以直接引入c++中的创建的model 运行程序可已看到生成了一个包含name,age,Heigth的列表
     model:ListModel {
         id: listModel;
         ListElement {
             name:"jack";
             age: "22";
             Height: "188cm"
         }
         ListElement {
             name:"mark";
             age:"19";
             Height:"178cm";
         }
         ListElement {
             name:"zhangsan";
             age:"17";
             Height:"177cm";
         }
         ListElement {
             name:"lisi";
             age:"27";
             Height:"167cm";
         }
         ListElement {
             name:"xiaoxiao";
             age:"25";
             Height:"18";
         }
     }
	}

   Component {
       id:modelItem;
       Rectangle {
           width:parent.width;
           height:40;
           color: "grey"
           Row {
               width:0.9*parent.width;
               anchors.left: parent.left;
               anchors.leftMargin: 0.1*parent.width;
               height:parent.height;
               Label {
                   text: name;
                   font.pixelSize: 20;
                   width: 0.3*parent.width;
                   anchors.verticalCenter: parent.verticalCenter;
                   verticalAlignment: Text.AlignHCenter;
               }
               Label {
                   text: age;
                   font.pixelSize: 20;
                   width: 0.3*parent.width
                   anchors.verticalCenter: parent.verticalCenter;
                   verticalAlignment: Text.AlignHCenter;
               }
               Label {
                   text: Height;
                   font.pixelSize: 20;
                   width: 0.3*parent.width
                   anchors.verticalCenter: parent.verticalCenter;
                   verticalAlignment: Text.AlignHCenter;
               }
           }
       }
   }
}

以上的内容在qt运行显示的是一个基础的列表,但是一眼望去并不明确每一项的具体含义, 这样在一些使用过程中很不方便:具体的显示效果如下:
在这里插入图片描述
可以通过鼠标移动或者滚轮滑动查看列表的显示,但是对每一项的含义不是那么的直观,也有一种方法就是直接在model也就是列表的index为1的时候添加每一列的名称进去,显示的时候可以看到每一列的名称,具体代码如下,只需在model的第一列添加如下代码到最前面:(修改后的model如下)

model:ListModel {
    id: listModel;
    ListElement {
        name:"name";
        age:"age";
        Height:"height";
    }

    ListElement {
        name:"jack";
        age: "22";
        Height: "188cm"
    }
    ListElement {
        name:"mark";
        age:"19";
        Height:"178cm";
    }
    ListElement {
        name:"zhangsan";
        age:"17";
        Height:"177cm";
    }
    ListElement {
        name:"lisi";
        age:"27";
        Height:"167cm";
    }
    ListElement {
        name:"xiaoxiao";
        age:"25";
        Height:"181cm";
    }
    ListElement {
        name:"huahua";
        age:"38";
        Height:"188cm"
    }
}

效果展示:
在这里插入图片描述
可以看到第一行有显示每一列数据的名字了,但是因为设置的字体显示与后面一致(可以单独对某一个index的item设置不同的参数来突出显示,这里不做过多说明),而且会随着滑动,而且数据多了会滑动消失,所以不推荐使用;
在qml中,可以ListView的特性创建一个列表头,显示每一项的具体含义;表头header的属性和delegate一样也是Component;通过自定义表头的组件显示到列表最上面;

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.4

Window {
    id: window
    width: 640
    height: 200
    visible: true
    title: qsTr("Hello World")
    //qml ListView组件
    /*
      定义一个简单的ListView列表,并创建一个Model填入数据,运行程序可已看到生成了一个包含name,age,Heigth但是一眼望去并不明确每一项的具体含义;
      利用ListView的特性创建一个列表头,显示每一项的具体含义;表头header的属性和delegate一样也是Component;
     */

    Rectangle {
        id:rootRect
        width:parent.width;
        height:parent.height;
        color: "darkgrey";

        ListView {
            id:listView;
            width:parent.width;
            height:parent.height;
            clip: true; //超出边界的数据进行裁剪
            delegate:modelItem;
            header:headerView;//只构建表头上滑动时表头也会跟随上滑动消失
            headerPositioning: ListView.OverlayHeader;//枚举类型
            /*
                ListView.OverlayHeader: 向上滑动直接覆盖表头
                ListView.InlineHeader:表头和内容是放置在一起的,移动也是一起移动,默认设置此属性;
                ListView.PullBackHeader:表头和内容是可以分开,向上滑动会顶上去看不见
            */

            //构建一个Model
            model:ListModel {
                id: listModel;
                ListElement {
                    name:"jack";
                    age: "22";
                    Height: "188cm"
                }
                ListElement {
                    name:"mark";
                    age:"19";
                    Height:"178cm";
                }
                ListElement {
                    name:"zhangsan";
                    age:"17";
                    Height:"177cm";
                }
                ListElement {
                    name:"lisi";
                    age:"27";
                    Height:"167cm";
                }
                ListElement {
                    name:"xiaoxiao";
                    age:"25";
                    Height:"18";
                }
            }
        }

        Component {
            id:headerView;
            Rectangle {
                width:parent.width;
                height: 40;
                color: "lightgrey";
                z:2;//将表头的z坐标设置在上层,表头在设置属性为overlayHeader时就不会随滑动而消失,始终显示在最上面

                Row {
                    width: 0.9*parent.width;
                    height: parent.height;
                    anchors.left: parent.left;
                    anchors.leftMargin: 0.1*parent.width;

                    Label {
                        text: "name";
                        font.pixelSize: 20;
                        width: 0.3*parent.width;
                        anchors.verticalCenter: parent.verticalCenter;
                        verticalAlignment: Text.AlignHCenter;
                    }
                    Label {
                        text: "age";
                        font.pixelSize: 20;
                        width: 0.3*parent.width
                        anchors.verticalCenter: parent.verticalCenter;
                        verticalAlignment: Text.AlignHCenter;
                    }
                    Label {
                        text: "Height";
                        font.pixelSize: 20;
                        width: 0.3*parent.width
                        anchors.verticalCenter: parent.verticalCenter;
                        verticalAlignment: Text.AlignHCenter;
                    }

                }
            }
        }

        Component {
            id:modelItem;
            Rectangle {
                width:parent.width;
                height:40;
                color: "grey"
                Row {
                    width:0.9*parent.width;
                    anchors.left: parent.left;
                    anchors.leftMargin: 0.1*parent.width;
                    height:parent.height;
                    Label {
                        text: name;
                        font.pixelSize: 20;
                        width: 0.3*parent.width;
                        anchors.verticalCenter: parent.verticalCenter;
                        verticalAlignment: Text.AlignHCenter;
                    }
                    Label {
                        text: age;
                        font.pixelSize: 20;
                        width: 0.3*parent.width
                        anchors.verticalCenter: parent.verticalCenter;
                        verticalAlignment: Text.AlignHCenter;
                    }
                    Label {
                        text: Height;
                        font.pixelSize: 20;
                        width: 0.3*parent.width
                        anchors.verticalCenter: parent.verticalCenter;
                        verticalAlignment: Text.AlignHCenter;
                    }
                }
            }
        }
    }
}

如果表头还是会随着滑动消失,可以设置组件的z轴,让该组件显示在最上层,达到表头一直显示的效果;特别要注意的是需要设置ListView的headerPositioning的属性为ListView.OverlayHeader这个类型(三个类型的描述在代码里有注释),这个是向上滑动覆盖表头,但是因为表头的z轴设置的是最上层,所以并不会被覆盖,以此达到表头显示的效果。
以上的header添加后就可以在显示一个带表头的列表,并且列表滑动表头不会随着列表滑动,始终显示在最上方。实现效果显示如下:
在这里插入图片描述

可以看到表头一直显示到最上方,且不会随滑动消失。
还有一个问题就是一个点击穿透的问题,上滑后点击表头会触发列表内容的点击,如果有监控对列表的点击操作时点击表头就会造成误操作,这里就需要做一个放穿透效果,即在表头的组件中加上以下代码:

MouseArea {
    anchors.fill: parent;
    onPressed: {
        mouse.accepted = true;
    }
}

如上所述。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你想在 Qt QML 中使用 C++ 类,可以通过 CMake 添加一个 C++ 类,并将其与 QML 集成。 以下是添加 C++ 类的步骤: 1. 在项目中创建一个新的 C++ 类,例如 `MyClass`,并将其添加到 `src` 目录下。 2. 在 CMakeLists.txt 文件中添加以下代码: ``` # 添加 C++ 类 add_library(MyClass SHARED src/myclass.cpp src/myclass.h ) # 链接 Qt 模块 target_link_libraries(MyClass PRIVATE Qt6::Core Qt6::Qml) # 安装库文件 install(TARGETS MyClass LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) # 安装头文件 install(FILES src/myclass.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/myproject ) ``` 这个命令会将 `MyClass` 添加到项目中,并将其链接到 Qt6 的核心库和 QML 库中。 3. 在 `main.qml` 文件中添加以下代码: ``` import myproject 1.0 // 创建 C++ 类实例 MyClass { id: myclass } // 使用 C++ 类的属性和方法 Text { text: myclass.text } ``` 这个命令会将 `MyClass` 导入到 QML 中,并创建一个 C++ 类实例。你可以像使用其他 QML 类一样使用这个实例的属性和方法。 注意,为了使 C++ 类能够在 QML 中使用,你需要在类的头文件中使用 `Q_OBJECT` 宏,并在 C++ 类中添加 QML 属性和方法。例如: ``` #ifndef MYCLASS_H #define MYCLASS_H #include <QObject> class MyClass : public QObject { Q_OBJECT Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) public: explicit MyClass(QObject *parent = nullptr); QString text() const; void setText(const QString &text); signals: void textChanged(); private: QString m_text; }; #endif // MYCLASS_H ``` 这个类中添加了一个 `text` 属性和相应的读写方法,并使用 `Q_PROPERTY` 宏将其导出到 QML 中。在实现文件中,需要为这个类的方法添加相应的实现代码。 以上就是在 Qt QML添加 C++ 类的步骤,希望对你有帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值