qt - QNetworkAccessManager 未使用此代码发出完成信号

标签 qt

所以我之前一直在浏览之前关于此问题的问题,但我找不到适合我的代码的解决方案。

cpp file of dialog
------------------------------------------------
#include "everesult.h"
#include "ui_everesult.h"

everesult::everesult(QWidget *parent) :
    QDialog(parent),
    ui1(new Ui::everesult)
{
    ui1->setupUi(this);
}

everesult::~everesult()
{
    delete ui1;
}

void everesult::setmodel(QStandardItemModel *model)
{
    ui1->listView->setModel(model);
}

void everesult::on_buttonBox_clicked(QAbstractButton *button)
{
    EveReprocess M_;
    QModelIndex Selectedindex = ui1->listView->currentIndex();
    QModelIndex StationIdsindex = ui1->listView->model()->index(0, 1);

    int typeID = 0;
    int stationID = 0;
    stationID = ui1->listView->model()->data(StationIdsindex, Qt::DisplayRole).toInt();
    typeID = ui1->listView->model()->data(Selectedindex, Qt::DisplayRole).toInt();
    M_.GetMaterials(typeID, stationID);
}
--------------------------------------------------
Getmaterial and replyFinished from main window.
--------------------------------------------------

void EveReprocess::GetMaterials(int typeId, int stationid)
{
    //get typeid from material list
    this->modelMaterial = new QSqlQueryModel();
    modelMaterial->setQuery(QString("SELECT tm.quantity, tm.materialTypeID, t.typeName FROM invTypeMaterials tm INNER JOIN invTypes t ON t.TypeID = tm.materialTypeId WHERE tm.TypeID=%1 ").arg(typeId));
    if (!modelMaterial->query().exec())
        qDebug() << modelMaterial->query().lastError();

    //Set eve Central Url with typeids
    QUrl url = QUrl("http://api.eve-central.com/api/marketstat?");
    QUrlQuery q;
    int numRows = modelMaterial->rowCount();
    for (int row = 0; row < numRows; ++row)
    {
        QModelIndex index = modelMaterial->index(row, 1);
        q.addQueryItem( QString("typeid"), QString::number(modelMaterial->data(index, Qt::DisplayRole).toInt()));
    }
    q.addQueryItem( QString("usesystem"), QString::number(stationid));

    //set created url and connect
    url.setQuery(q);
    qDebug() << url;    
    manager = new QNetworkAccessManager(this);
    connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply *)));
    manager->get(QNetworkRequest(url) );
}

void EveReprocess::replyFinished(QNetworkReply *reply)
{
    qDebug() << "replyFinished called";
    if ( reply->error() != QNetworkReply::NoError ) {
        qDebug() << "Request failed, " << reply->errorString();
        emit replyFinished(false);
        return;
    }
    qDebug() << "Request succeeded";
    //process with xmlreader and get values
    processSearchResult( reply);
}

一些代码在这里,我认为它应该在这里的某个地方,因为其余的工作正常。

在我使用对话框让用户从列表中选择一个整数后,出现了此问题。

下面是调用我为此创建的对话框的函数。抱歉,代码格式将在运行后清理

void EveReprocess::Search_TypeId(QString ItemName, QString SystemName)
{    
    QList<int> TypeIdList;
    QList<int> StationIdList;
    modelIds = new QStandardItemModel(10,2,this);
    if !(db.isOpen()) return;

    this->queryItem = new QSqlQuery;
    queryItem->prepare("SELECT typeID FROM invTypes WHERE invTypes.typeName LIKE ? AND invTypes.groupID NOT IN (268,269,270)AND published= 1");
    ItemName.prepend("%");
    ItemName.append("%");
    queryItem->bindValue(0, ItemName);

    this->queryStation = new QSqlQuery;
    queryStation->prepare("SELECT solarSystemID FROM mapSolarSystems WHERE mapSolarSystems.solarSystemName LIKE ?");
    SystemName.prepend("%");
    SystemName.append("%");
    queryStation->bindValue(0, SystemName);

    if(!queryStation->exec() || !queryItem->exec() )
    {
        qDebug() << queryItem->lastError().text();
        qDebug() << queryItem->lastQuery();
        qDebug() << queryStation->lastError().text();
        qDebug() << queryStation->lastQuery();
    }

    while( queryStation->next())
    {
        StationIdList.append(queryStation->value(0).toInt());
    }

    while(queryItem->next())
    {
        TypeIdList.append(queryItem->value(0).toInt());
    }


    for (int i = 0; i < StationIdList.count(); ++i)
    {
        modelIds->setItem(i,1,new QStandardItem(QString::number(StationIdList.at(i))));
    }

    for (int i = 0; i < TypeIdList.count(); ++i)
    {
        modelIds->setItem(i,0,new QStandardItem(QString::number(TypeIdList.at(i))));
    }


    //
    everesult Dialog;
    Dialog.setmodel(modelIds);
    Dialog.exec();
}

最佳答案

在继续之前,您的某些代码允许 SQL injections 。即使它不是安全漏洞,它仍然会导致错误。您应该使用绑定(bind),而不是在 SQL 查询中使用字符串替换。

您的问题在这里:

everesult Dialog;
Dialog.setmodel(modelIds);
Dialog.exec();

exec() 是一个阻塞函数 - 它会阻塞主事件循环,直到对话框关闭。因此,来自线程网络访问管理器的信号永远不会传递到您的对象。

您应该异步显示对话框,如下所示:

everesult * dialog = new everesult;
dialog->setModel(modelIds);
dialog->show();
connect(dialog, SIGNAL(accepted()), dialog, SLOT(deleteLater());
connect(dialog, SIGNAL(rejected()), dialog, SLOT(deleteLater());

请注意,类型名称以小写开头而变量名称以大写开头会产生误导。 Qt 的约定恰恰相反,保留它很有用,除非您有充分的理由不这样做。

SQL 查询中的 DO 参数绑定(bind)

QSqlQuery query("SELECT .. WHERE tm.TypeID=:typeid");
query.bindValue(":typeid", typeId);
QSqlQueryModel model;
model.setQuery(query);

不要在 SQL 查询中进行字符串替换

setQuery(QString("SELECT ... WHERE tm.TypeID=%1 ").arg(typeId));

关于qt - QNetworkAccessManager 未使用此代码发出完成信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18644073/

相关文章:

qt - 如何通过给定的一组位置向量获得绕 2 个轴的旋转速度

java - 在 Qt 中调用 java 函数以获得运行时权限

linux - 在 Debian Wheezy 上升级 GLIBC

c++ - 使用 Qt 修改任何复选框状态时执行操作

android - Android 上的 MouseArea 虚拟双击

macos - 在 mac 上使用 bundle 外的共享库安装应用程序

qt - 从哪里获得 MongoDB Qt 驱动程序

qt - 如何删除 qmake 中的更改默认 CFLAGS?

qt - 如何在 QML 中录制音频并播放?

c++ - 递归循环遍历目录并收集所有xml文件