c++ - 信号槽弄得一团糟

标签 c++ qt logic

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

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] 的一个一个请求,并保存回复图像。这件事反复发生。在这里只有我遇到问题。在此操作中出现崩溃,尤其是在保存图像时。

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

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

编辑: 你好,这是完整的代码。运行这个,连续点击消息框

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

这是pro文件

QT += webkit network

SOURCES += \
    main.cpp

最佳答案

您的代码崩溃是因为您读取了超出 image_Addresses 集边界的内容。

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

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

关于c++ - 信号槽弄得一团糟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7287233/

相关文章:

c - 选择排序字符 C

c++ - C++中的动态内存点

c++ - 编写管理程序?

c++ - 在缓冲区/数组中使用 Color 结构

java - 未使用 QAndroidJniObject 调用的三个函数之一

qt - 是否有完整的* .pro文件语法页面?

c++ - 链表中的运算符重载 <<

javascript - 动态创建 QML ObjectModel 元素

math - 序言中的幂函数

programming-languages - 关于高阶逻辑推理形式主义表达能力的问题