不少朋友需要会用到模态对话框,那么如何使用QML创建模态对话框呢?
分析:
我所需要的模态对话框是这样的:
从上到下一次包含了:
a.标题栏
b.内容框
c.按钮栏
为了方便接口使用,我们将这三个部分整合在一个Window中。
这里是代码示例:
import QtQuick 2.0
import QtQuick.Layouts 1.1
import QtQuick.Window 2.0
Window {
id: eo_askDialog
width: 300
height: 200
ColumnLayout{
anchors.fill: parent
spacing:2
//标题栏
Rectangle{
id: titleBar
Layout.fillWidth: parent
implicitHeight: 30
color: "darkgray"
}
//内容框
Rectangle{
id: contentView
Layout.fillWidth: parent
Layout.fillHeight: parent
color: "lightgray"
}
//按钮栏
Rectangle{
id: buttonBar
Layout.fillWidth: parent
implicitHeight: 30
color: "darkgray"
}
}
}
功能确定:
1.返回确认信号
2.返回取消信号
3.返回checkBox被选中时候的确认信号
4.返回关闭信号
5.可定制标题栏背景
6.可定制内容框背景
7.可定制按钮栏背景
8.可定制文字信息
为了实现以下功能,我们需要往Window中添加一些属性:
property string title: "ask dialog" //对话框标题
property string content: "ask content." //对话框内容
property string yesButtonString: "yes" //yes按钮的文字
property string noButtonString: "no" //no按钮的文字
property string checkBoxString: "check box" //选择框的文字
property string titleBackgroundImage: "" //标题栏背景图片
property string contentBackgroundImage: "" //内容框的背景图片
property string buttonBarBackgroundImage: "" //按钮框的背景图片
property bool checked: false //选择框是否确认
因为我们需要实现自定义的标题栏,所以加上这个属性可以忽略系统自带的标题栏:
flags: Qt.FramelessWindowHint | Qt.Window | Qt.WindowStaysOnTopHint
当然,不能忘了这是个模态对话框,加上如下的属性:
modality: Qt.ApplicationModal
我们需要告知外界Window的情况,所以加上自定义的信号:
/** 自定义信号
1.accept, yes按钮被点击
2.reject, no按钮被点击
3.checkAndAccept, 选择框和yes按钮被点击
**/
signal accept();
signal reject();
signal checkAndAccept();
现在我们得到了一个基本的模态框,只是现在还没有加上具体的标题、按钮和内容,以及把信号发送出去的相关逻辑代码。
这是Window现在的样子:
(你可以试着把它运行,但它就躺在那里不会理你)
现在我们需要一些交互代码:
1.实现标题栏
往Window的标题栏中加入一个RowLayout,其中包含2个MouseArea,
一个用于标题栏的文字显示和交互控制,另一个则作为关闭按钮使用。
RowLayout{
anchors.fill: parent
spacing: 2
MouseArea{
id: mouseControler
property point clickPos: "0,0"
Layout.fillHeight: parent
Layout.fillWidth: parent
//title
Text{
text: title
anchors.bottom: parent.bottom
anchors.bottomMargin: 5
anchors.left: parent.left
anchors.leftMargin: 10
}
onPressed: {
clickPos = Qt.point(mouse.x,mouse.y)
}
onPositionChanged: {
//鼠标偏移量motai
var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
//如果mainwindow继承自QWidget,用setPos
eo_askDialog.setX(eo_askDialog.x+delta.x)
eo_askDialog.setY(eo_askDialog.y+delta.y)
}
}
//close button
MouseArea{
id: closeButton
Layout.fillHeight: parent
implicitWidth: 45
Rectangle{
anchors.fill: parent
color:"red"
}
onClicked: {
console.log("close button clicked.");
eo_askDialog.visible = false;
reject()
}
}
}
这下我们的窗口就能拖动和关闭了!现在该轮到内容框了,
直接添加一个Text到Window的内容框中:
Text{
text: content
anchors.centerIn: parent
}
最后则是按钮栏,它和标题栏类似:
RowLayout{
anchors.fill: parent
spacing: 2
//checkBox
MouseArea{
id: checkBox
Layout.fillHeight: parent
width:100
Rectangle{
anchors.fill: parent
color:"lightgray"
}
Text{
text: checkBoxString
anchors.centerIn: parent
}
onClicked: {
checked = checked == false
console.log("checked changed.", checked)
}
}
//h spacer
Rectangle{
id: buttonBarSpacer
color: Qt.rgba(0,0,0,0)
Layout.fillWidth: parent
}
//yes button
MouseArea{
id: yesButton
Layout.fillHeight: parent
width:75
Rectangle{
anchors.fill: parent
color:"lightgray"
}
Text{
text: yesButtonString
anchors.centerIn: parent
}
onClicked: {
console.log("yes button clicked.")
eo_askDialog.visible = false;
if(checked){
checkAndAccept()
}
else{
accept()
}
}
}
//no button
MouseArea{
id: noButton
Layout.fillHeight: parent
width:75
Rectangle{
anchors.fill: parent
color:"lightgray"
}
Text{
text: noButtonString
anchors.centerIn: parent
}
onClicked: {
console.log("no button clicked.")
eo_askDialog.visible = false;
reject();
}
}
}
其中h space 只是一个占位置的框而已,用于把checkbox 和 yes、no 按钮分隔开。现在我们的框就是这样的:
具有完整的模态框的功能。
要完成背景图片的定制只需要往需要的MouseArea中加入一个Image
并引用Window的中定义的图片路径,并在Image
中添加一下不同的事件切换不同状态的图片的代码就好了,
当然你也可以根据自己的需要自行定制