总结了两个方式,推荐使用第一种
- 使用RectangularGlow来达到阴影的目的
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
main.qml
import QtQuick 2.9
import QtQuick.Window 2.0
import QtQuick.Controls 2.2
import QtQuick.Dialogs 1.2
import QtQuick.Controls.Styles 1.4
import QtGraphicalEffects 1.0
Window {
width: 840
height: 680
visible: true
color: "transparent"
x:Screen.width/2 - width/2
y:Screen.height/2 - height/2
property int titlebar_wrapper_size:40
id:registerWindow
flags: Qt.FramelessWindowHint |
Qt.WindowMinimizeButtonHint |
Qt.Window
function startLogin()
{
var userName = registername.text
if( userName != "" ){
id_mesDialog.icon = StandardIcon.Information
id_mesDialog.text = "登陆成功"
id_mesDialog.open()
}else{
id_mesDialog.icon = StandardIcon.Critical
id_mesDialog.text = "请输入用户名"
id_mesDialog.open()
}
}
MessageDialog {
id:id_mesDialog
title: "提示框"
icon: StandardIcon.Question
text: ""
standardButtons: StandardButton.Ok
Component.onCompleted: visible = false
}
Item {
anchors.fill: parent
RectangularGlow {
id: effect
anchors.fill: rect
glowRadius: 10
spread: 0.2
color: "#406A6F76"
cornerRadius: rect.radius + glowRadius
}
Rectangle {
id: rect
color: "white"
anchors.centerIn: parent
width: registerWindow.width - 40
height: registerWindow.height - 40
radius: 4
MouseArea {
id:dragparentwindow
width: parent.width
height: 57
property real lastMouseX: 0
property real lastMouseY: 0
onPressed: {
lastMouseX = mouseX
lastMouseY = mouseY
}
onMouseXChanged: registerWindow.x += (mouseX - lastMouseX)
onMouseYChanged: registerWindow.y += (mouseY - lastMouseY)
}
Rectangle{
id:titlebar
width: parent.width
Rectangle{
id:appclose
height: titlebar_wrapper_size
y:0
width: titlebar_wrapper_size
anchors.right: parent.right
Text{
text: "×"
anchors.horizontalCenter: parent.horizontalCenter
font.pointSize: 20
}
MouseArea{
width: parent.width
height: parent.height
hoverEnabled: true
onEntered: appclose.color="#ddd"
onExited: appclose.color="#fff"
onClicked: Qt.quit()
}
}
Rectangle{
id:appminimize
height: titlebar_wrapper_size
y:0
width: titlebar_wrapper_size
anchors.right: appclose.left
Text{
text: '-'
font.family: "Microsoft Yahei"
anchors.horizontalCenter: parent.horizontalCenter
font.pointSize: 15
}
MouseArea{
width: parent.width
height: parent.height
hoverEnabled: true
onEntered: appminimize.color="#ddd"
onExited: appminimize.color="#fff"
onClicked: registerWindow.visibility = Window.Minimized
}
}
Text{
text:"XTE"
font.family: "Microsoft Yahei"
font.pointSize: 85
anchors.horizontalCenter: parent.horizontalCenter
y:70
}
TextField{
id:registername
background: Rectangle {
border.color: "#0000CD"
border.width: 1
radius: 5
antialiasing:true
}
width:400
height:50
y:420
font.pointSize: 17
font.family: "Microsoft Yahei"
placeholderText: " Enter a nickname ..."
anchors.horizontalCenter: parent.horizontalCenter
}
Button{
id:login
text:"Login"
background: Rectangle {
anchors.fill: parent
radius: 3
color: login.down ? "#0084ff" :
login.hovered ? "#1AAD19" : "#0084ff"
}
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: registername.bottom
anchors.topMargin: 17
font.family: "Microsoft Yahei"
font.pointSize: 22
onClicked: startLogin()
}
}
}
}
}
- qml中的主界面是Rectangle,可以新建一个普通的widget,然后在widget类中新建QQuickView m_pQmlContainer = new QQuickView();然后根据这个QQuickView产生一个widget,作为当前窗口的子窗口,然后将当前窗口的标题栏隐藏。通过自绘来实现阴影。有个问题,MessageDialog弹出的时候,会有警告,并且不是模态的框。QQuickView(0x2de9437b5b0) must be a top level window
main.cpp
#include <QApplication>
#include <QQuickView>
#include "mainWidget.h"
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
MainWidget mainWidget;
mainWidget.SetQmlFile(QStringLiteral("qrc:/main.qml"));
mainWidget.show();
return app.exec();
}
mainWidget.h
#ifndef __MAIN_WIDGET_H_
#define __MAIN_WIDGET_H_
#include <QQuickView>
#include <QWidget>
#include <QPixmap>
#include <QPaintEvent>
class MainWidget : public QWidget
{
Q_OBJECT
public:
explicit MainWidget(QWidget *parent = nullptr);
~MainWidget();
void SetQmlFile(QString strQmlFile);
private:
QQuickView *m_pQmlContainer;
QPixmap m_shadow;
protected:
void paintEvent(QPaintEvent *e);
};
#endif
mainWidget.cpp
#include "mainWidget.h"
#include <QHBoxLayout>
#include <QQmlContext>
#include <QDebug>
#include <QPainter>
MainWidget::MainWidget(QWidget *parent): QWidget(parent),m_shadow(":/window_shadow.png")
{
m_pQmlContainer = new QQuickView();
QHBoxLayout* layout = new QHBoxLayout(this);
QWidget* pWidget = QWidget::createWindowContainer(m_pQmlContainer,this);
layout->addWidget(pWidget);
layout->setContentsMargins(5,3,5,7);
setLayout(layout);
setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint);
m_pQmlContainer->rootContext()->setContextProperty("window",this);
setFixedSize(910,610);
}
MainWidget::~MainWidget()
{
}
void MainWidget::SetQmlFile(QString strQmlFile)
{
m_pQmlContainer->setSource(strQmlFile);
}
void MainWidget::paintEvent(QPaintEvent* e)
{
QPainter painter(this);
QRect bottom(5, 136, 200, 7);
QRect top(5, 0, 200, 3);
QRect left(0, 3, 5, 133);
QRect right(205, 3, 5, 133);
QRect topRight(205, 0, 5, 3);
QRect topLeft(0, 0, 5, 3);
QRect bottomLeft(0, 136, 5, 7);
QRect bottomRight(205, 136, 5, 7);
QRect tBottom(5, this->height() - 7, this->width() - 10, 7);
QRect tTop(5, 0, this->width() - 10, 3);
QRect tLeft(0, 3, 5, this->height() - 10);
QRect tRight(this->width() - 5, 3, 5, this->height() - 10);
QRect tTopLeft(0, 0, 5, 3);
QRect tTopRight(this->width() - 5, 0, 5, 3);
QRect tBottomLeft(0, this->height() - 7, 5, 7);
QRect tBottomRight(this->width() - 5, this->height() - 7, 5, 7);
painter.drawPixmap(tBottom, m_shadow, bottom);
painter.drawPixmap(tTop, m_shadow, top);
painter.drawPixmap(tLeft, m_shadow, left);
painter.drawPixmap(tRight, m_shadow, right);
painter.drawPixmap(tTopRight, m_shadow, topRight);
painter.drawPixmap(tTopLeft, m_shadow, topLeft);
painter.drawPixmap(tBottomLeft, m_shadow, bottomLeft);
painter.drawPixmap(tBottomRight, m_shadow, bottomRight);
}
main.qml
import QtQuick 2.9
import QtQuick.Window 2.0
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
Rectangle {
id: loginWin
anchors.fill: parent
SystemPalette { id: activePalette }
//背景图片
Image
{
id: background
anchors { top: parent.top; bottom: parent.bottom }
anchors.fill: parent
source: "./background.jpeg"
fillMode: Image.PreserveAspectCrop
}
MouseArea {
anchors.fill: parent
property variant previousPosition
onPressed: {
previousPosition = Qt.point(mouseX,mouseY)
}
onPositionChanged: {
if(pressedButtons == Qt.LeftButton){
var dx = mouseX - previousPosition.x
var dy = mouseY - previousPosition.y
window.pos = Qt.point(window.pos.x + dx,window.pos.y + dy)
}
}
}
MessageDialog {
id:id_mesDialog
title: "提示框"
icon: StandardIcon.Question
text: ""
standardButtons: StandardButton.Ok
Component.onCompleted: visible = false
}
function login()
{
var userName = line.text
var password = linePassword.text
if( userName == "admin" && password == "123456" ){
id_mesDialog.icon = StandardIcon.Information
id_mesDialog.text = "登陆成功"
id_mesDialog.open()
}else{
id_mesDialog.icon = StandardIcon.Critical
id_mesDialog.text = "用户名或密码错误"
id_mesDialog.open()
}
}
//顶栏
Item
{
id: topBar
width: loginWin.width; height: loginWin.height*0.05
anchors.top: loginWin.top
anchors.topMargin: 20
Text
{
id: title
anchors { top: parent.top; horizontalCenter: parent.horizontalCenter }
text: "登陆"
font.bold: true
font.pointSize: loginWin.height * 0.05 * 0.7
color: "dark red"
}
}
//空白栏
Item
{
id: space
width: loginWin.width; height: loginWin.height * 0.1
anchors.top: topBar.bottom
}
// 登录框
Rectangle {
id: loginRect
width: loginWin.width * 0.8
height: loginWin.height * 0.3
anchors { top: space.bottom; horizontalCenter: parent.horizontalCenter }
border.color: "#707070"
color: "transparent"
LineInput
{
id: line
width: loginRect.width * 0.8; height: loginRect.height * 0.2
fontSize:height * 0.7
anchors { horizontalCenter: loginRect.horizontalCenter; top: loginRect.top; topMargin: 8 }
hint: "请输入用户号"
}
LineInput
{
id: linePassword
width: loginRect.width * 0.8; height: loginRect.height * 0.2
fontSize:height * 0.7
anchors { horizontalCenter: loginRect.horizontalCenter; bottom: loginButton.top; bottomMargin: loginRect.height * 0.1 }
hint: "请输入密码"
}
Button
{
id: loginButton
width: loginRect.width * 0.35; height: loginRect.height * 0.2
anchors { left: loginRect.left; leftMargin: 28; bottom: loginRect.bottom; bottomMargin: 8 }
text: "登陆"
onClicked: login()
}
Button
{
id: quitButton
width: loginRect.width * 0.35; height: loginRect.height * 0.2
anchors { right: loginRect.right; rightMargin: 28; bottom: loginRect.bottom; bottomMargin: 8 }
text: "退出"
onClicked: window.close()
}
}
}
Button.qml
import QtQuick 2.0
Rectangle {
id: container
property string text: "Button"
signal clicked
width: buttonLabel.width + 20; height: buttonLabel.height + 5
border { width: 1; color: Qt.darker(activePalette.button) }
antialiasing: true
radius: 8
// color the button with a gradient
gradient: Gradient {
GradientStop {
position: 0.0
color: {
if (mouseArea.pressed)
return activePalette.dark
else
return activePalette.light
}
}
GradientStop { position: 1.0; color: activePalette.button }
}
MouseArea {
id: mouseArea
anchors.fill: parent
onClicked: container.clicked();
}
Text {
id: buttonLabel
anchors.centerIn: container
color: activePalette.buttonText
text: container.text
}
}
LineInput.qml
import QtQuick 2.0
FocusScope {
id: wrapper
// 定义可通过元对象系统访问的属性
property alias text: input.text
property alias hint: hint.text
property int fontSize: 18
// 自定义信号
signal accepted
Rectangle {
anchors.fill: parent
border.color: "#707070"
color: "#c1c1c1"
radius: 4
// 输入栏隐藏文本
Text {
id: hint
anchors { fill: parent; leftMargin: 14 }
verticalAlignment: Text.AlignVCenter
horizontalAlignment: input.activeFocus ? Text.AlignLeft : Text.AlignHCenter
text: "Enter word"
font.pixelSize: fontSize
color: "#707070"
opacity: input.length ? 0 : 1
}
TextInput {
id: input
focus: true
anchors { left: parent.left; leftMargin: 14; right: parent.right; top: parent.top; bottom: parent.bottom }
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.pixelSize: fontSize
color: "black"
maximumLength: 8
onAccepted: wrapper.accepted()
}
}
}
window_shadow.png是这样的,大小为210*143,并且主窗口设置了margin,layout->setContentsMargins(5,3,5,7),留出来的边框用于自绘阴影。