QML <4> Tableview 自定义表格显示 delegate FontAwesome Canvas

QML <4> Tableview 自定义表格显示 delegate FontAwesome Canvas

前言

基于QML TableView 的自定义表格显示,表格实现内容参考网易云音乐如下图所示:
QML <4> Tableview 自定义表格显示 delegate FontAwesome Canvas_第1张图片
参考实现功能自定义表格实现如下:
QML <4> Tableview 自定义表格显示 delegate FontAwesome Canvas_第2张图片

一、表格列设置

表格列为固定列数,代码如下;

TableViewColumn{role: "num_flag"; title: ""; width: 80; elideMode: Text.ElideRight;}
TableViewColumn{role: "name"; title: qsTr("标题"); width: 320; elideMode: Text.ElideRight;}
TableViewColumn{role: "time"; title: qsTr("时长"); width: 90;}
TableViewColumn{role: "singer"; title: qsTr("歌手"); width: 120;}

二、headerDelegate

表头使用delegate自定义绘制,代码如下:

Component {
        id: header_delegate

        Rectangle {
            height: 40
            color:  "white"
            border.width: 1
            border.color: "gray"
            Text {
                id: headertext
                anchors.centerIn: parent
                text:  styleData.value
                color: "gray"
            }
        }
    }

三、itemDelegate

itemDelegate为单元格绘制代理,根据列role 和Loader 返回不同delegate ,处理表格列之间的区分显示,为了Component 中可以访问styleData,故列delegate定义在Loader内部
tips:== 和===的区别

 Component
    {
        id:item_delegate
        Loader
        {
            id:item_loader
            anchors.fill: parent
//            visible:  true
            //== 、=== 区别
            //https://blog.csdn.net/weixin_42420703/article/details/82531125
            sourceComponent:
            {
                var role = styleData.role;
                if (role === "num_flag")
                    return num_falg_component;
                if (role === "name")
                    return name_component;
                else if (role === "time")
                    return time_component;
                else if (role === "singer")
                    return singercomponent;
                else return empty_component;

            }

1.排行delegate

第一列主要显示:行号,标记、上升、下降排名,如下图所示:
QML <4> Tableview 自定义表格显示 delegate FontAwesome Canvas_第3张图片
在这几个功能点实现上,使用Canvas 绘制,上下 趋势箭头使用Unicode字符,字符获取网址:
https://unicode-table.com/cn/blocks/

代码如下:

 Component
                {
                    id:num_falg_component
                    Rectangle
                    {
                        id:draw_rect
                        height: row_height
                        property  var row:"1";
                        property var new_flag : false;
                         //false :down true :up
                        property var trend : true;
                        property var trend_num:11;
                        Canvas
                        {
                            id:draw
                            anchors.fill: parent

                            onPaint: {
                                var ctx = getContext("2d");
                                row = styleData.row+1;

                                if(row === 2 )
                                {
                                    new_flag = true;
                                }
                                else if( row == 3 )
                                {
                                    trend = false;
                                    trend_num =6;
                                }

                                //行号
                                ctx.fillStyle = "gray";
                                ctx.lineWidth = 1;
                                ctx.font="12px Georgia";
                                ctx.fillText(row, 15,15,width/2);
                                //新
                                if(new_flag)
                                {
                                    ctx.fillStyle = "green";
                                    ctx.lineWidth = 3;
                                    ctx.fillText("new", width/2,15,width/2);
                                }
                                else
                                {
                                    var trend_text = String.fromCodePoint(0x2193);
                                    var trend_color="blue";
                                    if(trend)
                                    {
                                        trend_color = "red";
                                        trend_text = String.fromCodePoint(0xA71B);
                                    }
                                    ctx.fillStyle = trend_color;
                                    ctx.fillText(trend_text, width/2,15,width/3);
                                    ctx.fillStyle = "red";
                                    ctx.fillText(trend_num, width/2+10,15,width/3*2);
                                }
                            }
                        }
                    }
                }

2.标题delegate

标题栏主要实现功能是只有前三行显示专辑图片,如图所示:
在这里插入图片描述
Component 代码如下:

Component
            {
                id:name_component
                TableNameColumn
                {
                    music_name_text: "As Long As You Love You"
                    image_show: styleData.row < 3 ? true:false
                    iamge_source: "qrc:/img/img/109951166294262909.jpg"
                    height: row_height
                    width:parent.width
                }

             }

自定义组件TableNameColumn 代码如下:

import QtQuick 2.0
import QtQuick.Layouts 1.0
import QtQuick.Controls 2.12
import "qrc:/scripts/Custom/ToolScripts.js" as JsTool
Rectangle
{
    id:root

    property string music_name_text: "";
    property bool image_show: false;
    property alias iamge_source:image.source
    width: 300
    height: 50
    anchors.fill: parent
    Image {
        id: image
        width: 45
        height: 45
        anchors.verticalCenter: parent.verticalCenter
        anchors.leftMargin: 0
        anchors.topMargin: 3
        anchors.left: parent.left
        anchors.top: parent.top
        visible: image_show
    }

    Rectangle
    {
        id:music_name
        width: 241
        height: 45
        anchors.left: image_show ?image.right :parent.left
        anchors.top:  parent.top
        Button {
            id: paly_canvas
            background: Rectangle {
                color: "white"
                opacity: 0.2 //透明度
                }
            width: 18
            height: 18
            anchors.verticalCenter:  parent.verticalCenter
            anchors.left: parent.left
            font.family: "FontAwesome"
            text: "\uf01d"
        }
        Canvas
        {
            id:name_draw
            x: 26
            y: 0
            width: 222
            height: 45
            anchors.verticalCenter: parent.verticalCenter
            anchors.left: paly_canvas.right
            onPaint:
            {
                var ctx = getContext("2d");
                ctx.fillStyle = "rgba(54, 54, 54, 1)";
                ctx.lineWidth = 2;
                ctx.font="11px Georgia";
                ctx.fillText(music_name_text,1, height/2,height);
            }
        }
    }
}

3.时长delegate

除显示时长外,在鼠标所在当前行显示 添加 、 收藏、 分享、下载按钮如图所示:
QML <4> Tableview 自定义表格显示 delegate FontAwesome Canvas_第4张图片
使用StackView 实现,MouseArea 监听鼠标行为,图标使用FontAwesome,delegate 代码如下:

 				Component
                {
                    id:time_component
                    TableTimeColumn
                    {
                        id:time_column
                        height: row_height
                        MouseArea
                        {
                            anchors.fill: parent
                            hoverEnabled :true
                            onEntered:
                            {
                                time_column.changeStackView(1)
                            }
                            onExited:
                            {
                                time_column.changeStackView(0)
                            }
                        }
                    }
                }

自定义组件TableTimeColumn 代码如下:

import QtQuick 2.0
import QtQuick.Controls 2.14
import "qrc:/scripts/Custom/ToolScripts.js" as JsTool
Item
{

    property int timesec: 60
    StackView {
        id: stack
        initialItem: time_view
        anchors.fill: parent
    }

    Component {
        id: time_view
        Canvas
        {
            id:time_text
            anchors.centerIn: parent
            onPaint: {
                var ctx = getContext("2d");
                JsTool.drawBackground(ctx,"white",width,height);
                ctx.fillStyle = "rgba(54, 54, 54, 1)";
                ctx.lineWidth = 2;
                ctx.font="14px Georgia";
                var str=JsTool.calTimeFromSecond(timesec);
                JsTool.draw_text_show(ctx,width-15,height/2,1,str);
            }
        }
    }
    Component {
        id: opt_view

       Rectangle
       {
           anchors.centerIn: parent
           Row
           {
               anchors.centerIn: parent
               spacing:2

               Button
               {
                   id:plus
                   text: "\uf055"
                   font.family: "FontAwesome"
                   width:18
                   height: 18
                   background: Rectangle {
                       color: "white"
                       opacity: 0.2 //透明度
                       }
               }
               Button
               {
                   id:btn_file
                   font.family: "FontAwesome"
                   text: "\uf0c7"
                   width:18
                   height: 18
                   background: Rectangle {
                       color: "white"
                       opacity: 0.2 //透明度
                       }
               }
               Button
               {
                   font.family: "FontAwesome"
                   text: "\uf045"
                   width:18
                   height: 18
                   background: Rectangle {
                       color: "white"
                       opacity: 0.2 //透明度
                       }
               }
               Button
               {
                   font.family: "FontAwesome"
                   text: "\uf019"
                   width:18
                   height: 18
                   background: Rectangle {
                       color: "white"
                       opacity: 0.2 //透明度
                       }
               }

           }
       }
    }
    function changeStackView(index)
    {
       stack.pop()
        if(index === 0 )
        {
            stack.push(time_view)
        }
        else
        {
            stack.push(opt_view)
        }
    }
}

4.歌手delegate

歌手列文字使用Canvas 绘制,文字长度超过宽度显示"…",如下图所示:
在这里插入图片描述
delegate 代码如下:

			Component
                {
                    id:singercomponent
                    TableSinglerColumn
                    {
                        height: row_height
                        id: text_singer
                    }
                }

自定义组件TableSinglerColumn 代码如下:

import QtQuick 2.0
import "qrc:/scripts/Custom/ToolScripts.js" as JsTool
Rectangle
{
    property string text: "未知sdfsdfkjdsfjdslkflkdsflkdsfjkdsfjdsk"
    anchors.fill: parent
    Canvas
    {
        anchors.fill: parent
        onPaint: {
            var ctx = getContext("2d");
            ctx.fillStyle = "rgba(54, 54, 54, 1)";
            ctx.lineWidth = 2;
            ctx.font="14px Georgia";
            var str= text
            JsTool.draw_text_show(ctx,width-15,height/2,1,str);
        }
    }
}

四、行rowDelegate

排行前3显示专辑图片,故行高有变化,如下图所示:
QML <4> Tableview 自定义表格显示 delegate FontAwesome Canvas_第5张图片
TableView 的行高由rowDelegate 返回,代码如下:

     property var image_row_height:40
     property var row_height:30
	 rowDelegate: Rectangle
        {
            height: styleData.row < 3 ?image_row_height:row_height;
            //border.color:"gray";
            //color: styleData.alternate?"lightgray":"white"
        }

总结

1 QML 使用FontAwesome

  • 资源获取
    FontAwesome 资源获取:http://www.fontawesome.com.cn/faicons/
    下载后将ttf 文件添加到qrc文件中,
    QML <4> Tableview 自定义表格显示 delegate FontAwesome Canvas_第6张图片

  • 工程配置
    main.cpp 中配置如下:
    QML <4> Tableview 自定义表格显示 delegate FontAwesome Canvas_第7张图片

  • 使用示例
    text为 对应的十六进制数值,在css文件中可根据对应图标名称找到对应数值
    QML <4> Tableview 自定义表格显示 delegate FontAwesome Canvas_第8张图片
    Button使用图标代码如下:

  Button
               {
                   id:plus
                   text: "\uf055"
                   font.family: "FontAwesome"
                   width:18
                   height: 18
                   background: Rectangle {
                       color: "white"
                       opacity: 0.2 //透明度
                       }
               }

2 function 函数封装

QML 中使用的function函数可单独写到*.js 文件中,在添加到qrc文件中,使用function时 在QML 文件中 import ,代码如下:

import "qrc:/scripts/Custom/ToolScripts.js" as JsTool
JsTool.draw_text_show(ctx,width-15,height/2,1,str);
  • 工程中使用的function 函数如下:
//ctx 画布
// linewidth 行宽
// lineheight  行高
// maxline 最大行数
// str 显示字符串
function draw_text_show(ctx,linewidth,lineheight,maxline,str)
{
    var strwidth = ctx.measureText(str).width;
    if(strwidth < linewidth)
    {
        ctx.fillText(str, 5, lineheight);
    }
    else
    {
        var curwidth = 0;
        var curline= 1;
        var maskstr = '...';
        var maskwidth = ctx.measureText(maskstr).width;
        var curstr="";
        var len = str.length;
        for( var i = 0; i < str.length; ++i )
        {
            var fontWidth = ctx.measureText(str[i]).width;
            var nextwidth = curwidth+fontWidth;

            var draw_all = false;

            //########
            //####...
            if(curline === maxline)
            {
                nextwidth += maskwidth;
                if(nextwidth <= linewidth)
                {
                    curwidth += fontWidth;
                    curstr  +=  str[i];
                    if(i+1 < str.length)
                    {
                        continue;
                    }
                }
                else
                {
                    curstr += maskstr;
                    draw_all = true;
                }

            }
            else
            {
                if( nextwidth <= linewidth )
                {
                    curwidth += fontWidth;
                    curstr  +=  str[i]
                    continue;
                }

            }

            ctx.fillText(curstr, 5, lineheight*curline);
            curline++;
            curwidth = 0;
            curstr="";
            if(draw_all)
            {
                break;
            }
        }
    }
}

//根据秒数,计算时分
function calTimeFromSecond( timesecs)
{
    var  date= new  Date(0,0,0,0,0,timesecs,0);   //转换为Date对象
   return Qt.formatDateTime(date, "mm:ss");
}
//播放按钮
function draw(ctx)
{
    // 圆圈绘制
    ctx.strokeStyle = "gray"
    ctx.lineWidth = 1
    ctx.beginPath()
    ctx.arc(width/2,height/2,width/2,0,Math.PI*2)
    ctx.stroke()
    //三角形绘制
    ctx.fillStyle = "gray"
    ctx.strokeStyle = "gray"
    ctx.beginPath()
    ctx.moveTo(width/4, height/4)
    ctx.lineTo(width/4, height/4*3)
    ctx.lineTo(width/4*3+2, height/2)
    ctx.closePath()
    ctx.fill()
    ctx.stroke()
}
//绘制背景
function drawBackground(ctx,color,width,height )
{
    ctx.clearRect(0, 0, width, height)
    ctx.strokeStyle = color;
    ctx.fillStyle = color;
    ctx.fillRect(0, 0,width, height)
    ctx.stroke()
}

你可能感兴趣的:(QML,qt,开发语言,css)