Вызов слотов из класса в Qt - PullRequest
0 голосов
/ 01 марта 2012

Я пытаюсь запрограммировать приложение, которое извлекает файлы с сервера.

У меня есть класс 'Window' (mainwindow.cpp, который является классом виджета, который будет UI), а затем у меня естькласс Backend (Backend.cpp).

В графическом интерфейсе есть кнопка и две кнопки-переключателя.Если выбран переключатель «удаленный», то при нажатии кнопки будет происходить выборка файлов с сервера.

Однако в вызове 'connect' в Backend.cpp есть проблема, которую я не могу понять.Я получаю сообщение об ошибке: отсутствует соответствующий вызов функции для 'QObject :: connect (QNetworkReply * &), const char [13], Backend * const, const char [20])'

Вот коды:

ОТВЕТ: Избегайте круглых включений !!!!Вот обновленные коды:

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 голосов
/ 01 марта 2012

Вы опубликовали это:

class Backend
{
    // Q_OBJECT
public:

    Backend();
    void FetchFile(QUrl fpath);

public slots:
    void getBytesFromFile();

private:
    QNetworkReply *reply;
    QNetworkAccessManager qnam;

};

Q_OBJECT по-прежнему комментируется, если да, удалите его .. вы используете сигнал и слоты ..

РЕДАКТИРОВАТЬ: старайтесь избегать кругового включения: вы включили Backend в основное окно и наоборот ...

2 голосов
/ 01 марта 2012

Чтобы использовать сигналы и слоты, ваши классы (как сигнализация, так и слоты) должны быть производными от QObject, т.е.

#include "mainwindow.h"

#include <QObject>

class Backend : public QObject
{
    Q_OBJECT
public:
    Backend(QObject* parent=0);

[...]

Backend::Backend(QObject* parent)
    : QObject(parent)
{
}
0 голосов
/ 02 марта 2012

Кажется, у вас есть некоторые проблемы с механизмом сборки. С размещенным кодом и без комментариев QObject :: connect (& qnam, SIGNAL (закончено (QNetworkReply *)), this, SLOT (getBytesFromFile ())) ; в функции Backend :: FetchFile весь ваш код работает. Запустив и отметив «Загрузить файлы с веб-сервера», он печатает «мы загружаем данные с URL» из getBytesFromFile - разве это не тот слот, который вы хотите назвать?

0 голосов
/ 01 марта 2012

Закомментированные строки:

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.

...