C++ 信号槽弄得一团糟
我正在尝试使用Qt创建一个图像保存应用程序。现在是存根C++ 信号槽弄得一团糟,c++,qt,logic,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_Add
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"
这个问题可能有很多解决方案。我想你应该看看。在简单的情况下,您可以使用布尔变量检查是否可以继续。您还应该考虑在忙于处理图像时要做什么。您可以将请求排队,也可以拒绝它们。此外,还可以实现线程化,以便新线程为新请求提供服务
p.S.信号对我来说更像事件而不是线程。这个问题可能有很多解决方案。我想你应该看看。在简单的情况下,您可以使用布尔变量检查是否可以继续。您还应该考虑在忙于处理图像时要做什么。您可以将请求排队,也可以拒绝它们。此外,还可以实现线程化,以便新线程为新请求提供服务
p.S.信号对我来说更像是事件而不是线程。错误是什么?为什么在末尾有一个
#include
仅供参考,您可以使用
QImage
类,该类包括从QIODevice*
保存和加载,例如QNetworkReply
。在庞大的Qt框架中重新发明轮子是极为罕见的。错误是什么,为什么在最后有一个#include
仅供参考,您可以使用
QImage
类,该类包括从QIODevice*
保存和加载,例如QNetworkReply
。在Qt这个庞大的框架中,很少需要重新设计轮子。您的代码崩溃,因为您读取的内容超出了映像地址集的边界
void ImageSaver::request_Image()
{
QString temp_Address = *(image_Addresses.begin()+index);
...
您在收到每个图像后增加索引,但代码中的任何地方都没有检查索引是否仍然小于image\u Addresses.size(),因此一旦取消引用image\u Addresses.begin()+index for index==image\u Addresses.size(),代码就会崩溃。因为您读取的内容超出了image\u Addresses集的边界
void ImageSaver::request_Image()
{
QString temp_Address = *(image_Addresses.begin()+index);
...
您在收到每个图像后增加索引,但代码中的任何地方都没有检查索引是否仍然小于image\u Addresses.size(),因此一旦取消引用image\u Addresses.begin()+index for index==image\u Addresses.size(),它将崩溃。在哪里?有留言吗?您应该提供一个完整且最少的示例来演示该行为。插槽类似于函数调用,信号只是稍后(在事件循环期间)调用插槽的一种方式。不清楚为什么要将算法拆分为多个插槽。我会尝试将整个过程放在一个插槽中,看看您是否仍然崩溃。根据您当前的示例判断,您正在使用默认方法连接信号和插槽。这是一个直接连接,意味着您实际上只是在进行函数调用。这里没有多线程,除非你在我们看不到的地方做线程。Tom K引用了一个“排队连接”,但它看起来不像是您正在做的事情。请参见:如果它崩溃,请提供回溯。您对信号/插槽的假设是错误的,它们是正常的方法调用,不涉及多线程。@Tom请在编辑中尝试代码。如果你说如何把整个过程放在一个插槽中,我将非常感谢你。我认为你崩溃的原因如下。但是,使用msgbox调试这样的代码是危险的:如果有一个网络操作挂起,并且您打开了一个消息框,msgbox将在exec内部打开一个本地事件循环。如果网络op在对话框打开时返回,则被调用的插槽将更改应用程序的状态。一旦关闭对话框,exec()之后的代码将被执行,并且在exec()之前可能做出的任何假设都不再有效,因为网络op在这两者之间调用了插槽。最好不要在这样的上下文中使用阻塞exec()调用。它在哪里崩溃?有留言吗?您应该提供一个完整且最少的示例来演示该行为。插槽类似于函数调用,信号只是稍后(在事件循环期间)调用插槽的一种方式。不清楚为什么要将算法拆分为多个插槽。我会尝试将整个过程放在一个插槽中,看看您是否仍然崩溃。根据您当前的示例判断,您正在使用默认方法连接信号和插槽。这是一个直接连接,意味着您实际上只是在进行函数调用。这里没有多线程,除非你在我们看不到的地方做线程。Tom K引用了一个“排队连接”,但它看起来不像是您正在做的事情。请参见:如果它崩溃,请提供回溯。您对信号/插槽的假设是错误的,它们是正常的方法调用,不涉及多线程。@Tom请在编辑中尝试代码。如果你说如何把整个过程放在一个插槽中,我将非常感谢你。我认为你崩溃的原因如下。但是,使用msgbox调试这样的代码是危险的:如果有一个网络操作挂起,并且您打开了一个消息框,msgbox将在exec内部打开一个本地事件循环。如果网络op在对话框打开时返回,则被调用的插槽将更改应用程序的状态。一旦关闭对话框,exec()之后的代码将被执行,并且在exec()之前可能做出的任何假设都不再有效,因为网络op在这两者之间调用了插槽。最好不要在这样的上下文中使用blocking exec()调用。#include“main.moc”是在主cpp文件中有信号/插槽时的标准做法。它更多的是关于它在哪里而不是它在什么地方。@AJG85我想我使用了那个QImage类,查看编辑。我的意思是你可以做一些类似于
classimagesaver:publicqimage
的事情,然后在你的版本中使用包含你想要的额外位,并覆盖你想要的任何东西
void ImageSaver::request_Image()
{
QString temp_Address = *(image_Addresses.begin()+index);
...