我之前写过一篇QT5.9.1与opencv3.3读取图片,但是我们对于这种读取操作不是很满意,一般我们打开文件都是有一个对话框,并且图片是在一个小窗口中显示的。
关于如何新建一个项目,请看上一篇。
我们想要有一个小窗口去显示图片,那我们就要用到QMdiArea
。从左边拖一个MDI Area
到窗口中,点击MainWindow
然后选择栅格布局。
我们看到MDI Area
的边界和MainWindow
的边界有一些距离,这很难看,所以我们要调整这个间隔。选中centralWidget
,然后修改LayoutLeftMargin
、LayoutTopMargin
、 LayoutRightMargin
、LayoutBottomMargin
都设置为0。
接着我们要对小窗口进行设计,由于我们要显示一个图片,最简单的做法就是新建一个ChildWindow
类,让这类继承QLabel
类就可以了。
我们现在来处理ChildWindow
类,其中用到了我们之前写的一个转换函数QT中的QImage、QPixmap和opencv 中的mat转化,我这里新建一个头文件qimageandmat.h
,将上面文章中给的代码copy过去。
//childwindow.cpp
//读取图片
bool ChildWindow::loadFile(const QString &fileName)
{
//读取一幅图片,这里我们要将QString转换为String使用toLocal8Bit()函数,避免乱码问题
cv::Mat image = cv::imread(fileName.toLocal8Bit().data());
if(!image.data)
{
QMessageBox::warning(this, tr("CVS"),
tr("Cannot read file %1\n")
.arg(fileName));//添加头文件#include <QMessageBox>
return false;
}
else
{
//将Mat转化为QPixmap,使用了我们写的一个函数
QPixmap img = CVS::cvMatToQPixmap(image);
//显示在label中
this->setPixmap(img);
//改变label的大小用于自适应图像大小
this->setScaledContents(true);
}
setCurrentFile(fileName);//设置小窗口的标题
return true;
}
接着编写setCurrentFile
//childwindow.cpp
//设置小窗口的标题
void ChildWindow::setCurrentFile(const QString &fileName)
{
curFile = QFileInfo(fileName).canonicalFilePath();//获取文件绝对路径,添加头文件#include <QFileInfo>
setWindowTitle(userFriendlyCurrentFile() + "[*]");
}
QString ChildWindow::userFriendlyCurrentFile()
{
return strippedName(curFile);
}
QString ChildWindow::strippedName(const QString &fullFileName)
{
return QFileInfo(fullFileName).fileName();
}
最后ChildWindow
的头文件片段
#include <QLabel>
#include <opencv2/opencv.hpp>
#include <QImage>
#include "qimageandmat.h"
class ChildWindow : public QLabel
{
Q_OBJECT
public:
ChildWindow();
bool loadFile(const QString &fileName);
QString userFriendlyCurrentFile();
QString currentFile() { return curFile; }
private:
void setCurrentFile(const QString &fileName);
QString strippedName(const QString &fullFileName);
QString curFile;
};
接着我们处理MainWindow
原来的mainwindow
中的actionOpenFile
槽函数这个时候变为
//mainwindow.cpp
void MainWindow::on_actionOpenFile_triggered()
{
fileName = QFileDialog::getOpenFileName(this); //文件打开窗口,添加头文件#include <QFileDialog>
if (!fileName.isEmpty())
openFile(fileName);//打开文件
}
接着编写openFile
函数
//mainwindow.cpp
//打开文件窗口
bool MainWindow::openFile(const QString &fileName)
{
const bool succeeded = loadFile(fileName); //读取文件
return succeeded;
}
接着编写loadFile
文件
//mainwindow.cpp
//读取图片
bool MainWindow::loadFile(const QString &fileName)
{
ChildWindow *child = createChildWindow(); //创建一个子窗口
const bool succeeded = child->loadFile(fileName);//子窗口读取图片
if (succeeded) //如果读取成功,显示图片;否则,关闭
child->show();
else
child->close();
return succeeded;
}
接着编写createChildWindow
函数
//mainwindow.cpp
//创建子窗口
ChildWindow *MainWindow::createChildWindow()
{
ChildWindow *child = new ChildWindow;
ui->mdiArea->addSubWindow(child);
return child;
}
最后MainWindow
的头文件片段
#include <QMainWindow>
#include <QMdiSubWindow>
#include "childwindow.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
bool openFile(const QString &fileName);
~MainWindow();
private slots:
void on_actionOpenFile_triggered();
private:
bool loadFile(const QString &fileName);
ChildWindow *createChildWindow();
QMdiArea *mdiArea;
QString fileName;
Ui::MainWindow *ui;
};
接着运行
ok!^_^