C++ QNetworkRequest(HTTP GET)不';在重构成独立类之后,t fire

C++ QNetworkRequest(HTTP GET)不';在重构成独立类之后,t fire,c++,qt,qtnetwork,C++,Qt,Qtnetwork,我最近开始了一个乏味的过程,制作了一个大型的单片音频播放器应用程序,我大约在2个月前编写了这个应用程序 这一过程进行得相当顺利,尽管其中一种方法(ScrobbleMedia——可以预见,它足以使HTTP请求将播放曲目的信息提交给last.fm)似乎不再发出网络请求 但是,将传递给QNetworkAccessManager实例/QNetworkRequest的QUrl对象正在正确生成 为便于比较,可在上找到该代码的功能Mercurial修订版 重构后,ScrobbleMedia方法当前的外观如下:

我最近开始了一个乏味的过程,制作了一个大型的单片音频播放器应用程序,我大约在2个月前编写了这个应用程序

这一过程进行得相当顺利,尽管其中一种方法(ScrobbleMedia——可以预见,它足以使HTTP请求将播放曲目的信息提交给last.fm)似乎不再发出网络请求

但是,将传递给QNetworkAccessManager实例/QNetworkRequest的QUrl对象正在正确生成

为便于比较,可在上找到该代码的功能Mercurial修订版

重构后,ScrobbleMedia方法当前的外观如下:

#include "scrobblemedia.h"

#include <QDebug>
#include <cstdio>

ScrobbleMedia::ScrobbleMedia(QString asUsername, QString asPassword,
                         QString asArtist, QString asTrack, QString asAlbum)
{

    QString KEndPointURL = "http://lastfmstats.livefrombmore.com/universalscrobbler/scrobble.php";
    QUrl iScrobbleEndPoint(KEndPointURL);

      QNetworkAccessManager *iScrobbleDispatcher = new QNetworkAccessManager(this);


iScrobbleEndPoint.addQueryItem("submissionType","track");
iScrobbleEndPoint.addQueryItem("username", asUsername);
iScrobbleEndPoint.addQueryItem("password", asPassword);
iScrobbleEndPoint.addQueryItem("artist", asArtist);
iScrobbleEndPoint.addQueryItem("track", asTrack);
iScrobbleEndPoint.addQueryItem("album", asAlbum);
iScrobbleEndPoint.addQueryItem("number","1");
iScrobbleEndPoint.addQueryItem("duration","200");

iScrobbleDispatcher->get(QNetworkRequest(iScrobbleEndPoint));
connect(iScrobbleDispatcher, SIGNAL(finished(QNetworkReply*)),
 SLOT(replyFinished(QNetworkReply*)));

// QString Outside = iScrobbleEndPoint.toEncoded();

qDebug()  << "Received: " + 
  asUsername + " " + 
   asPassword + " " + 
    asArtist + " " +
     asTrack + " " + 
      asAlbum;

qDebug() << iScrobbleEndPoint.toString();

}

ScrobbleMedia::~ScrobbleMedia() {

}
#包括“scrobblemedia.h”
#包括
#包括
ScrobbleMedia::ScrobbleMedia(QString asUsername,QString asPassword,
Astarist,asTrack,asAlbum)
{
QString KEndPointURL=”http://lastfmstats.livefrombmore.com/universalscrobbler/scrobble.php";
QUrl-iScrobbleEndPoint(KEndPointURL);
QNetworkAccessManager*iScrobbleDispatcher=新的QNetworkAccessManager(此);
iScrobbleEndPoint.addQueryItem(“提交类型”、“跟踪”);
iScrobbleEndPoint.addQueryItem(“用户名”,asUsername);
iScrobbleEndPoint.addQueryItem(“密码”,asPassword);
iScrobbleEndPoint.addQueryItem(“艺术家”,即艺术家);
iScrobbleEndPoint.addQueryItem(“track”,asTrack);
iScrobbleEndPoint.addQueryItem(“相册”,asAlbum);
iScrobbleEndPoint.addQueryItem(“数字”、“1”);
iScrobbleEndPoint.addQueryItem(“持续时间”,“200”);
iScrobbleDispatcher->get(QNetworkRequest(iScrobbleEndPoint));
连接(iScrobbleDispatcher,信号)(完成(QNetworkReply*)),
插槽(replyFinished(QNetworkReply*));
//QString Outside=iScrobbleEndPoint.toEncoded();

qDebug()在阅读了大量不同的信息源(其中大部分是相互矛盾的)之后,我发现以下结果是一个可行的解决方案——尽管调试输出中存在一个表面问题,似乎不会影响操作(
Object::connect:没有这样的信号QNetworkReplyImpl::finished(QNetworkReply*))在../AudioPlayer/scrobblemedia.cpp:29
)中:

scrobblemedia.cpp
中:

#include "scrobblemedia.h"

#include <QDebug>
#include <cstdio>

ScrobbleMedia::ScrobbleMedia(QString asUsername, QString asPassword,
                             QString asArtist, QString asTrack, QString asAlbum)
{

    QByteArray iDataSink;
    QEventLoop iLoop;

    QString KEndPointURL = "http://lastfmstats.livefrombmore.com/universalscrobbler/scrobble.php";
    QUrl iScrobbleEndPoint(KEndPointURL);

    iScrobbleEndPoint.addQueryItem("submissionType","track");
    iScrobbleEndPoint.addQueryItem("username", asUsername);
    iScrobbleEndPoint.addQueryItem("password", asPassword);
    iScrobbleEndPoint.addQueryItem("artist", asArtist);
    iScrobbleEndPoint.addQueryItem("track", asTrack);
    iScrobbleEndPoint.addQueryItem("album", asAlbum);
    iScrobbleEndPoint.addQueryItem("number","1");
    iScrobbleEndPoint.addQueryItem("duration","200");

    QNetworkAccessManager iScrobbleDispatcher;
    QNetworkRequest iScrobbleRequest(iScrobbleEndPoint);
    QNetworkReply *iScrobbleReply = iScrobbleDispatcher.get(iScrobbleRequest);

    QObject::connect(iScrobbleReply, SIGNAL(finished(QNetworkReply*)), &iLoop,
     SLOT(quit()));

    iDataSink = iScrobbleReply->readAll();

    qDebug()  << "Received: " + asUsername + " " + asPassword + " " + asArtist + " " + asTrack + " " + asAlbum;

    qDebug() << iScrobbleEndPoint.toString();

    iLoop.exec();
}

ScrobbleMedia::~ScrobbleMedia() {

}

void ScrobbleMedia::replyFinished(QNetworkReply*) {

}

void ScrobbleMedia::reallyDone() {

    qDebug() << "We've probably successfully Scrobbled...";
}
谢谢大家的帮助


希望这段代码将来能成为其他人的有用模板。

两个问题:为什么Q_OBJECT宏后面有分号?为什么没有replyFinished()标题中声明的插槽?如果您在Windows上,您可能希望使用CONFIG+=console qmake选项重新编译您的项目,因为它将允许您查看运行时Qt警告(如“无此类插槽”消息)。谢谢,Sergey。我今晚将更新代码,并让您知道发生了什么(因为我目前手头没有Qt工具链).分号是习惯性的,我不确定它是否会起作用。@Tyson,你也应该提供你的Qt SDK版本。QNAM和finished()有很多问题Qt旧版本的信号。@Tyson,至于分号,将它放在只扩展到上帝的宏之后尤其危险,巨魔知道什么。但即使不考虑这一点,在函数体之外的任何地方使用额外的分号本身都是非常危险的,它可能会在许多编译器上中断。@Tyson,未定义的引用ce只是意味着您已经在类中声明了它,但还没有在实现文件中定义它。(比如,忘记添加
ScrobbleMedia::
)reallyDone()的确切位置插槽被调用?我在代码中没有看到它。为什么需要事件循环?如果它不是多线程应用程序,那么使用单独的事件循环至少是不必要的,甚至可能是危险的。最后,你的问题不是“装饰性的”。你得到它是因为你试图连接到一个不存在的信号
finished(QNetworkReply*)
在iScrobbleReply中。它只有finished()信号,没有参数。是QNetworkAccessManager具有finished()插槽,带有QNetworkReply*参数。这就是为什么永远不会调用quit()方法的原因。reallyDone()没有在任何地方调用它-它只是以前尝试使事情正常运行时留下的。事件循环的想法是在中提出的,在我的案例中似乎有效。考虑到这一点,我删除了
reallyDone()
,并定义了
void finished(QNetworkReply*)
,除了提供它的存根实现之外。代码本身仍然可以工作(我可以在Wireshark中看到HTTP请求),但是干净地处理“无底插槽”问题是以后的事情,因为我必须马上离开去某个地方。更新:我更新了
connect()
调用
QObject::connect(iScrobbleReply,SIGNAL(finished()),&iLoop,SLOT(quit());
,看起来不仅应用程序仍然工作,而且SLOT错误不再出现。
#include "scrobblemedia.h"

#include <QDebug>
#include <cstdio>

ScrobbleMedia::ScrobbleMedia(QString asUsername, QString asPassword,
                             QString asArtist, QString asTrack, QString asAlbum)
{

    QByteArray iDataSink;
    QEventLoop iLoop;

    QString KEndPointURL = "http://lastfmstats.livefrombmore.com/universalscrobbler/scrobble.php";
    QUrl iScrobbleEndPoint(KEndPointURL);

    iScrobbleEndPoint.addQueryItem("submissionType","track");
    iScrobbleEndPoint.addQueryItem("username", asUsername);
    iScrobbleEndPoint.addQueryItem("password", asPassword);
    iScrobbleEndPoint.addQueryItem("artist", asArtist);
    iScrobbleEndPoint.addQueryItem("track", asTrack);
    iScrobbleEndPoint.addQueryItem("album", asAlbum);
    iScrobbleEndPoint.addQueryItem("number","1");
    iScrobbleEndPoint.addQueryItem("duration","200");

    QNetworkAccessManager iScrobbleDispatcher;
    QNetworkRequest iScrobbleRequest(iScrobbleEndPoint);
    QNetworkReply *iScrobbleReply = iScrobbleDispatcher.get(iScrobbleRequest);

    QObject::connect(iScrobbleReply, SIGNAL(finished(QNetworkReply*)), &iLoop,
     SLOT(quit()));

    iDataSink = iScrobbleReply->readAll();

    qDebug()  << "Received: " + asUsername + " " + asPassword + " " + asArtist + " " + asTrack + " " + asAlbum;

    qDebug() << iScrobbleEndPoint.toString();

    iLoop.exec();
}

ScrobbleMedia::~ScrobbleMedia() {

}

void ScrobbleMedia::replyFinished(QNetworkReply*) {

}

void ScrobbleMedia::reallyDone() {

    qDebug() << "We've probably successfully Scrobbled...";
}
#ifndef SCROBBLEMEDIA_H
#define SCROBBLEMEDIA_H

#include <QString>
#include <QtNetwork>
#include <QUrl>
#include <QNetworkAccessManager>



class ScrobbleMedia : public QObject
{
     Q_OBJECT


private:


public:

    ScrobbleMedia(QString asUsername, QString asPassword, QString asArtist, QString asTrack, QString asAlbum);
    ~ScrobbleMedia();

private slots:
    void replyFinished(QNetworkReply*);
    void reallyDone();

};

#endif // SCROBBLEMEDIA_H