OPenCV - QML图像处理(2):QML实现界面遮罩、带阴影和圆角的弹窗
·
Widget版本的有如下的遮罩和弹窗:

要用QML实现类似的功能。
遮罩:
ShadeItem.qml
import QtQuick 2.0
//遮罩
Rectangle
{
id: root
opacity: 0.0
state: enabled ? "on" : "baseState"
property int dialogWidth: 300
property int dialogHeight: 200
enabled: false
color: "black"
states:
[
State
{
name: "on"
PropertyChanges
{
target: root
opacity: 0.6
}
}
]
transitions:
[
Transition
{
from: "*"
to: "*"
NumberAnimation
{
properties: "opacity"
easing.type: Easing.OutQuart
duration: 500
}
}
]
}
简单的代码,默认是禁用不可见的,当启用时透明度设为 0.6。
带阴影和圆角的弹窗
MessageDialog.qml
import QtQuick 2.0
import Qt5Compat.GraphicalEffects
Window
{
id: root
visible: false
width: 500
height: 400
color: "#00000000"
modality: Qt.WindowModal
flags: Qt.FramelessWindowHint | Qt.Window
signal accepted
Rectangle
{
id: contextRect
anchors.fill: parent
anchors.margins: 20
radius: 12
MouseArea
{
anchors.fill: parent
property int dx
property int dy
onPressed:
{
dx = mouseX
dy = mouseY
}
onPositionChanged:
{
root.x += mouseX - dx
root.y += mouseY - dy
}
}
}
DropShadow
{
anchors.fill: contextRect
horizontalOffset: -5
verticalOffset: -5
radius: 12
color: "#20000000"
source: contextRect
transparentBorder :true
}
DropShadow
{
anchors.fill: contextRect
horizontalOffset: 5
verticalOffset: 5
radius: 12
color: "#20000000"
source: contextRect
transparentBorder :true
}
DropShadow
{
anchors.fill: contextRect
horizontalOffset: 5
verticalOffset: -5
radius: 12
color: "#20000000"
source: contextRect
transparentBorder :true
}
DropShadow
{
anchors.fill: contextRect
horizontalOffset: -5
verticalOffset: 5
radius: 12
color: "#20000000"
source: contextRect
transparentBorder :true
}
Text
{
id: titleText
text: qsTr("提示")
height: 40
color: "#00beac"
font.bold: true
font.pixelSize: 24
anchors.top: contextRect.top
anchors.horizontalCenter: contextRect.horizontalCenter
anchors.topMargin: 20
}
Text
{
id:infoText
color: "#222222"
font.pixelSize: 18
anchors.top: titleText.bottom
anchors.bottom: btn.top
anchors.left: contextRect.left
anchors.right: contextRect.right
horizontalAlignment:Text.AlignHCenter
verticalAlignment:Text.AlignVCenter
}
Button
{
id:btn
text: qsTr("确定")
width: 200;height: 44
anchors.bottom: contextRect.bottom
anchors.bottomMargin: 20
anchors.horizontalCenter: contextRect.horizontalCenter
onBtnclicked:
{
root.accepted()
}
}
function setMsgInfo(info)
{
infoText.text = info
root.visible = true
}
}
由于 DropShadow 类型只能设置偏向一个角的阴影偏移,这里设置了四个 DropShadow 对象确保弹窗四周都有阴影。
上面用到的按钮见:
QML编写自定义控件:自定义按钮_友善啊,朋友的博客-CSDN博客_qml 自定义按钮
迄今为止的 ShowMatItem 类型的C++代码:
#ifndef SHOWMATITEM_H
#define SHOWMATITEM_H
#include <QQuickPaintedItem>
#include <QPixmap>
#include <opencv2/core/core.hpp>
class ShowMatItem : public QQuickPaintedItem
{
Q_OBJECT
QML_ELEMENT
// QML_FOREIGN(cv::Mat)
public:
ShowMatItem(QQuickItem *parent = 0);
void paint(QPainter *painter)override;
Q_INVOKABLE void setSrcFile(const QString & filePath);
Q_INVOKABLE bool imageIsEmpty();
private:
cv::Mat mat;
QString srcFilePath;
};
#endif // SHOWMATITEM_H
#include "showmatitem.h"
#include <QPainter>
#include <QPixmap>
#include <QDebug>
#include "util.h"
ShowMatItem::ShowMatItem(QQuickItem *parent)
:QQuickPaintedItem(parent)
{
}
void ShowMatItem::paint(QPainter *painter)
{
painter->setRenderHints(QPainter::Antialiasing, true);
auto rect = boundingRect().toRect();
painter->drawPixmap(rect,util::matToPixmap(rect.size(),mat));
painter->save();
painter->setPen(QPen(QColor("#2222222"),3));
painter->drawRect(rect);
painter->restore();
}
void ShowMatItem::setSrcFile(const QString & filePath)
{
QString temp = filePath;
srcFilePath = temp.remove("file:///").replace("/","\\");
util::readImage(temp,mat);
update();
}
bool ShowMatItem::imageIsEmpty()
{
return mat.empty();
}
迄今为止的 main.qml 代码:
import QtQuick 2.14
import QtQuick.Controls
import com.qmlcompany.cppComponents 1.0
import Qt.labs.platform 1.1 as Labs //名称冲突了要用as,注意Labs要大写开头
import QtQuick.Layouts
ApplicationWindow
{
id:root
visible: true
title: qsTr("OpenCV图像处理助手")
color:"#FFFFFF"
width: 1000; height: 600
modality:Qt.ApplicationModal
menuBar: MenuBar
{
Menu
{
title: qsTr("文件")
MenuItem
{
text: qsTr("打开文件")
onTriggered:
{
fileDialog.open()
}
Labs.FileDialog
{
id: fileDialog
title: qsTr("打开图片")
nameFilters: ["image files (*.png *.jpg *.jpeg *.bmp)"]
acceptLabel: qsTr("确定")
rejectLabel: qsTr("取消")
fileMode: Labs.FileDialog.OpenFile
onAccepted:
{
var filePath = fileDialog.files[0]
srcImage.setSrcFile(filePath)
}
}
}
MenuSeparator {}
MenuItem
{
text: qsTr("退出")
onTriggered: Qt.quit()
}
}
Menu
{
title: qsTr("形态学操作")
MenuItem
{
text: qsTr("选择操作参数")
onTriggered:
{
if(!srcImageIsEmpty())
{
console.log("图片不为空")
}
}
}
}
}
RowLayout
{
id: layout
anchors.fill: parent
spacing: 20
ShowMatItem
{
id:srcImage
Layout.preferredWidth: parent.width/2 - layout.spacing/2 - Layout.margins*2
Layout.preferredHeight: parent.height - Layout.margins*2
Layout.margins: 10
}
ShowMatItem
{
id:desImage
Layout.preferredWidth: parent.width/2 - layout.spacing/2 - Layout.margins*2
Layout.preferredHeight: parent.height - Layout.margins*2
Layout.margins: 10
}
}
ShadeItem
{
id:windowShadeItem
anchors.fill: parent
}
MessageDialog
{
id:messageDialog
onAccepted:
{
messageDialog.visible = false
windowShadeItem.enabled = false
}
}
function srcImageIsEmpty()
{
if(srcImage.imageIsEmpty())
{
windowShadeItem.enabled = true
messageDialog.setMsgInfo("请先打开一张图片")
return true;
}
return false;
}
}
效果:

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)