信号槽搞得一团糟

时间:2011-09-02 17:38:20

标签: c++ qt logic

我正在尝试使用Qt创建一个图像保存应用程序。现在存根

class ImageSaver:public QObject
{
    int index;
    QWebPage * main_Page;
    QNetworkAccessManager * manager;
    QNetworkReply * reply;
    QString file_Name;
    QSet<QString> image_Addresses;
    QString web_Address;
    Q_OBJECT
signals:
    void image_Saved();
public slots:
    void request_Image();
    void on_Finished(bool status);
    void got_Reply(QNetworkReply * reply);
public:
    ImageSaver();
    void start();
};

ImageSaver::ImageSaver()
{
    index = 0;

    manager = new QNetworkAccessManager;

    reply = NULL;

    connect(main_Page,SIGNAL(loadFinished(bool)),this,SLOT(on_Finished(bool)));

    connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(got_Reply(QNetworkReply*)));

    connect(this,SIGNAL(image_Saved()),this,SLOT(request_Image()));
}

void ImageSaver::start()
{
    //loads the url 
    // In the end of the loading it will emit load_Finished(bool)
    // So that signal will execute on_Finished(bool)
}

void ImageSaver::request_Image()
{
    QString temp_Address = *(image_Addresses.begin()+index);

   //makes a request to the server to give the image "temp_Address"
   //When the server gives the reply signal finished(QNetworkReply*) will be emitted
   // this in turn will call the got_Reply(QNetworkReply*)
}

void ImageSaver::on_Finished(bool status)
{
       //collects all the images's url addresses, and pushes them in the list 
        //"image_Addresses"
        //Then emits image_Saved();
        //This signal will wake up the function request_Image()
}

void ImageSaver::got_Reply(QNetworkReply * reply)
{
    //Image is extracted from the reply and got saved in the same name as in the page
    //index got increased;
    //emits the signal image_Saved();
    //This signal will activate the function request_Image()
}

int main(int argc,char * argv[])
{
    QApplication app(argc,argv);
    ImageSaver a;
    a.start();
    return app.exec();
}

#include "main.moc"

简而言之,第一个电话是“开始”。这叫“on_Finished”并且没有问题直到这个。因此,所有图像文件的地址都被推送到列表中。接下来是逐个请求image [i]制作,并且回复图像被保存。这件事反复发生。这里只有我遇到问题。此操作中出现崩溃,尤其是在保存图像时。

我的假设是“signal-slot”与函数调用不同,你或多或少像线程一样,但是在相同的函数(指针)上运行。因此,当一个信号请求画家时,它已经渲染了某些东西,然后就会出现崩溃。

有人可以说崩溃背后的事实以及如何在不崩溃的情况下保存所有图像吗?

修改       嗨,这是完整的代码。运行这个,然后单击连续的消息框

    #include <QApplication>
#include <QDir>
#include <QImage>
#include <QObject>
#include <QMessageBox>
#include <QPainter>
#include <QPixmap>
#include <QSet>
#include <QTimer>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QtNetwork/QNetworkRequest>
#include <QtWebKit/QWebElement>
#include <QtWebKit/QWebFrame>
#include <QtWebKit/QWebPage>
#include <QUrl>

class ImageSaver:public QObject
{
    int index;
    QWebPage * main_Page;
    QNetworkAccessManager * manager;
    QNetworkReply * reply;
    QString file_Name;
    QSet<QString> image_Addresses;
    QString web_Address;
    Q_OBJECT
signals:
    void image_Saved();
public slots:
    void request_Image();
    void on_Finished(bool status);
    void got_Reply(QNetworkReply * reply);
public:
    ImageSaver();
    void start();
protected:
    //void show_Frame(QWebFrame * frame);
};

ImageSaver::ImageSaver()
{
    index = 0;

    this->main_Page = new QWebPage;

    manager = new QNetworkAccessManager;

    reply = NULL;

    connect(main_Page,SIGNAL(loadFinished(bool)),this,SLOT(on_Finished(bool)));

    connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(got_Reply(QNetworkReply*)));

    connect(this,SIGNAL(image_Saved()),this,SLOT(request_Image()));
}

void ImageSaver::start()
{
    web_Address = "yahoo.com";

    QDir dir;

    dir.mkdir(web_Address);

    QUrl url = QUrl::fromUserInput(web_Address);

    main_Page->mainFrame()->load(url);
}

void ImageSaver::request_Image()
{
    QString temp_Address = *(image_Addresses.begin()+index);

        int a = temp_Address.lastIndexOf("/");
        file_Name = temp_Address.mid(a+1);

        //Without the below message box, the program closes shortly
        //This message box is slowing down that effect
        QMessageBox hh;
        hh.setText(file_Name);
        hh.exec();
        QNetworkRequest request= QNetworkRequest(QUrl(temp_Address));
        request.setRawHeader("img","src");
        manager->get(request);
}

void ImageSaver::on_Finished(bool status)
{
    if(status)
    {
        QMessageBox mm;
        mm.setText("Finished");
        mm.exec();

        QWebElementCollection temp_Collection= main_Page->mainFrame()->findAllElements("*");

        for(int i=0;i<temp_Collection.count();++i)
        {
            QWebElement temp_Element = temp_Collection[i];
            if(temp_Element.tagName().contains("img",Qt::CaseInsensitive) && temp_Element.attributeNames().contains("src",Qt::CaseInsensitive))
            {
                QString image_Web_Address = temp_Element.attribute("src");
                if(!image_Addresses.contains(image_Web_Address))
                    image_Addresses.insert(image_Web_Address);
            }
        }
        emit image_Saved();
        QMessageBox kk;
        kk.setText("Image is going to be saved");
        kk.exec();
    }

    else
    {
        QMessageBox mm;
        mm.setText("Not ready");
        mm.exec();
    }

    QMessageBox mm;
    mm.setText("Getting out of finished");
    mm.exec();
}

void ImageSaver::got_Reply(QNetworkReply * reply)
{
    QImage image;
    if(image.load(static_cast<QIODevice *>(reply),0))
        image.save(web_Address+QDir::separator()+file_Name,0);

    ++index;
    emit image_Saved();
}

/*
void ImageSaver::show_Frame(QWebFrame * temp_Frame)
{
    QImage image(temp_Frame->contentsSize(),QImage::Format_ARGB32_Premultiplied);
    image.fill(Qt::transparent);

    QPainter painter(&image);
    painter.setRenderHint(QPainter::Antialiasing,true);
    painter.setRenderHint(QPainter::TextAntialiasing,true);
    painter.setRenderHint(QPainter::SmoothPixmapTransform,true);

    temp_Frame->documentElement().render(&painter);

    painter.end();

    foreach(QWebFrame * temp_Frame0,temp_Frame->childFrames())
        show_Frame(temp_Frame0);
}
*/

int main(int argc,char * argv[])
{
    QApplication app(argc,argv);

    ImageSaver a;
    a.start();

    return app.exec();
}

#include "main.moc"

这是专业档案

QT += webkit network

SOURCES += \
    main.cpp

3 个答案:

答案 0 :(得分:1)

这个问题可能有很多解决方案。我想你应该看看The State Machine Framework。在简单的情况下,你可以使用布尔变量来检查你是否可以继续。您还应该考虑在忙于处理图像时该怎么做。您可以排队请求或只是拒绝它们。您还可以实现线程,以便新线程提供新请求。

P.S。信号更像是事件而非线程给我。

答案 1 :(得分:1)

错误是什么,为什么最后有#include

仅供参考,您可以使用QImage课程,其中包括从QIODevice*保存和加载,例如QNetworkReply。在Qt的庞大框架中重新发明轮子是非常罕见的。

答案 2 :(得分:1)

您的代码崩溃是因为您超出了image_Addresses设置的边界。

void ImageSaver::request_Image()
{
    QString temp_Address = *(image_Addresses.begin()+index);
    ...

在收到每个图像后递增索引,但是代码中的任何地方都没有检查索引是否仍然小于image_Addresses.size(),因此一旦取消引用image_Addresses.begin()+ index for index ==它就会崩溃image_Addresses.size()。