Qt-QMl-自定義自己想要的TabView

上效果圖




上實現源碼,這裏的代碼都是來自Qt官方源碼修改其中某一行內容

/*
  作者:張建偉
  時間:2018年4月8日
  簡述:自定義TabView,主要實現Tab和實現內容重疊,不在佔用獨立空間
       該文件內容僅適用於某平臺顯示器使用
  */
 
 
import QtQuick 2.2
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls.Private 1.0
 
 
 
 
FocusScope
{
    id:root
 
 
    implicitWidth: 240
    implicitHeight: 150
 
 
    property int currentIndex: 0    //當前標籤索引
    readonly property int count: __tabs.count       //當前標籤數量
    property bool frameVisible: true                //標籤邊框可見
    property bool tabsVisible: true                 //標籤是否可見
    property int tabPosition: Qt.TopEdge            //標籤位置
    readonly property alias contentItem: stack      //標籤內容視圖屬性          //這裏翻譯有問題
    default property alias data: stack.data         //內容
 
 
    property ListModel __tabs: ListModel { }
    property Component style: Settings.styleComponent(Settings.style, "DTabViewStyle.qml", root)
    property var __styleItem: loader.item
    onCurrentIndexChanged: __setOpacities()
    //添加標籤
    function addTab(title, component)
    {
        return insertTab(__tabs.count, title, component)
    }
    //插入標籤
    function insertTab(index, title, component)
    {
        var tab = tabcomp.createObject()
        tab.sourceComponent = component
        tab.title = title
        __tabs.insert(index, {tab: tab})
        tab.__inserted = true
        tab.parent = stack
        __didInsertIndex(index)
        __setOpacities()
        return tab
    }
    //移除標籤
    function removeTab(index)
    {
        var tab = __tabs.get(index).tab
        __willRemoveIndex(index)
        __tabs.remove(index, 1)
        tab.destroy()
        __setOpacities()
    }
    //移動標籤
    function moveTab(from, to)
    {
        __tabs.move(from, to, 1)
 
 
        if (currentIndex == from)
        {
            currentIndex = to
        }
        else
        {
            var start = Math.min(from, to)
            var end = Math.max(from, to)
            if (currentIndex >= start && currentIndex <= end)
            {
                if (from < to)
                    --currentIndex
                else
                    ++currentIndex
            }
        }
    }
    //獲取標籤
    function getTab(index)
    {
        var data = __tabs.get(index)
        return data && data.tab
    }
 
 
    function __willRemoveIndex(index)
    {
        if (count > 1 && (currentIndex > index || currentIndex == count -1))
            --currentIndex
    }
    function __didInsertIndex(index)
    {
        if (count > 1 && currentIndex >= index)
            currentIndex++
    }
 
 
    function __setOpacities() {
        for (var i = 0; i < __tabs.count; ++i)
        {
            var child = __tabs.get(i).tab
            child.visible = (i == currentIndex ? true : false)
        }
    }
 
 
    activeFocusOnTab: false
 
 
    Component
    {
        id: tabcomp
        Tab {}
    }
 
 
    TabBar
    {
        id: tabbarItem
        objectName: "tabbar"
        tabView: root
        style: loader.item
        anchors.top: parent.top
        anchors.left: root.left
        anchors.right: root.right
    }
    Loader
    {
        id: loader
        z: tabbarItem.z - 1
        sourceComponent: style
        property var __control: root
    }
    Loader
    {
        id: frameLoader
        z: tabbarItem.z - 1
 
 
        anchors.fill: parent
        //        anchors.topMargin: tabPosition === Qt.TopEdge && tabbarItem && tabsVisible  ? Math.max(0, tabbarItem.height - baseOverlap) : 0
        anchors.bottomMargin: tabPosition === Qt.BottomEdge && tabbarItem && tabsVisible ? Math.max(0, tabbarItem.height -baseOverlap) : 0
        sourceComponent: frameVisible && loader.item ? loader.item.frame : null
 
 
        property int baseOverlap: __styleItem ? __styleItem.frameOverlap : 0
 
 
        Item {
            id: stack
 
 
            anchors.fill: parent
            anchors.margins: (frameVisible ? frameWidth : 0)
            anchors.topMargin: anchors.margins + (style =="mac" ? 6 : 0)
            anchors.bottomMargin: anchors.margins
 
 
            property int frameWidth
            property string style
            property bool completed: false
 
 
            Component.onCompleted: {
                addTabs(stack.children)
                completed = true
            }
 
 
            onChildrenChanged: {
                if (completed)
                    stack.addTabs(stack.children)
            }
 
 
            function addTabs(tabs) {
                var tabAdded = false
                for (var i = 0 ; i < tabs.length ; ++i) {
                    var tab = tabs[i]
                    if (!tab.__inserted && tab.Accessible.role === Accessible.LayeredPane) {
                        tab.__inserted = true
                        // reparent tabs created dynamically by createObject(tabView)
                        tab.parent = stack
                        // a dynamically added tab should also get automatically removed when destructed
                        if (completed)
                            tab.Component.onDestruction.connect(stack.onDynamicTabDestroyed.bind(tab))
                        __tabs.append({tab: tab})
                        tabAdded = true
                    }
                }
                if (tabAdded)
                    __setOpacities()
            }
 
 
            function onDynamicTabDestroyed() {
                for (var i = 0; i < __tabs.count; ++i) {
                    if (__tabs.get(i).tab === this) {
                        __willRemoveIndex(i)
                        __tabs.remove(i, 1)
                        __setOpacities()
                        break
                    }
                }
            }
        }
        onLoaded: { item.z = -1 }
    }
 
 
    onChildrenChanged: stack.addTabs(root.children)
    states: [
        State {
            name: "Bottom"
            when: tabPosition === Qt.BottomEdge && tabbarItem != undefined
            PropertyChanges {
                target: tabbarItem
                anchors.topMargin: -frameLoader.baseOverlap
            }
            AnchorChanges {
                target: tabbarItem
                anchors.top: frameLoader.bottom
            }
        }
    ]
 
 
 
 
//    style: TabViewStyle
//    {
//        tab:Rectangle
//        {
//            id:t_root
//            //            implicitWidth: Math.max(text.width + 4, 80)
//            implicitWidth: 80
//            implicitHeight: 30
//            //            color: styleData.selected ? "steelblue" :"lightsteelblue"
 
 
//            property bool selectd: styleData.selected
 
 
 
 
//            Canvas
//            {
//                id: m_canvas
//                anchors.fill: parent
//                onPaint:
//                {
 
 
 
 
 
 
//                }
//            }
//        }
//    }
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
//BaseTabView
//{
//    style: TabViewStyle
//    {
 
 
 
 
 
 
 
 
 
 
//            }
//            Text {
//                id: text
//                anchors.centerIn: parent
//                text: styleData.title
//                font.family: "微軟雅黑"
//                font.pixelSize: 18
//                color: styleData.selected ? "black" : "green"
//            }
 
 
//        }
 
 
//    }
 
 
 
 
 
 
 
 
//}
 
 

這裏還有一個是美化的樣式表,還是現在還有個問題,這個樣式文件無法拷出來,必須還放到Qt的程序目錄纔可以

/*
  作者:張建偉
  時間:2018年4月8日
  簡述:自定義TabView Style文件
  */
 
 
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Controls.Private 1.0
 
 
Style {
    readonly property TabView control: __control
    property bool tabsMovable: false
    property int tabsAlignment: Qt.AlignLeft
    property int tabOverlap: 1
    property int frameOverlap: 2
    property Component frame: Rectangle {
        color: "#dcdcdc"
        border.color: "#aaa"
 
 
        Rectangle {
            anchors.fill: parent
            color: "transparent"
            border.color: "#66ffffff"
            anchors.margins: 1
        }
    }
    property Component tab: Item {
        scale: control.tabPosition === Qt.TopEdge ? 1 : -1
 
 
        property int totalOverlap: tabOverlap * (control.count - 1)
        property real maxTabWidth: control.count > 0 ? (styleData.availableWidth + totalOverlap) / control.count : 0
 
 
        //implicitWidth: Math.round(Math.min(maxTabWidth, textitem.implicitWidth + 20))
 
 
        implicitWidth: 80
        implicitHeight: Math.round(textitem.implicitHeight + 10)
 
 
        Item {
            id: m_Item
            anchors.fill: parent
            anchors.bottomMargin: styleData.selected ? 0 : 1
            Canvas
            {
                id: m_Canvas
                anchors.fill: parent
                property bool isSelectd: styleData.selected
                property int m_width: m_Item.width
                property int  m_height: m_Item.height
                onPaint:
                {
                    var  ctx = getContext("2d");
                    ctx.width = m_width
                    ctx.clearRect(0,0,2000,2000);
                    ctx.height = m_height
                    ctx.lineWidth = 2.0;
                    ctx.lineJoin = 'miter';
                    ctx.strokeStyle = "#00FF00";
                    ctx.fillStyle = "#00FF00";
                    ctx.moveTo(1,0);
                    ctx.lineTo(m_Item.width-1,0);
 
 
                    ctx.lineTo(70,m_Item.height-1);
                    ctx.lineTo(10,m_Item.height-1);
                    ctx.lineTo(1,0);
 
 
                    if(isSelectd)
                    {
                        ctx.fill();
                    }
                    else
                    {
                        ctx.stroke();
                    }
                }
            }
        }
        Text {
            id: textitem
            anchors.fill: parent
            anchors.leftMargin: 4
            anchors.rightMargin: 4
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: Text.AlignHCenter
            text: styleData.title
            elide: Text.ElideMiddle
            renderType: Settings.isMobile ? Text.QtRendering : Text.NativeRendering
            scale: control.tabPosition === Qt.TopEdge ? 1 : -1
            font.bold: true
            font.family: "微軟雅黑"
            font.pixelSize: 16
            color: styleData.selected ? "black" : "#00FF00"
            Rectangle {
                anchors.centerIn: parent
                width: textitem.paintedWidth + 6
                height: textitem.paintedHeight + 4
                visible: (styleData.activeFocus && styleData.selected)
                radius: 3
                color: "#224f9fef"
                border.color: "#47b"
            }
        }
    }
 
 
    property Component leftCorner: null
 
 
    property Component rightCorner: null
 
 
    property Component tabBar: null
}
 
 



希望對大家有所幫助