基于qml创建最简单的图像处理程序(1)-基于qml创建界面

为什么使用QT,包括进一步使用QML?两个主要原因,一是因为我是一个c++程序员,有语言使用惯性;二是我主要做图像处理方面工作,使用什么平台对于我来说不重要,我只需要在不同平台上面能够运行我的图像处理程序(而主要是和OpenCV有关系的)。所以选择QT,它能够在win/linux/android,包括PI上面都提供不错的GUI支持;而如果我想在Android上编写图像处理程序,又主要遇到两个问题,一是相机的获取。OpenCV的videocapture在Android上支持不好,在最新版本的OpenCV里面已经把这个部分相关内容去掉了,同时QCamera(基于widget的camera)支持也不好,Qml是目前对Android支持最好的。这个地方QML提供的camera功能就类似windows中的dshow一样,是一个基础类库;二是界面的创建,在windows下面,基于ribbon等,我能够创建还说的过去的界面,但是在Android中,目前没有很好的工具。特别是在手机这个小小界面中,如果界面有问很影响使用。

我需要的是一个界面说的过去(有官方控件),对相机支持好,能够支持各种平台的这么一个工具,不求最好,但是要能用。在不多的选择中,QML(qtquick)是最合适的。当然如果要掌握QML也要跨越一些学习曲线,但是付出是值得的。

本文中参考了一些资料(主要是《qtquick核心编程》),我们基于qml创建最简单的图像处理程序。两个主要内容,一个是直接使用qml自己的能力进行图像处理;二个是引用并且使用OpenCV。只求实现主要功能,很多细节还需打磨,但我相信瑕不掩瑜。

新建工程,最新默认的界面main.qml代码为

import QtQuick 2.9
import QtQuick.Window 2.2

Window {
visible: true
width: 640
height: 480
}

我就直接在这个QML上进行修改

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.1
import QtQuick.Dialogs 1.1
import QtQuick.Controls.Styles 1.1
Window {
    visible: true
    width: 640
    height: 480
    //RGB
    color: "#0000FF";

//忙等控件,包含在QtQuick.Controls中
    BusyIndicator {
        id: busy;
        running: false;
        anchors.centerIn: parent;
        z: 2;
    }
    //状态显示Label
    Label {
        id: stateLabel;
        visible: false;
        anchors.centerIn: parent;
    }
    //主要界面
    Image {
        objectName: "imageViewer";
        id: imageViewer;
        asynchronous: true;
        anchors.fill: parent;
        fillMode: Image.PreserveAspectFit;
        //根据imageviewer状态判断,控制控件表现出不同状态
        onStatusChanged: {
            if (imageViewer.status === Image.Loading) {
                busy.running = true;
                stateLabel.visible = false;
            }
            else if(imageViewer.status === Image.Ready){
                busy.running = false;
            }
            else if(imageViewer.status === Image.Error){
                busy.running = false;
                stateLabel.visible = true;
                stateLabel.text = "ERROR";
            }
        }
    }

//打开文件界面,包含在 QtQuick.Dialogs 中。固然在Android中使用这个方法打开图片不是最佳方法,但是可用方法
    FileDialog {
        id: fileDialog;
        title: "Please choose a file";
        nameFilters: ["Image Files (*.jpg *.png *.gif)"];
        onAccepted: {
            console.log(fileDialog.fileUrl);
            imageViewer.source = fileDialog.fileUrl;
        }
    }

//以下用于创建button,其中ButtonStyle来自QtQuick.Controls.Styles
    //其中所谓Component就是可重用构建的意思,这个用于Button的Componet是可以复用的
    Component{
        id: btnStyle;
        ButtonStyle {
            background: Rectangle {
                implicitWidth: 140;
                implicitHeight: 50;
                border.width: control.pressed ? 2 : 1;
                border.color: (control.pressed || control.hovered) ? "#00A060" : "#888888";
                radius: 12;
                gradient: Gradient {
                    GradientStop { position: 0 ; color: control.pressed ? "#cccccc" : "#e0e0e0"; }
                    GradientStop { position: 1 ; color: control.pressed ? "#aaa" : "#ccc"; }
                }
            }
        }
    }
    //就是做了个黑色的框子,用于放button的
    Rectangle {
        anchors.left: parent.left;
        anchors.top: parent.top;
        anchors.bottom: openFile.bottom;
        anchors.bottomMargin: -6;
        anchors.right: quit.right;
        anchors.rightMargin: -6;
        color: "#404040";
        opacity: 0.7;
    }

//打开按钮
    Button {
        id: openFile;
        text: "打开";
        anchors.left:  parent.left;
        anchors.leftMargin: 6;
        anchors.top: parent.top;
        anchors.topMargin: 6;
        onClicked: {
            fileDialog.visible = true;
        }
        //直接使用了btnStyle
        style: btnStyle;
        z: 1;
    }
    //退出就是退出
    Button {
        id: quit;
        text: "退出";
        anchors.left: openFile.right;
        anchors.leftMargin: 4;
        anchors.bottom: openFile.bottom;
        onClicked: {
            Qt.quit()
        }
        style: btnStyle;
        z: 1;
    }

//另外一个黑色框子,注意用到了op,也就是上面的4个按钮

Rectangle {
        anchors.left: parent.left;
        anchors.top: op.top;
        anchors.topMargin: -4;
        anchors.bottom: parent.bottom;
        anchors.right: op.right;
        anchors.rightMargin: -4;
        color: "#404040";
        opacity: 0.7;
    }

//以另一种方式将几个按钮连在一起
    //我们实现4个比较简单的效果
    Grid {
        id: op;
        anchors.left: parent.left;
        anchors.leftMargin: 4;
        anchors.bottom: parent.bottom;
        anchors.bottomMargin: 4;
        rows: 2;
        columns: 2;
        rowSpacing: 4;
        columnSpacing: 4;
        z: 1;
        //柔化效果
        Button {
            text: "柔化";
            style: btnStyle;
            onClicked: {
                //busy.running = true;
                //processor.process(fileDialog.fileUrl, ImageProcessor.Soften);
            }
        }
        //灰度效果
        Button {
            text: "灰度";
            style: btnStyle;
            onClicked: {
                //busy.running = true;
                //processor.process(fileDialog.fileUrl, ImageProcessor.Gray);
            }
        }
        //浮雕效果
        Button {
            text: "浮雕";
            style: btnStyle;
            onClicked: {
                //busy.running = true;
                //processor.process(fileDialog.fileUrl, ImageProcessor.Emboss);
            }
        }
        //黑白效果
        Button {
            text: "黑白";
            style: btnStyle;
            onClicked: {
                //busy.running = true;
                //processor.process(fileDialog.fileUrl, ImageProcessor.Binarize);
            }
        }
    }

}

虽然代码代码看上去有点多,但是好在还算有结构。

1、头文件,不多说。用在哪里的看注释;

2、全部的界面都包含在Windos{}中的

Window {
    visible: true
    width: 640
    height: 480
    //RGB
    color: "#0000FF";
……

在这段代码中width和height已经没有什么实际价值了。需要注意的是color为背景色,而qml是按照RGB来定义的。

3、控件控件,全部都是控件的定义。我们使用QML就要习惯直接使用代码定义的方式精确地进行界面定位,包含以下:

//忙等控件,包含在QtQuick.Controls中
    BusyIndicator {
        id: busy;
        running: false;
        anchors.centerIn: parent;
        z: 2;
    }

//状态显示Label
    Label {
        id: stateLabel;
        visible: false;
        anchors.centerIn: parent;
    }

//主要图片显示
    Image {
        objectName: "imageViewer";
        id: imageViewer;
        asynchronous: true;
        anchors.fill: parent;
        fillMode: Image.PreserveAspectFit;
        //根据imageviewer状态判断,控制控件表现出不同状态
        onStatusChanged: {
            if (imageViewer.status === Image.Loading) {
                busy.running = true;
                stateLabel.visible = false;
            }
            else if(imageViewer.status === Image.Ready){
                busy.running = false;
            }
            else if(imageViewer.status === Image.Error){
                busy.running = false;
                stateLabel.visible = true;
                stateLabel.text = "ERROR";
            }
        }
    }

//打开文件界面,包含在 QtQuick.Dialogs 中。固然在Android中使用这个方法打开图片不是最佳方法,但是可用方法
    FileDialog {
        id: fileDialog;
        title: "Please choose a file";
        nameFilters: ["Image Files (*.jpg *.png *.gif)"];
        onAccepted: {
            console.log(fileDialog.fileUrl);
            imageViewer.source = fileDialog.fileUrl;
        }
    }

4、按钮控件,但是使用了一些可重用思想

//以下用于创建button,其中ButtonStyle来自QtQuick.Controls.Styles
    //其中所谓Component就是可重用构建的意思,这个用于Button的Componet是可以复用的
    Component{
        id: btnStyle;
        ButtonStyle {
            background: Rectangle {
                implicitWidth: 140;
                implicitHeight: 50;
                border.width: control.pressed ? 2 : 1;
                border.color: (control.pressed || control.hovered) ? "#00A060" : "#888888";
                radius: 12;
                gradient: Gradient {
                    GradientStop { position: 0 ; color: control.pressed ? "#cccccc" : "#e0e0e0"; }
                    GradientStop { position: 1 ; color: control.pressed ? "#aaa" : "#ccc"; }
                }
            }
        }
    }

//打开按钮
    Button {
        id: openFile;
        text: "打开";
        anchors.left:  parent.left;
        anchors.leftMargin: 6;
        anchors.top: parent.top;
        anchors.topMargin: 6;
        onClicked: {
            fileDialog.visible = true;
        }
        //直接使用了btnStyle
        style: btnStyle;
        z: 1;
    }
    //退出就是退出
    Button {
        id: quit;
        text: "退出";
        anchors.left: openFile.right;
        anchors.leftMargin: 4;
        anchors.bottom: openFile.bottom;
        onClicked: {
            Qt.quit()
        }
        style: btnStyle;
        z: 1;
    }

5、将按钮放在一起,我们使用grid

//以另一种方式将几个按钮连在一起
    //我们实现4个比较简单的效果
    Grid {
        id: op;
        anchors.left: parent.left;
        anchors.leftMargin: 4;
        anchors.bottom: parent.bottom;
        anchors.bottomMargin: 4;
        rows: 2;
        columns: 2;
        rowSpacing: 4;
        columnSpacing: 4;
        z: 1;
        //柔化效果
        Button {
            text: "柔化";
            style: btnStyle;
            onClicked: {
                //busy.running = true;
                //processor.process(fileDialog.fileUrl, ImageProcessor.Soften);
            }
        }
        //灰度效果
        Button {
            text: "灰度";
            style: btnStyle;
            onClicked: {
                //busy.running = true;
                //processor.process(fileDialog.fileUrl, ImageProcessor.Gray);
            }
        }
        //浮雕效果
        Button {
            text: "浮雕";
            style: btnStyle;
            onClicked: {
                //busy.running = true;
                //processor.process(fileDialog.fileUrl, ImageProcessor.Emboss);
            }
        }
        //黑白效果
        Button {
            text: "黑白";
            style: btnStyle;
            onClicked: {
                //busy.running = true;
                //processor.process(fileDialog.fileUrl, ImageProcessor.Binarize);
            }
        }
    }

6、两个黑色框子,没有其它用途,就是美观

//就是做了个黑色的框子,用于放button的
    Rectangle {
        anchors.left: parent.left;
        anchors.top: parent.top;
        anchors.bottom: openFile.bottom;
        anchors.bottomMargin: -6;
        anchors.right: quit.right;
        anchors.rightMargin: -6;
        color: "#404040";
        opacity: 0.7;
    }

//另外一个黑色框子,注意用到了op,也就是上面的4个按钮
    Rectangle {
        anchors.left: parent.left;
        anchors.top: op.top;
        anchors.topMargin: -4;
        anchors.bottom: parent.bottom;
        anchors.right: op.right;
        anchors.rightMargin: -4;
        color: "#404040";
        opacity: 0.7;
    }

这个时候已经有以下界面,能够打开显示图片了

打开图片,显示图片

到这个部分请查看 阶段代码1

来自为知笔记(Wiz)

附件列表

原文地址:https://www.cnblogs.com/jsxyhelu/p/8343310.html

时间: 2024-08-25 06:11:53

基于qml创建最简单的图像处理程序(1)-基于qml创建界面的相关文章

基于qml创建最简单的图像处理程序(2)-使用c++&qml进行图像处理

<基于qml创建最简单的图像处理程序>系列课程及配套代码基于qml创建最简单的图像处理程序(1)-基于qml创建界面http://www.cnblogs.com/jsxyhelu/p/8343310.html课程1附件https://files.cnblogs.com/files/jsxyhelu/%E9%98%B6%E6%AE%B5%E4%BB%A3%E7%A0%811.zip基于qml创建最简单的图像处理程序(2)-使用c++&qml进行图像处理http://www.cnblogs

ASP.NET 创建WebService——简单例子

Web service是一个基于可编程的web的应用程序,用于开发分布式的互操作的应用程序,也是一种web服务 WebService的特性有以下几点: 1.使用XML(标准通用标记语言)来作为数据交互的格式. 2.跨平台性,因为使用XML所以只要本地应用可以连接网络解析XML就可以实现数据交换,比如安卓.IOS.WindowsPhone等都可以实现对Web service的数据交互. 3.基于HTTP协议,直接跨越防火墙,通用型强: 下面使用Visual Studio 2013(其他VS版本亦是

Highcharts创建一个简单的柱状图

新建一个html文件,将highcharts引入到你的页面后,通过两个步骤我们就可以创建一个简单的图表了. 1.创建div容器 在页面的 body部分创建一个div,并指定div 的 id,高度和宽度,代码如下 <div id="container" style="min-width:800px;height:400px"></div> 2.编写Highcharts代码 编写Highcharts必须的代码,用<script><

图像处理程序框架—MFC相关知识点

CDC:Windows使用与设备无关的图形设备环境(DC :Device Context) 进行显示 . MFC基础类库定义了设备环境对象类----CDC类.CDC与CGdiObject的关系 说道CDC类就不能不提一下GdiObject---图形对象类. 在Windows应用程序中,设备环境与图形对象共同工作,协同完成绘图显示工作.就像画家绘画一样,设备环境好比是画家的画布,图形对象好比是画家的画笔.用画笔在画布上绘画,不同的画笔将画出不同的画来.选择合适的图形对象和绘图对象,才能按照要求完成

设计模式之简单工厂模式Simple Factory(四创建型)

工厂模式简介. 工厂模式专门负责将大量有共同接口的类实例化 工厂模式可以动态决定将哪一个类实例化,不必事先知道每次要实例化哪一个类. 工厂模式有三种形态: 1.简单工厂模式Simple Factory,又称静态工厂方法模式 2.工厂方法模式Factory Method,又称多态性工厂模式 3.抽象工厂模式Abstract Factory,又称工具箱模式 2.什么是简单工厂模式 简单工厂模式是类的创建模式.是由一个工厂对象决定创建出哪一种产品类的实例,是不同的工厂方法模式的一个特殊实现.由一个工厂

基于BP神经网络的简单字符识别算法自小结(C语言版)

本文均属自己阅读源码的点滴总结,转账请注明出处谢谢. 欢迎和大家交流.qq:1037701636 email:[email protected] 写在前面的闲话: 自我感觉自己应该不是一个很擅长学习算法的人,过去的一个月时间里因为需要去接触了BP神经网络.在此之前一直都认为算法界的神经网络.蚁群算法.鲁棒控制什么的都是特别高大上的东西,自己也就听听好了,未曾去触碰与了解过.这次和BP神经网络的邂逅,让我初步掌握到,理解透彻算法的基本原理与公式,转为计算机所能识别的代码流,这应该就是所谓的数学和计

基于Struts1框架的简单工程搭建

新进入了某坑爹外包公司,所有的项目几乎都是用很古老的框架struts1,这里对struts温习下,并搭建了一个简单的登录工程. 1.Eclipse下创建一个Web工程,工程名称StrutsOneDemo,根目录修改为WebRoot(这样的Web工程可以在myeclipse下正常运行),该工程实现登录功能: 2.在lib中添加Struts1所需的jar包,这里使用的是1.3.10版本的jar包: 3.在src下创建三个包com.by.action.com.by.form.com.by.manage

创建一个简单的 MDM 服务器(1)

前提:已获得 APNS 证书 ,已完成 MDM 配置描述文件的制作.请参考< MDM 证书申请流程 >一文和<配置MDM Provisioning Profile>. 环境:OSX 10.9.2,JDK 1.6,Eclipse JavaEE Helois,Tomcat 7.0 一.前言 <THE IOS MDMPROTOCOL>(即Inside Apple MDM)一文中描述了一个简单 MDM Server Python 实现(server.py).笔者也曾参照此文配置

django创建一个简单的web站点

一.新建project 使用Pycharm,File->New Project-,选择Django,给project命名 (project不能用test命名) 新建的project目录如下: settings.py:工程相关的配置 urls.py:网站访问入口,对应到views wigs.py:部署相关 manage.py:执行命令 templates:html等静态文件 备注:新建工程后需要安装django的lib包,然后验证django是否安装成功 >>> import dja