第三章 创建完整的Qt+OpenCV项目,本章学习记录的内容包括:
1.Qt应用程序样式
2.Qt应用程序多语言
3. 如何在Qt中创建和使用插件
1..接第二章的项目Hello_Qt_OpenCV,在它的基本上添加样式表,
样式表内容为:
*
{
font: 75 11pt;
background-color: rgb(220, 220, 220);
}
QPushButton, QLineEdit, QGroupBox
{
border: 2px solid rgb(0, 0, 0);
border-radius: 10px;
min-width: 80px;
min-height: 35px;
}
QPushButton
{
background-color: rgb(0, 255, 0);
}
QLineEdit
{
background-color: rgb(0, 170, 255);
}
QPushButton:hover, QRadioButton:hover, QCheckBox:hover
{
color: red;
}
QPushButton:!hover, QRadioButton:!hover, QCheckBox:!hover
{
color: black;
}
点击MainWindow类,选择styleSheet属性,打开属性对话框,输入上面的qss代码,如下所示:
点击OK按钮,马上就可以看到效果了
编译运行结果如下:
2.Qt应用程序多语言
首先要生成翻译文件,在项目工程文件中(*.pro)添加翻译文件即
TRANSLATIONS = translation_de.ts translation_tr.ts, 然后选择菜单【工具】=》【外部】=》【Qt语言家】=》【更新翻译lupdate】就生成了以上两个翻译文件。
也可以用命令来执行C:\Qt\Qt5.12.9\5.12.9\msvc2017_64\bin\lupdate.exe Hello_Qt_OpenCV.pro都可以生生翻译文件,然后用linguist.exe打开 翻译文件。
对每一条文案进行翻译。
然后点菜单栏【文件】=》【发布】即可生成*.qm的二进制语言文件。
接着把二进制的语言文件添加到资源文件中。
编写应用语言的代码:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
loadSettings();
turkishTranslator = new QTranslator(this);
turkishTranslator->load(":/translations/translation_tr.qm");
germanTranslator = new QTranslator(this);
germanTranslator->load(":/translations/translation_de.qm");
}
在菜单中添加三个子菜单项
编写对应该的槽函数及语言切换事件函数
protected:
void changeEvent(QEvent *event);
private slots:
void on_actionTurkish_triggered();
void on_actionEnglish_triggered();
void on_actionGerman_triggered();
private:
Ui::MainWindow *ui;
void loadSettings();
void saveSettings();
QTranslator *turkishTranslator;
QTranslator *germanTranslator;
void MainWindow::changeEvent(QEvent *event)
{
if(event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
else
{
QMainWindow::changeEvent(event);
}
}
void MainWindow::on_actionTurkish_triggered()
{
qApp->installTranslator(turkishTranslator);
}
void MainWindow::on_actionGerman_triggered()
{
qApp->installTranslator(germanTranslator);
}
void MainWindow::on_actionEnglish_triggered()
{
qApp->removeTranslator(turkishTranslator);
qApp->removeTranslator(germanTranslator);
}
运行效果:
3.QT的插件创建与使用
首先创建一个名为median_filter_plugin插件项目,【文件】=》【新建文件或项目】=》【Library】=》【C++ Library】,选择相应的文件目录,按操作指引创建项目。
一定要将类型选为“Shared Library”,然后输入“median_filter_plugin”作为名称并单击【下一步】。选择工具箱类型作为桌面。在“Select Required Modules”页面中,确保只选中了“QtCore”,并继续单击【下一步】(最后单击【完成】),不需要更改任何选项,直到最终进入Qt Creator的代码编辑器页面。
添加代码
//cvplugininterface.h
#ifndef CVPLUGININTERFACE_H
#define CVPLUGININTERFACE_H
#include <QObject>
#include <QString>
#include "opencv2/opencv.hpp"
class CvPluginInterface
{
public:
virtual ~CvPluginInterface() {}
virtual QString description() = 0;
virtual void processImage(const cv::Mat &inputImage, cv::Mat &outputImage) = 0;
};
#define CVPLUGININTERFACE_IID "com.amin.cvplugininterface"
Q_DECLARE_INTERFACE(CvPluginInterface, CVPLUGININTERFACE_IID)
#endif // CVPLUGININTERFACE_H
//median_filter_plugin.h
#ifndef MEDIAN_FILTER_PLUGIN_H
#define MEDIAN_FILTER_PLUGIN_H
#include "median_filter_plugin_global.h"
#include "cvplugininterface.h"
class MEDIAN_FILTER_PLUGINSHARED_EXPORT Median_filter_plugin: public QObject, public CvPluginInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "com.amin.cvplugininterface")
Q_INTERFACES(CvPluginInterface)
public:
Median_filter_plugin();
~Median_filter_plugin();
QString description();
void processImage(const cv::Mat &inputImage, cv::Mat &outputImage);
};
#endif // MEDIAN_FILTER_PLUGIN_H
//median_filter_plugin_global.h
#ifndef MEDIAN_FILTER_PLUGIN_GLOBAL_H
#define MEDIAN_FILTER_PLUGIN_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(MEDIAN_FILTER_PLUGIN_LIBRARY)
# define MEDIAN_FILTER_PLUGINSHARED_EXPORT Q_DECL_EXPORT
#else
# define MEDIAN_FILTER_PLUGINSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // MEDIAN_FILTER_PLUGIN_GLOBAL_H
//median_filter_plugin.h
#include "median_filter_plugin.h"
Median_filter_plugin::Median_filter_plugin()
{
}
Median_filter_plugin::~Median_filter_plugin()
{
}
QString Median_filter_plugin::description()
{
return "This plugin applies median blur filters to any image."
" This plugin's goal is to make us more familiar with the"
" concept of plugins in general.";
}
void Median_filter_plugin::processImage(const cv::Mat &inputImage, cv::Mat &outputImage)
{
cv::medianBlur(inputImage, outputImage, 5);
}
工程文件设置
#-------------------------------------------------
#
# Project created by QtCreator 2017-09-10T12:23:47
#
#-------------------------------------------------
QT -= gui
TARGET = median_filter_plugin
TEMPLATE = lib
#win环境配置
win32:{
CONFIG(debug, debug|release){
DESTDIR += $$PWD/../bin/win64d
LIBS += -L$$PWD/../lib/win64d -lopencv_world480d
}else{
DESTDIR += $$PWD/../bin/win64
LIBS += -L$$PWD/../lib/win64 -lopencv_world480
}
}
INCLUDEPATH += ../Include
CONFIG += plugin
DEFINES += MEDIAN_FILTER_PLUGIN_LIBRARY
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
median_filter_plugin.cpp
HEADERS += \
median_filter_plugin.h \
median_filter_plugin_global.h \
cvplugininterface.h
unix {
target.path = /usr/lib
INSTALLS += target
}
win32: {
include(c:/dev/opencv/opencv.pri)
}
unix: !macx{
CONFIG += link_pkgconfig
PKGCONFIG += opencv
}
unix: macx{
INCLUDEPATH += /usr/local/include
LIBS += -L/usr/local/lib \
-lopencv_world
}
编译生成median_filter_plugin.dll,根据编译模式把动态库放到bin/win64d/filter_plugins或bin/win64/filter_plugins目录下.
然后创建应用程序Plugin_User
打开mainwindow.ui界面,设计相应控件及布局。
把cvplugininterface.h文件添加到项目中,编写mainwindow.h和mainwindow.cpp的相关代码。
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDir>
#include <QFileDialog>
#include <QMessageBox>
#include <QPluginLoader>
#include <QFileInfoList>
#include "opencv2/opencv.hpp"
#include "cvplugininterface.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_inputImgButton_pressed();
void on_helpButton_pressed();
void on_filterButton_pressed();
private:
Ui::MainWindow *ui;
void getPluginsList();
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#define FILTERS_SUBFOLDER "/filter_plugins/"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
getPluginsList();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::getPluginsList()
{
QDir filtersDir(qApp->applicationDirPath() + FILTERS_SUBFOLDER);
QFileInfoList filters = filtersDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files, QDir::Name);
foreach(QFileInfo filter, filters)
{
if(QLibrary::isLibrary(filter.absoluteFilePath()))
{
QPluginLoader pluginLoader(filter.absoluteFilePath(), this);
if(dynamic_cast<CvPluginInterface*>(pluginLoader.instance()))
{
ui->filtersList->addItem(filter.fileName());
pluginLoader.unload(); // we can unload for now
}
else
{
QMessageBox::warning(this, tr("Warning"),
QString(tr("Make sure %1 is a correct plugin for this application<br>"
"and it's not in use by some other application!")).arg(filter.fileName()));
}
}
else
{
QMessageBox::warning(this, tr("Warning"),
QString(tr("Make sure only plugins exist in plugins folder.<br>"
"%1 is not a plugin.")).arg(filter.fileName()));
}
}
if(ui->filtersList->count() <= 0)
{
QMessageBox::critical(this, tr("No Plugins"), tr("This application cannot work without plugins!"
"<br>Make sure that filter_plugins folder exists "
"in the same folder as the application<br>and that "
"there are some filter plugins inside it"));
this->setEnabled(false);
}
}
void MainWindow::on_inputImgButton_pressed()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Input Image"), QDir::currentPath(), tr("Images") + " (*.jpg *.png *.bmp)");
if(QFile::exists(fileName))
{
ui->inputImgEdit->setText(fileName);
}
}
void MainWindow::on_helpButton_pressed()
{
if(ui->filtersList->currentRow() >= 0)
{
QPluginLoader pluginLoader(qApp->applicationDirPath() + FILTERS_SUBFOLDER + ui->filtersList->currentItem()->text());
CvPluginInterface *plugin = dynamic_cast<CvPluginInterface*>(pluginLoader.instance());
if(plugin)
{
QMessageBox::information(this, tr("Plugin Description"), plugin->description());
}
else
{
QMessageBox::warning(this, tr("Warning"), QString(tr("Make sure plugin %1 exists and is usable.")).arg(ui->filtersList->currentItem()->text()));
}
}
else
{
QMessageBox::warning(this, tr("Warning"), QString(tr("First select a filter plugin from the list.")));
}
}
void MainWindow::on_filterButton_pressed()
{
if(ui->filtersList->currentRow() >= 0 && !ui->inputImgEdit->text().isEmpty())
{
QPluginLoader pluginLoader(qApp->applicationDirPath() + FILTERS_SUBFOLDER + ui->filtersList->currentItem()->text());
CvPluginInterface *plugin = dynamic_cast<CvPluginInterface*>(pluginLoader.instance());
if(plugin)
{
if(QFile::exists(ui->inputImgEdit->text()))
{
using namespace cv;
Mat inputImage, outputImage;
inputImage = imread(ui->inputImgEdit->text().toStdString());
plugin->processImage(inputImage, outputImage);
imshow(tr("Filtered Image").toStdString(), outputImage);
}
else
{
QMessageBox::warning(this, tr("Warning"), QString(tr("Make sure %1 exists.")).arg(ui->inputImgEdit->text()));
}
}
else
{
QMessageBox::warning(this, tr("Warning"), QString(tr("Make sure plugin %1 exists and is usable.")).arg(ui->filtersList->currentItem()->text()));
}
}
else
{
QMessageBox::warning(this, tr("Warning"), QString(tr("First select a filter plugin from the list.")));
}
}
工程文件
#-------------------------------------------------
#
# Project created by QtCreator 2017-09-10T13:12:21
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = Plugin_User
TEMPLATE = app
CONFIG += plugin
#win环境配置
win32:{
CONFIG(debug, debug|release){
DESTDIR += $$PWD/../bin/win64d
LIBS += -L$$PWD/../lib/win64d -lopencv_world480d
}else{
DESTDIR += $$PWD/../bin/win64
LIBS += -L$$PWD/../lib/win64 -lopencv_world480
}
}
INCLUDEPATH += ../Include
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h \
cvplugininterface.h
FORMS += \
mainwindow.ui
win32: {
include(c:/dev/opencv/opencv.pri)
}
unix: !macx{
CONFIG += link_pkgconfig
PKGCONFIG += opencv
}
unix: macx{
INCLUDEPATH += /usr/local/include
LIBS += -L/usr/local/lib \
-lopencv_world
}
编译运行