一、直接添加图片

1.参考Qt的帮助文档,可支持的类型,即可以直接读取并显示的格式有BMPGIFJPGJPEGPNGTIFFPBMPGMPPMXBMXPM

2.显示图片步骤:

先打开一个图像;将图像文件加载进QImage对象中;再用QPixmap对象获得图像;最后用QLabel选择一个QPixmap图像对象显示。

这是要插入的图片:

 

 

代码如下(在这之前需要在界面里添加一个Qlabel控件,对象名为label


QString filename(“F:\\Study\\junior\\Qt\\door\\1.jpg”);
        QImage* img=new QImage;
        if(! ( img->load(filename) ) ) //加载图像
        {
            QMessageBox::information(this,
                                     tr("打开图像失败"),
                                     tr("打开图像失败!"));
            delete img;
            return;
        }
        ui->label->setPixmap(QPixmap::fromImage(*img));




 

显示的效果如图所示:

 

很明显只能显示图片的一小部分。

 

二、修改label的大小

Qlable设置大小的函数有resize()

所以在添加图片前加上这行代码可以先调整好label的大小。
    

ui->label->resize(img->width(),img->height());



 

显示结果:

    

好像图片过大了,label的大小已经超过了窗口的大小,还是不能完全显示,所以还是要找其他合适的解决方法。

 

 

我想label的大小范围是固定的,所以应该按比例缩放图片的大小,经过查阅资料有如下的方法:

首先用


label->setGeometry(0,0,400,300);//前两个参数表示label左上角位置后面分别是宽和高



函数设置lable的位置和大小,接着根据图片的大小缩放到合适的大小显示

图片缩放的相关函数是


img->scaled(width,height,Qt::KeepAspectRatio);



该函数前两个参数表示的是缩放之后图片的宽高,而第三个参数的作用是选择模式是否保持长宽比,相关的参数可以在qt的帮助文档中查看。接下来看使用了缩放之后的效果:

 

的确能够把画面全部显示出来了。下面是mainwindows的构建代码:

{
    ui->setupUi(this);
    QString StrWidth,StrHeigth;
    QString filename="F:\\Study\\junior\\Qt\\door\\1.jpg";
            QImage* img=new QImage,* scaledimg=new QImage;//分别保存原图和缩放之后的图片
            if(! ( img->load(filename) ) ) //加载图像
            {
                QMessageBox::information(this,
                                         tr("打开图像失败"),
                                         tr("打开图像失败!"));
                delete img;
                return;
            }
            int Owidth=img->width(),Oheight=img->height();
            int Fwidth,Fheight;       //缩放后的图片大小
            ui->label->setGeometry(0,0,400,300);
            int Mul;            //记录图片与label大小的比例,用于缩放图片
            if(Owidth/400>=Oheight/300)
                Mul=Owidth/400;
            else
                Mul=Oheight/300;
            Fwidth=Owidth/Mul;
            Fheight=Oheight/Mul;
            *scaledimg=img->scaled(Fwidth,Fheight,Qt::KeepAspectRatio);
            ui->label_text->setText(QString("width: ")+StrWidth.setNum(Fwidth)
                                    +QString("\nheight: ")+StrHeigth.setNum(Fheight));
            ui->label->setPixmap(QPixmap::fromImage(*scaledimg));
}


 


2016.9.8

目标:在Qt的实现通过按钮控制在窗口中查看mjpeg-streamer运行时本地显示的摄像头画面。

 

思路:原来在html中只要直接插入图片标签,对应的地址"/?action=stream" ,在打开mjpeg-streamer的时候,就能在网页中显示对应的画面,所以我想在qt的label中将该地址引用为图片是否就可以直接看到画面,接下来就直接在上次的基础上修改代码试试。

 

事实证明我想的太简单了,p_w_picpath.load()只能打开本地的图片,对于网上的图片只能先保存为本地的图片然后再在控件里显示,所以接下来要解决的是如何获取网络上的图片。
查阅了资料之后发现就下载而言,Qt5的QtNetwork模块为我们提供了相当便利的接口,下面我就直接给出源码,相关的函数用法都可以参考帮助文档:

 


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QNetworkAccessManager *manager;
    manager = new QNetworkAccessManager(this);
    connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(slot_replyFinished(QNetworkReply*)));
    QNetworkRequest request;
    request.setUrl(QUrl("http://www.bz55.com/uploads/allimg/150707/139-150FG51639-50.jpg"));
    manager->get(request);
}
MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::slot_replyFinished(QNetworkReply* reply)
{
 QPixmap pix;
 QByteArray data = reply->readAll();
 pix.loadFromData(data, "JPG");
 pix.save("/root/Qt/program/netpicture/tmp1.jpg", "JPG", 100);
 ui->textEdit->resize(500,500);
 ui->textEdit->append("<img src=/root/Qt/program/netpicture/tmp1.jpg width=400 hight=300>");
}




 

要注意的是在mainwindow.h里要写上


void MainWindow::slot_replyFinished(QNetworkReply* reply)




这个槽函数的声明并且加上


#include <QNetworkReply>
#include <QNetworkAccessManager>
#include <QNetworkRequest>




这几个头文件,在.pro文件中加上

QT+= network

这一行,接下来就可以编译运行了。

 

代码中链接对应的图片就显示在了textEdit控件中了,当然在

“/root/Qt/program/netpicture”目录下也成功的下载了这个图片(不然也无法显示)。

 

好了既然能显示网络上的图片了那就简单的修改一下源码试试在label中显示mjpeg-streamer生成的“http://localhost:8080/?action=stream图片,如果能够显示的话只要加上循环控制应该就可以显示视频了。

 

 

2016.9.10

coding...

 

2016.9.11

思考:经过一天的修改折腾想要的功能基本实现了,其中和预想的不一样的是要读取mjpg-streamer打开后对应的图片链接是http://localhost:8080/?action=snapshot

前面那个链接对应的是一个流,这才是一个静态图片。

还有一个难点是在执行了manager->get(request);并不能立即调用槽函数,所以紧接着执行在label中显示图片的语句的话会出现图片打开失败的错误提示,我想应该是向链接发出访问请求是需要一小段时间的虽然很短但还是比两行命令之间的时间差要长很多,所以我在这两行命令之间添加了延时代码,要注意的是不能调用系统的sleep()函数,因为这样你的控件就会失去响应,当然label上的画面也就不会刷新了。

接下来就直接贴出代码,这里我也将获取到的画面自动缩放到640*480大小:


QString PU="http://192.168.253.3:8080/?action=snapshot";
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    SetWindow();
}
MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::PicConnect(QString PicUrl)
{       //connect to picture
    QNetworkAccessManager *manager;
    manager = new QNetworkAccessManager(this);
    connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(slot_replyFinished(QNetworkReply*)));
    QNetworkRequest request;
    request.setUrl(QUrl(PicUrl));
    manager->get(request);
}
 
void MainWindow::slot_replyFinished(QNetworkReply* reply)
{       //save the picture
 QPixmap pix;
 QByteArray data = reply->readAll();
 pix.loadFromData(data, "JPG");
 pix.save("/root/Qt/program/netpicture/tmp1.jpg", "JPG", 100);
}
void MainWindow::SetWindow()
{       //set the window with one label and pushButton
    this->resize(800,600);
    ui->PicLabel->setGeometry(10,10,640,480);
    ui->PicLabel->setText("PICTURE......");
    ui->PicButton->setGeometry(300,500,30,15);
    isPicOnLabel=false;
    ui->PicButton->setText("Show");
}
void MainWindow::on_PicButton_clicked()
{
    if(isPicOnLabel==false)
    {
        ShowPic();
    }
    else
    {
        StopPic();
    }
}
void MainWindow::ShowPic()
{
    isPicOnLabel=true;
    ui->PicButton->setText("stop");
    while(1)
    {
            if(isPicOnLabel==false)
                break;
            PicConnect(PU);
            QEventLoop eventloop;
            QTimer::singleShot(10, &eventloop, SLOT(quit()));
//等待10*0.001秒
            eventloop.exec();
            if(! ( img->load("/root/Qt/program/netpicture/tmp1.jpg") ) ) //加载图像
            {
                QMessageBox::information(this,
                                         tr("打开图像失败"),
                                         tr("打开图像失败!"));
                delete img;
                return;
            }
            *scaledimg=img->scaled(640,480,Qt::KeepAspectRatio);
            ui->PicLabel->setPixmap(QPixmap::fromImage(*scaledimg));
    }
}
void MainWindow::StopPic()
{
    isPicOnLabel=false;
    ui->PicButton->setText("show");
}




 

其中mainwindow.h.需要包含的头文件以及需要添加的成员变量:


#include <QMainWindow>
#include <QNetworkReply>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include<QMessageBox>
#include<QTimer>
 
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    bool isPicOnLabel;
    explicit MainWindow(QWidget *parent = 0);    
    QImage* img=new QImage,* scaledimg=new QImage;
    ~MainWindow();
public slots:
    void slot_replyFinished(QNetworkReply* reply);
private slots:
    void on_PicButton_clicked();
private:
    Ui::MainWindow *ui;
    void PicConnect(QString p);
    void SetWindow();
    void ShowPic();
    void StopPic();
};




最后可以看一下程序运行的效果:

这是在按下“show”按钮之前

 

 

按下之后:

 

这时候能够看到连续的画面,帧数可以通过


QTimer::singleShot(10, &eventloop, SLOT(quit()));




的第一个参数来控制,第一个参数的单位是毫秒。

 

为了添加拍照功能,于是加上了一个savebutton,槽函数代码如下:


void MainWindow::on_SaveButton_clicked()
{
    if(isPicOnLabel==false)
    {
        QMessageBox::information(this,
                                 tr("ERROR!"),
                                 tr("NO PICTURE !"));
    }
    else
    {
        QString str_time,path;
        QDateTime time = QDateTime::currentDateTime();
        str_time = time.toString("yyyy-MM-dd_hh-mm-ss");
        path="../netpicture/photo/"+str_time+".jpg";
        QPixmap::fromImage(*img).save(path, "JPG", 100);
        QMessageBox::information(this,
                                 tr("save"),
                                 tr("PICTURE has been saved to folder 'photo!'"));
 
    }
}