Сигнал-слот делает беспорядок - PullRequest
0 голосов
/ 02 сентября 2011

Я пытаюсь создать приложение для сохранения изображений, используя 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», и до этого нет проблем. Таким образом, адреса всех файлов изображений были помещены в список. Затем выполняется один за другим запрос изображения [i], и ответное изображение сохраняется. Это происходит неоднократно. Вот только у меня проблема. В этой операции возникают сбои, особенно при сохранении изображения.

Мое предположение, что "сигнал-слот" не похож на вызов функции, вы более или менее похожи на поток, но работают с той же функцией (указателем). Поэтому, когда один сигнал запрашивает маляра, который уже что-то рендерит, появится сбой.

Кто-нибудь может сказать, что стоит за сбоем и как сохранить все изображения без сбоев?

EDIT: Привет, это полный код Запустите этот и щелкните по окнам сообщений непрерывно

    #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 ]

1 голос
/ 02 сентября 2011

В чем ошибка и почему у вас есть #include в конце?

К вашему сведению, вы можете использовать класс QImage, который включает сохранение и загрузку из QIODevice*, например, QNetworkReply. Крайне редко нужно изобретать велосипед в массивной структуре, которая является Qt.

1 голос
/ 03 сентября 2011

Ваш код падает, потому что вы читаете за пределами набора image_Addresses.

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

Вы увеличиваете индекс после каждого полученного изображения, но нигде в коде нет проверки, является ли индекс все еще меньше, чем image_Addresses.size (), поэтому он аварийно завершает работу после разыменования image_Addresses.begin () + index для index == image_Addresses.size ().

1 голос
/ 02 сентября 2011

Может быть много решений этой проблемы.Я думаю, что вы должны взглянуть на State Machine Framework .В простых ситуациях вы можете просто использовать логическую переменную, чтобы проверить, можете ли вы продолжать.Вы также должны подумать, что делать, когда вы заняты обработкой изображения.Вы можете поставить запрос в очередь или просто отклонить его.Также вы можете реализовать многопоточность, чтобы новые запросы обслуживались новыми потоками.

PS Сигналы для меня больше похожи на события, чем на потоки.

...