《基于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.com/jsxyhelu/p/8361441.html
课程2附件
https://files.cnblogs.com/files/jsxyhelu/%E9%98%B6%E6%AE%B5%E4%BB%A3%E7%A0%812.zip
基于qml创建最简单的图像处理程序(3)-使用opencv&qml进行图像处理
http://www.cnblogs.com/jsxyhelu/p/8361443.html
课程3附件
https://files.cnblogs.com/files/jsxyhelu/%E9%98%B6%E6%AE%B5%E4%BB%A3%E7%A0%813.zip

  为什么使用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;
    }

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

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

  1. Spring MVC:使用基于Java的配置创建一个简单的Controller

    这是我博客上与Spring MVC相关的第一篇文章. 开端总是令人兴奋的,因此我将尽量简洁明了. Spring MVC允许以最方便,直接和快速的方式创建Web应用程序. 开始使用这项技术意味着需要Sp ...

  2. Qt6 QML Book/QtQuick控件/图像查看器

    An Image Viewer 图像查看器 Let's look at a larger example of how Qt Quick Controls are used. For this, we ...

  3. Linux实验三父子进程每隔3秒,实验三进程的创建和简单控制(学生分析.doc

    实验三进程的创建和简单控制(学生分析 实验 进程的创建和简单控制 实验目的: 掌握进程的概念和进程的状态,对进程有感性的认识: 掌握进程创建方法: 认识进程的并发执行,了解进程族之间各种标识及其存在的 ...

  4. java多线程创建一个简单的案例

    1.创建一个简单的线程,不需要去创建个Runnable Thread thread = new Thread(new Runnable() {@Overridepublic void run() {/ ...

  5. 创建一个简单的springboot项目demo

    springboot的核心功能: 1:起步依赖 2:核心注入; 创建一个简单的springboot项目demo步骤: 1:创建一个maven项目 2:pom.xml添加起步依赖 <parent& ...

  6. iWatch 开发 2:创建一个简单的Apple watch应用

    在上篇文章中,我系统的介绍了一下 iWatch 的功能,相信大家对iWatch开发 也有了一个系统的认识. 今天这篇文章来跟大家说下如何创建一个简单的 iWatch app. 使用 Xcode 创建 ...

  7. 创建一个简单的守护进程

    下面的内容是看了书上总结来的. 要写这样的一个程序看似复杂,但是它也是遵循一定的规则的.书中的方法介绍了用五个步骤来创建一个简单的守护进程. 1.创建子进程,父进程退出 由于守护进程是在后台运行,脱离 ...

  8. 基于MFC SDI的图像处理程序(带效果图)

    基于MFC SDI的图像处理程序(带效果图) 收藏 本程序主要实现了位图的打开保存,JPG格式作为BMP格式,以及24位BMP转化到8位.4位.1位(黑白图)及灰度图.还有一些简单的算法如反色,采用高 ...

  9. java简单创建图片面板_图像界面编程简单窗体创建

    /* * 图像界面编程 * JFrame 窗体 * JPanel 面板 * JLabel 标签 * JButton 按钮 * JLabel 标签 * ImageIcon 图标 * * * */ pac ...

最新文章

  1. 基于先验时间一致性车道线的IPM相机外参标定
  2. Maven最全笔记,99%的人都收藏了!
  3. PR详解及二分类的PR曲线绘制
  4. IOS NSInvocation应用与理解
  5. 用Elm语言降低失败的风险
  6. 【设计模式】单例模式 Singleton Pattern
  7. 单元测试线程代码的5个技巧
  8. 【AI视野·今日CV 计算机视觉论文速览 第242期】Mon, 14 Feb 2022
  9. Apache SOLR and Carrot2集成
  10. H264格式详细说明
  11. IDEA 启动本地 Flink Web UI
  12. h5页面如何切图_H5设计稿切图按照什么尺寸,微信公众号版本的
  13. VPP协议栈学习一:snd_wnd
  14. 树莓派 自动关闭屏幕解决办法
  15. outlook中打不开超链接
  16. 新型肺炎疫情蔓延下的游戏行业会更火爆吗?
  17. 为什呢vue组件中的data必须是函数?
  18. 笔记:MySQL中的DDL、DML、DQL、约束等知识以及Navicat的安装教程
  19. SIGCOMM‘2021 Congestion Detection in Lossless Networks 阅读笔记
  20. On release of batch it still contained JDBC statements

热门文章

  1. framework7使用笔记
  2. leetcode -- 3 sum
  3. CCTouchDispatcher sharedDispatcher 方法过期
  4. IOS数据存储之文件沙盒存储
  5. 开启JAVA自学新篇章
  6. 前端技术选型的遗憾和经验教训
  7. Hibernate学习(九)———— 二级缓存和事务级别详讲
  8. mysql format函数对数字类型转化的坑
  9. 媒体查询漫谈——@media Queries
  10. Fetch API 初步解读