首页 文章

从Qt中的类调用插槽

提问于
浏览
0

我正在尝试编写一个从服务器获取文件的应用程序 .

我有一个'Window'类(mainwindow.cpp,它是一个widget类,它是UI),然后我有一个'Backend'类(Backend.cpp) .

GUI有一个按钮和两个单选按钮 . 如果选择单选按钮“远程”,则单击按钮将导致从服务器获取文件 .

但是,在Backend.cpp的'connect'调用中存在一些问题,我无法弄清楚 . 我得到的错误是:没有匹配函数调用'QObject :: connect(QNetworkReply *&),const char [13],Backend * const,const char [20])'

以下是代码:

ANSWER: Avoid circular inclusions!!!! Here are the updated codes:

mainwindow.h

#ifndef WINDOW_H
#define WINDOW_H

#include <QWidget>
#include <QRadioButton>
#include <QtNetwork/QTcpSocket>
#include <QtNetwork/QHostAddress>
#include <QFile>
#include <QUrl>

#include "Backend.h"
class QGroupBox;

class Window : public QWidget
{
    Q_OBJECT

public:
    Window(QWidget *parent = 0);
    QTcpSocket *conn;
    QFile *file;

    QUrl url;
    Backend backend_inst;

private:

    QRadioButton *button_local;
    QRadioButton *button_remote;
    QGroupBox *createPushButtonGroup();


private slots:
    void onClick_button1();
    void onCheck_local();
    void onCheck_remote();
};

#endif

mainwindow.c

#include <QtGui>

#include "mainwindow.h"

Window::Window(QWidget *parent)
    : QWidget(parent)
{
    QGridLayout *grid = new QGridLayout;
    grid->addWidget(createPushButtonGroup(), 1, 1);
    setLayout(grid);

    setWindowTitle(tr("File-Fetch App"));
    resize(480, 420);
}

QGroupBox *Window::createPushButtonGroup()
{

    QGroupBox *groupBox = new QGroupBox();

    QPushButton *pushButton1 = new QPushButton(tr("Fetch Files!!"));

    button_local = new QRadioButton(tr("&Download Files from Local Storage"));
    button_remote = new QRadioButton(tr("&Download Files from a Web-Server"));
    button_local->setChecked(1);


    connect(pushButton1,SIGNAL(clicked()), this, SLOT(onClick_button1()));

    QVBoxLayout *vbox = new QVBoxLayout;
    vbox->addWidget(pushButton1);
    vbox->addSpacing(50);
    vbox->addWidget(button_local);
    vbox->addWidget(button_remote);
    vbox->addStretch(1);
    groupBox->setLayout(vbox);

    return groupBox;
}

void Window::onClick_button1()
{
    QTextStream out(stdout);
    out << "fetch button clicked\n";
    if (button_local->isChecked()){
        onCheck_local();
    }
    else if (button_remote->isChecked()){
         onCheck_remote();
    }

}
void Window::onCheck_local()
{

    QTextStream out(stdout);
    out << "local update button checked\n";

}
void Window::onCheck_remote()
{
    QTextStream out(stdout);
    out << "remote update button checked\n";
    QString pathname= "http://192.168.1.1:8000/example.txt";
    QUrl webaddr = pathname;
   backend_inst.FetchFile(webaddr);
}

Backend.h

#ifndef BACKEND_H
#define BACKEND_H

#include <QObject>
#include <QNetworkReply>
#include <QNetworkAccessManager>
#include <QUrl>
#include <QTextStream>

class Backend : public QObject
{
    Q_OBJECT

public:

    Backend(QObject* parent=0);
    void FetchFile(QUrl fpath);

public slots:
    void getBytesFromFile();

private:
    QNetworkReply *reply;
    QNetworkAccessManager qnam;

};

#endif // BACKEND_H

Backend.cpp

#include "Backend.h"


Backend::Backend(QObject* parent)
    : QObject(parent)
{
}

void Backend::FetchFile(QUrl fpath)
{
    reply = qnam.get(QNetworkRequest(fpath));
    QObject::connect(reply, SIGNAL(readyRead()),this, SLOT(getBytesFromFile()));

    //qnam = new QNetworkAccessManager;
    //QObject::connect(&qnam, SIGNAL(finished(QNetworkReply*)), this, SLOT(getBytesFromFile()));
}

void Backend::getBytesFromFile(){

    QByteArray downloadedData;
    QTextStream out(stdout);
    out << "we are loading data from URL\n";
    downloadedData =reply->readAll();
    out << downloadedData;
    delete reply;

}

main.cpp中

#include <QApplication>

#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    Window window;
    window.show();
    return app.exec();
}

4 回答

  • 2

    要使用信号和插槽,您的类(信令和插槽)必须从QObject派生,即

    #include "mainwindow.h"
    
    #include <QObject>
    
    class Backend : public QObject
    {
        Q_OBJECT
    public:
        Backend(QObject* parent=0);
    
    [...]
    
    Backend::Backend(QObject* parent)
        : QObject(parent)
    {
    }
    
  • 0

    你发布了这个:

    class Backend
    {
        // Q_OBJECT
    public:
    
        Backend();
        void FetchFile(QUrl fpath);
    
    public slots:
        void getBytesFromFile();
    
    private:
        QNetworkReply *reply;
        QNetworkAccessManager qnam;
    
    };
    

    Q_OBJECT 仍然被评论如果是删除它..你正在使用信号和插槽..

    编辑:尽量避免循环包含:你在主窗口包括后端,反之亦然 .

  • 0

    注释掉的行:

    qnam = new QNetworkAccessManager;
    QObject::connect(&qnam, SIGNAL(finished(QNetworkReply*)), this, SLOT(getBytesFromFile()));
    

    是什么导致了你的问题 . Connect除了指针外,不是指向指针的指针 . qnam 是指针是前一版本代码中的指针,并且在其上使用address-of运算符会将其转换为指向指针的指针 . 第二个错误是您需要为信号和插槽设置相同的签名才能调用它(否则会出现运行时错误) . 所以,正确的:

    connect(qnam, SIGNAL(finished(QNetworkReply*)), this, SLOT(getBytesFromFile(QNetworkReply*)));
    

    (显然,更改 getBytesFromFile 方法的实际签名) .

    至于为什么你的错误仍然存在,尽管注释掉代码:我认为你正在运行一个旧版本,而新版本由于vtable问题而无法构建(正如你在评论主题中描述的那样) . 我的猜测是qmake正在出现故障,我在将Q_OBJECT宏添加到已有的类时遇到过这种情况 . 转到您的构建文件夹并删除Makefile * . 然后回到Qt创建者并重建项目,这应该迫使qmake再次生成Makefile .

  • 2

    看来你的构建机制存在一些问题 . 已发布的代码和未评论的 QObject::connect(&qnam, SIGNAL(finished(QNetworkReply)), this, SLOT(getBytesFromFile()))* ;在Backend :: FetchFile函数中,您的所有代码都可以正常工作 . 运行并选中"Download Files from Web-Server"它会从getBytesFromFile打印"we are loading data from URL" - 这不是您想要调用的插槽吗?

相关问题