2012-10-01 24 views
0

我正在與Qt創建者合作製作一個GUI程序,該程序需要使用不同的URL並將下載並顯示html代碼。Qt在網絡回覆後更新

用戶可以將不同的URL添加到listWidget。然後用戶可以選擇一個特定的URL並下載將在URL列表旁邊顯示的HTML。

我遇到的問題是收到回覆後正在更新文本區域。

main.cpp - 基本上只顯示窗口。

#include <QtGui/QApplication> 
#include "mainwindow.h" 
#include "htmlmanager.h" 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 
    MainWindow w; 
    w.show(); 

    return a.exec(); 
} 

mainwindow.h - 非常簡單。包含將用於從輸入網站請求html的對象html。

#ifndef MAINWINDOW_H 
#define MAINWINDOW_H 
#include <QMainWindow> 
#include "htmlmanager.h" 
#include <QString> 
namespace Ui { 
class MainWindow; 
} 
class MainWindow : public QMainWindow 
{ 
    Q_OBJECT 

public: 
    explicit MainWindow(QWidget *parent = 0); 
    ~MainWindow(); 
    HtmlManager html; 

private slots: 
    void on_addButton_clicked(); 
    void on_actionExit_triggered(); 
    void on_removeButton_clicked(); 
    void on_downloadButton_clicked(); 
private: 
    Ui::MainWindow *ui; 
}; 
#endif // MAINWINDOW_H 

mainwindow.cpp - 這是問題的開始。如果你看下「downloadButton_clicked()」函數,你會發現它通過發送請求來獲取html。但是,在下一行之前沒有收到回覆,因此文本字段設置爲「」。

#include "mainwindow.h" 
#include "ui_mainwindow.h" 

MainWindow::MainWindow(QWidget *parent) : 
    QMainWindow(parent), 
    ui(new Ui::MainWindow) 
{ 
    ui->setupUi(this); 

} 

MainWindow::~MainWindow() 
{ 
    delete ui; 
} 

void MainWindow::on_addButton_clicked() 
{ 
    if(!ui->lineEdit->text().isEmpty()) 
    { 
     ui->listWidget->addItem(ui->lineEdit->text()); 
    } 
    else 
    { 
     qDebug() << "Input field is empty."; 
    } 
} 

void MainWindow::on_actionExit_triggered() 
{ 
    //doesn't do anything right now 
} 

void MainWindow::on_removeButton_clicked() 
{ 
    if(ui->listWidget->currentItem()) //If an item is selected 
    { 
     delete ui->listWidget->currentItem(); 
    } 
    else 
    { 
     qDebug() << "No selection"; 
    } 
} 

void MainWindow::on_downloadButton_clicked() 
{ 
    if(ui->listWidget->currentItem()) //If an item is selected 
    { 
     html.fetch(ui->listWidget->currentItem()->text()); 
     ui->textBrowser->setText(html.str); 
    } 
    else 
    { 
     qDebug() << "No selection"; 
    } 

} 

htmlmaneger.h

#ifndef HTMLMANAGER_H 
#define HTMLMANAGER_H 

#include <QObject> 
#include <QDebug> 
#include <QtNetwork> 
#include <QNetworkReply> 
#include <QNetworkAccessManager> 
#include <QString> 


class HtmlManager : public QObject 
{ 
    Q_OBJECT 
    public: 
     HtmlManager(); 
     void fetch(QString Url); 
     QString str; 

    public slots: 
     void replyFinished(QNetworkReply* pReply); 

    private: 
     QNetworkAccessManager* m_manager; 
}; 

#endif // HTMLMANAGER_H 

htmlmanager.cpp - 一旦回覆被接收,它存儲在QString的 「STR」

#include "htmlmanager.h" 

HtmlManager::HtmlManager() 
{ 
    m_manager = new QNetworkAccessManager(this); 
    connect(m_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*))); 
} 
void HtmlManager::fetch(QString Url) 
{ 
    m_manager->get(QNetworkRequest(QUrl(Url))); 
    qDebug() << "Sending network request."; 
} 
void HtmlManager::replyFinished(QNetworkReply* pReply) 
{ 
    qDebug() << "Recieved network reply."; 
    QByteArray data=pReply->readAll(); 
    str = data; 
} 

的HTML是有一個簡單的方法一旦接收到回覆,將str的值發送到MainWindow類;還是有方法讓onclick函數等待更新文本區域,直到接收到回覆爲止?

回答

3

你肯定不想等待onClick()函數的回覆。這會導致你的程序無法響應,直到網絡請求發出(這很可能永遠需要)。

攻擊這種方法的一種方法是將信號添加到您的HtmlManager類。有些東西可能叫做stringReceived。然後,在你的主窗口類你只需要添加一行:

connect(html, SIGNAL(stringReceived(QString)), ui->textBrowser, SLOT(setText(QString)); 
+0

如何更改您發佈的代碼以使其合法。 html對象和ui-> textbrowser是不同類型的。我可以改變什麼來使它工作? –

+0

沒關係,他們都是不同類型的。它們都來自QObject。 QObject :: connect的文檔是[here](http://qt-project.org/doc/qt-4.8/qobject.html#connect)。第一個和第三個參數是QObject指針。 –

+0

他們在上面的代碼中是不同的類型,但我解決了這個問題。現在,當我使用您建議的代碼時,出現鏈接器錯誤。LNK2005:已經在htmlmanager.obj中定義了「protected:void __thiscall HtmlManager :: stringReceived(class QString)」(?stringReceived @ HtmlManager @@ IAEXVQString @@@ Z)你知道這可能是什麼原因嗎? –

0

QNetworkAccessManager不提供同步或阻塞方法。如果你想等到收到回覆,你必須在本地事件循環中等待,直到回覆完成信號被調用。

參見下面的鏈接用於打開異步操作成同步之一: http://doc.qt.digia.com/qq/qq27-responsive-guis.html

在「在一個本地事件循環中等待」他們已經示出了使用QNetworkAccessManager一個例子一節。你可以在超時和本地事件循環中使用相同的方法。