使用 PathSvg 自定义 Window

Customizing Window with PathSvg

这是我 main.qml 中现在的内容:

import QtQuick 2.9
import QtQuick.Window 2.3
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.5
import QtQuick.Shapes 1.12
import QtGraphicalEffects 1.0

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Test Window")

    property double iconSize: 24

    RowLayout{
        anchors.fill: parent
        Rectangle{
            id: rect
            Layout.fillHeight: true
            Layout.preferredWidth: iconSize
            ListView{
                id: lv
                model: ViewModel.views
                anchors.fill: parent
                delegate: ItemDelegate{
                    width: iconSize
                    height: iconSize
                    ColumnLayout{
                        Shape {
                            ShapePath {
                                fillColor: hovered? "blue" : highlighted? "green" : "black"
                                PathSvg { path: modelData.icon }
                            }
                        }
                    }
                    onClicked: {
                        lv.currentIndex = index
                        load.setSource(modelData.view)
                    }
                    highlighted: ListView.isCurrentItem
                    background: Rectangle{
                        anchors.fill: parent
                        color: "transparent"
                    }
                }
                Component.onCompleted: load.setSource("a.qml")
            }
        }

        Loader{
            id: load
            Layout.fillHeight: true
            Layout.fillWidth: true
            Layout.margins: 5
        }

        DropShadow{
            anchors.fill: rect
            source: rect
            radius: 10
            samples: 15
            color: "black"
        }

        DropShadow{
            anchors.fill: load
            source: load
            radius: 10
            samples: 15
            color: "black"
        }
    }
}

当我 运行 应用程序时,我得到这些 warnings/error:

qrc:/main.qml:58:9: QML DropShadow: Detected anchors on an item that is managed by a layout. This is undefined behavior; use Layout.alignment instead.
qrc:/main.qml:66:9: QML DropShadow: Detected anchors on an item that is managed by a layout. This is undefined behavior; use Layout.alignment instead. 

我必须在两个 DropShadow 中都有 anchors.fill: elementId 才能让它工作,对吗?外观如下:

首先,那些 SVG 并不顺利,我已经尝试使用列出的一些属性 here 但这些实际上没有帮助!我该怎么做才能使它们看起来更好?

其次,我想用 DropShadow 顶部的另一个 Rectangle 替换默认的 Window 标题栏,并添加 3 个 SVG 作为最小化、最大化和关闭buttons 但还没有找到任何自定义默认 QtQuick 的例子 Window.

编辑

这是保存 SVG 路径数据的 Constants.h

#ifndef CONSTANTS_H
#define CONSTANTS_H
#include<QString>

const QString AIcon = "M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M11,7A2,2 0 0,0 9,9V17H11V13H13V17H15V9A2,2 0 0,0 13,7H11M11,9H13V11H11V9Z";
const QString BIcon = "M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M15,10.5V9A2,2 0 0,0 13,7H9V17H13A2,2 0 0,0 15,15V13.5C15,12.7 14.3,12 13.5,12C14.3,12 15,11.3 15,10.5M13,15H11V13H13V15M13,11H11V9H13V11Z";
const QString CIcon = "M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M11,7A2,2 0 0,0 9,9V15A2,2 0 0,0 11,17H13A2,2 0 0,0 15,15V14H13V15H11V9H13V10H15V9A2,2 0 0,0 13,7H11Z";

#endif // CONSTANTS_H

这里是View.h,型号:

#ifndef VIEW_H
#define VIEW_H

#include <QObject>
#include <QString>
#include "Property.h"

class View : public QObject
{
    Q_OBJECT
    PROPERTY(QString, icon)
    PROPERTY(QString, view)
public:
    View(QString icon, QString view) : m_icon(icon), m_view(view) {}
};

#endif // VIEW_H

这里是VM.h,ViewModel

#ifndef VM_H
#define VM_H

#include <QObject>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QtCore>
#include "Property.h"
#include "Constants.h"
#include "view.h"

class VM : public QObject
{
    Q_OBJECT
    PROPERTY(QVector<View*>, views)
public:
    explicit VM(QObject *parent = nullptr);

private:
    QQmlApplicationEngine engine;

};

#endif // VM_H

这里是 VM.cpp:

#include "vm.h"

VM::VM(QObject *parent) : QObject(parent)
{
    engine.rootContext()->setContextProperty("ViewModel", this);
    engine.load("qrc:/main.qml");

    m_views.push_back(new View(AIcon, "a.qml"));
    m_views.push_back(new View(BIcon, "b.qml"));
    m_views.push_back(new View(CIcon, "c.qml"));
    emit viewsChanged();
}

这里是 main.cpp:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "vm.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
    VM vm;
    return app.exec();
}

PROPERTY宏:

#ifndef PROPERTY_H
#define PROPERTY_H

#define PROPERTY(QType, name) \
    Q_PROPERTY(QType name READ name WRITE set##name NOTIFY name##Changed) \
    public: \
    QType name(){return m_##name;}\
    void set##name(QType value){m_##name = value; emit name##Changed();} \
    Q_SIGNAL void name##Changed(); \
    private: \
    QType m_##name;


#endif // PROPERTY_H

这里是 a.qml:

import QtQuick 2.0

Item {
    anchors.fill: parent
    Rectangle{
        anchors.fill: parent
        Text{
            text: "A View"
            font.pointSize: 18
            anchors.centerIn: parent
        }
    }
}

a.qmlb.qmlc.qml除了text外都是一样的。对于 b.qml,我将 B View 作为 text,将 C View 作为 c.qml

flags: Qt.Window | Qt.CustomizeWindowHintflags: Qt.FramelessWindowHint 都有效。第一个默认情况下我得到一个调整大小的抓地力和一个外部黑色边框,但 TitleBar 比我预期的要高:

它总是显示在我的任务栏中。有了后者就完美了:

没有外边框,默认情况下没有调整大小功能,甚至不会出现在任务栏中。在这两种情况下,我都必须手动处理拖动!