صفحه 2 از 2 اولاول 12
نمایش نتایج 41 تا 54 از 54

نام تاپیک: معرفی و آموزش C++‎‎‎/Qt به صورت گام به گام

  1. #41

    نقل قول: معرفی و آموزش C++‎‎‎‎‎‎/Qt به صورت گام به گام

    مرحله سی دوم : معرفی و کار با شبکه / استفاده از پروتکل های HTTP و FTP

    در اينترنت همانند ساير شبكه های كامپيوتری از پروتكل های متعدد و با اهداف مختلف استفاده می گردد. هر پروتكل از يك ساختار خاص برای ارسال و دريافت اطلاعات (بسته های اطلاعاتی ) استفاده نموده و ترافيك مختص به خود را در شبكه ايجاد می نمايد . HTTP ( برگرفته از Hyper Text Transfer Protocol ) ، يكی از متداولترين پروتكل های لايه application است كه مسئوليت ارتباط بين سرويس گيرندگان و سرويس دهندگان وب را برعهده دارد .

    به طور کلی در این قسمت میرسیم به موارد شبکه و کار با پروتکل ها و ...

    در C++‎‎‎‎ کتابخانه های Qt کلاس هایی رو برای شبکه دارند که برای فراخوانی کلاس ها به برنامه ابتدا لازمه در فایل .pro موجود در پروژه کد زیر رو اضافه کنیم :


    QT += network


    البته میتونید در ادامه همون QT += موجود به این صورت عمل کنید :


    QT += core network


    البته دقت کنید باید فاصله بین رفرنس ها وجود داشته باشد.

    یک توضیحی بدم که چرا از نماد های += استفاده میکنیم دلیلش اینه و مشخصه که دستور افزودن رو دادیم به QT تا رفرنس مورد نظر رو وارد پروژه میکند ولی اگه بخوام رفرنس مورد نظر رو حذف یا از پروژه بیرون کنم چطور ؟ این موقت باید بگم -= به مثال زیر توجه کنید :


    QT += core network
    QT -= gui



    در خط دوم مشخص کردم که رفرنس های مربوط به gui که شامل widget ها و یا هر رابط کاربری به جز Console هستش رو از پروژه حذف کن یعنی نیازی به رفرنس gui نداریم.

    ادامه مطلب در پست بعدی...
    آخرین ویرایش به وسیله کامبیز اسدزاده : پنج شنبه 25 اردیبهشت 1393 در 15:29 عصر

  2. #42

    نقل قول: معرفی و آموزش C++‎‎‎‎‎‎‎/Qt به صورت گام به گام

    ادامه مرحله سی دوم : معرفی و کار با شبکه / استفاده از پروتکل های HTTP و FTP

    خب پروژم رو ایجاد میکنم و تحت توضیحات در پست قبلی رفرنس network رو به پروژم اضافه میکنم.
    حالا روی پروژم راست کلیک میکنم و Add New و قسمت File and Classes گزینه C++‎‎‎‎‎‎‎‎‎‎ Class رو انتخاب میکنم و اطلاعاتش رو به صورت زیر مشخص میکنم.

    ابتدا من نیاز دارم یک کلاس برای پروتکل HTTP ایجاد کنم به صورت زیر ایجاد میکنم و فایل هیدر و اصلی رو آماده میکنم.


    #ifndef MYHTTP_H
    #define MYHTTP_H


    #include <QObject>


    #include <QtGlobal>
    #include <QObject>
    #include <QNetworkAccessManager>
    #include <QNetworkRequest>
    #include <QNetworkReply>
    #include <QFile>
    #include <QTimer>




    class MyHttp : public QObject
    {
    Q_OBJECT


    public:
    explicit MyHttp(QObject *parent = 0);
    virtual ~MyHttp();


    signals:
    void addLine(QString qsLine);
    void downloadComplete();
    void progress(int nPercentage);


    public slots:
    void download(QUrl url);
    void pause();
    void resume();


    private slots:
    void download();
    void finishedHead();
    void finished();
    void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
    void error(QNetworkReply::NetworkError code);
    void timeout();


    private:
    QUrl _URL;
    QString _qsFileName;
    QNetworkAccessManager* _pManager;
    QNetworkRequest _CurrentRequest;
    QNetworkReply* _pCurrentReply;
    QFile* _pFile;
    int _nDownloadTotal;
    bool _bAcceptRanges;
    int _nDownloadSize;
    int _nDownloadSizeAtPause;
    QTimer _Timer;
    };


    #endif // MYHTTP_H




    خب در این کلاس من برای HTTP کلاس و توابع مورد نیاز رو تحت کلاس های QNetworkAccessManager / QNetworkRequest / QNetworkReply ایجاد کردم.
    که وظیفه هرکدام به صورت زیر است :

    کلاس QNetworkAccessManager : وظیفه این کلاس این هستش که برای ما قابلیت ارسال اطلاعات و دریافت اطلاعات رو از سرور فراهم میکنه
    کلاس QNetworkRequest : وظیفه این کلاس که دریافت و نگه داری اطلاعاتی هستش که کلاس QNetworkAccessManager به آنها نیاز خواهد داشت.
    کلاس QNetworkReply : وظیفه این کلاس هم نگه داری داده ها و هیدر هایی هستش که درخواست شده.

    کلاس QtGlobal : بعضی وقتها لازمه این کلاس رو فراخوانی کنیم زیرا هیدر ها و توابع اساسی Qt توسط اینکلود کردن این کلاس قابل شناسایی هستش که البته روش های دیگری هم هست تا به طور کلی از هر بار اینکلود کردن چنین موارد در قسمت های مختلف پروژه جلوگیری کنیم که بعد ها توضیحاتی خواهیم داد.

    کلاس QObject : مشخصه که برای ایجاد و شناسایی آبجکت ها استفاده میشود.
    کلاس QFile : برای کار با فایلها مورد نیاز هستش به عنوان مثال اگه قرار هست فایلی رو دانلود کنیم و عمل مثلا کپی رو روی فایل دانلود شده انجام دهیم به این کلاس نیاز اساسی خواهیم داشت.
    کلاس QTimer : برا کار با زمان مورد استفاده قرار میگیره که در این مثال ازش برای مشخص سازی زمان دریافت و ارسال استفاده خواهیم کرد.

    خب ابتدا من کلاسم رو از نوع عمومی و آبجکت مشخص کردم به صورت زیر :


    class MyHttp : public QObject



    برای اینکه تمامی هیدر فایل های آبجکت ما توسط زبان C++‎‎‎‎‎‎‎‎‎‎ قابل شناسایی باشه لازمه کار اینه از ماکرو مخصوص آبجکت در Qt استفاده کنیم که به صورت زیر در کلاس ازش استفاده خواهد شد.


    Q_OBJECT


    در خط بعدی تعریف کلی کلاس مشخص شده و بعد سیگنال / اسلات ها و متغیر های مورد نیاز اعمال گردیده است.

    تا اینجا کار ما با فایل MyHttp.h تمونه میریم در پست بعدی کار با فایل MyHttp.cpp
    آخرین ویرایش به وسیله کامبیز اسدزاده : پنج شنبه 25 اردیبهشت 1393 در 17:11 عصر

  3. #43

    نقل قول: معرفی و آموزش C++‎‎‎‎/Qt به صورت گام به گام

    ادامه مرحله سی دوم : معرفی و کار با شبکه / استفاده از پروتکل های HTTP و FTP

    خب فایل cpp ما حاوی کد های زیر خواهد بود که در این فایل ما بدنه توابع خودمون رو کامل کردیم و برای دانلود فایلمون همراه با اطلاعات دقیق ارسال و دریافت لازم داریم ! اشاره کنم که خیلی ساده تر از اینها میشه کد دانلود فایل رو توسط http نوشت ولی نیاز دونستم کمی پروژه پیچیده تر رو انتخاب کنم تا نتیجه حاصل از فایل دانلود شده همراه با پکیج های ارسالی و دریافتی همانند سیستم ارسال و دریافت کننده TeamViewer مشخص بشه که ممکنه خیلی ها به این نیاز داشته باشند.


    #include "myhttp.h"
    #include <QFileInfo>
    #include <QDateTime>
    #include <QDebug>




    MyHttp::MyHttp(QObject *parent) :
    QObject(parent)
    , _pManager(NULL)
    , _pCurrentReply(NULL)
    , _pFile(NULL)
    , _nDownloadTotal(0)
    , _bAcceptRanges(false)
    , _nDownloadSize(0)
    , _nDownloadSizeAtPause(0)
    {
    }




    MyHttp::~MyHttp()
    {
    if (_pCurrentReply != NULL)
    {
    pause();
    }
    }




    void MyHttp::download(QUrl url)
    {
    qDebug() << "download: URL=" << url.toString();


    _URL = url;
    {
    QFileInfo fileInfo(url.toString());
    _qsFileName = fileInfo.fileName();
    }
    _nDownloadSize = 0;
    _nDownloadSizeAtPause = 0;


    _pManager = new QNetworkAccessManager(this);
    _CurrentRequest = QNetworkRequest(url);


    _pCurrentReply = _pManager->head(_CurrentRequest);


    _Timer.setInterval(5000);
    _Timer.setSingleShot(true);
    connect(&_Timer, SIGNAL(timeout()), this, SLOT(timeout()));
    _Timer.start();


    connect(_pCurrentReply, SIGNAL(finished()), this, SLOT(finishedHead()));
    connect(_pCurrentReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));
    }




    void MyHttp::pause()
    {
    qDebug() << "pause() = " << _nDownloadSize;
    if (_pCurrentReply == NULL)
    {
    return;
    }
    _Timer.stop();
    disconnect(&_Timer, SIGNAL(timeout()), this, SLOT(timeout()));
    disconnect(_pCurrentReply, SIGNAL(finished()), this, SLOT(finished()));
    disconnect(_pCurrentReply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadProgress(qint64, qint64)));
    disconnect(_pCurrentReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));


    _pCurrentReply->abort();
    // _pFile->write( _pCurrentReply->readAll());
    _pFile->flush();
    _pCurrentReply = 0;
    _nDownloadSizeAtPause = _nDownloadSize;
    _nDownloadSize = 0;
    }




    void MyHttp::resume()
    {
    qDebug() << "resume() = " << _nDownloadSizeAtPause;


    download();
    }




    void MyHttp::download()
    {
    qDebug() << "download()";


    if (_bAcceptRanges)
    {
    QByteArray rangeHeaderValue = "bytes=" + QByteArray::number(_nDownloadSizeAtPause) + "-";
    if (_nDownloadTotal > 0)
    {
    rangeHeaderValue += QByteArray::number(_nDownloadTotal);
    }
    _CurrentRequest.setRawHeader("Range", rangeHeaderValue);
    }


    _pCurrentReply = _pManager->get(_CurrentRequest);


    _Timer.setInterval(5000);
    _Timer.setSingleShot(true);
    connect(&_Timer, SIGNAL(timeout()), this, SLOT(timeout()));
    _Timer.start();


    connect(_pCurrentReply, SIGNAL(finished()), this, SLOT(finished()));
    connect(_pCurrentReply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadProgress(qint64, qint64)));
    connect(_pCurrentReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));
    }




    void MyHttp::finishedHead()
    {
    _Timer.stop();
    _bAcceptRanges = false;


    QList<QByteArray> list = _pCurrentReply->rawHeaderList();
    foreach(QByteArray header, list)
    {
    QString qsLine = QString(header) + " = " + _pCurrentReply->rawHeader(header);
    addLine(qsLine);
    }


    if (_pCurrentReply->hasRawHeader("Accept-Ranges"))
    {
    QString qstrAcceptRanges = _pCurrentReply->rawHeader("Accept-Ranges");
    _bAcceptRanges = (qstrAcceptRanges.compare("bytes", Qt::CaseInsensitive) == 0);
    qDebug() << "Accept-Ranges = " << qstrAcceptRanges << _bAcceptRanges;
    }


    _nDownloadTotal = _pCurrentReply->header(QNetworkRequest::ContentLengthHeader).toIn t();


    // _CurrentRequest = QNetworkRequest(url);
    _CurrentRequest.setRawHeader("Connection", "Keep-Alive");
    _CurrentRequest.setAttribute(QNetworkRequest::Http PipeliningAllowedAttribute, true);
    _pFile = new QFile(_qsFileName + ".part");
    if (!_bAcceptRanges)
    {
    _pFile->remove();
    }
    _pFile->open(QIODevice::ReadWrite | QIODevice::Append);


    _nDownloadSizeAtPause = _pFile->size();
    download();
    }




    void MyHttp::finished()
    {
    qDebug() << __FUNCTION__;


    _Timer.stop();
    _pFile->close();
    QFile::remove(_qsFileName);
    _pFile->rename(_qsFileName + ".part", _qsFileName);
    _pFile = NULL;
    _pCurrentReply = 0;
    emit downloadComplete();
    }




    void MyHttp::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
    {
    _Timer.stop();
    _nDownloadSize = _nDownloadSizeAtPause + bytesReceived;
    qDebug() << "Download Progress: Received=" << _nDownloadSize << ": Total=" << _nDownloadSizeAtPause + bytesTotal;


    _pFile->write(_pCurrentReply->readAll());
    int nPercentage = static_cast<int>((static_cast<float>(_nDownloadSiz eAtPause + bytesReceived) * 100.0) / static_cast<float>(_nDownloadSizeAtPause + bytesTotal));
    qDebug() << nPercentage;
    emit progress(nPercentage);


    _Timer.start(5000);
    }




    void MyHttp::error(QNetworkReply::NetworkError code)
    {
    qDebug() << __FUNCTION__ << "(" << code << ")";
    }




    void MyHttp::timeout()
    {
    qDebug() << __FUNCTION__;
    }




    در این کلاس تمامی اتفاقانی مثل ارسال / دریافت اطلاعات و تمامی رخداد های موجود در طی دانلود یک فایل رو ایجاد کردیم که هر کدام وظیفه خاص خودش رو خواهد داشت.
    آخرین ویرایش به وسیله کامبیز اسدزاده : پنج شنبه 25 اردیبهشت 1393 در 17:45 عصر

  4. #44

    نقل قول: معرفی و آموزش C++‎‎‎‎/Qt به صورت گام به گام

    ادامه مرحله سی دوم : معرفی و کار با شبکه / استفاده از پروتکل های HTTP و FTP

    خب حالا بیاییم سراغ تجزیه تحلیل این کلاس ببینیم توش چه خبره...

    ابتدا موارد زیر رو اینکلود کردیم :


    #include "myhttp.h"

    #include <QFileInfo>
    #include <QDateTime>
    #include <QDebug>


    دلیلشون واظحه ! اولیرو حتما باید اینکلود کنیم چون بدون اون دسترسی به کلاس و توابع از پیش تعریف شده در فایل .h امکانپذیر نخواهد بود.
    QFileInfo برای کار با اطلاعات فایل هستش و گزینه QDateTime هم خب برای کار با تاریخو زمانو اینجور چیزا و در نهایت QDebug برای کار QDebug که من خودم شخصا ازش متنفرم چون خیلی ضعیفتر از std::cout عمل میکنه ولی خب طی این آموزش ها از همین روش استفاده میکنیم هرچند هیچ موردی نخواهد داشت اگه شما در پروژه هاتون به جای QDebug از iostream و فراخوانی std::cout برای چاپ موارد مورد نظرتون استفاده کنید فقط در بعضی از موارد باید عمل تبدیل QString به StdString ها رو رعایت کنید و در رابطه با مقادیر دیگه هم همینطوره...


    خب در خط بعدی به صورت زیر...


    MyHttp::MyHttp(QObject *parent) :
    QObject(parent)
    , _pManager(NULL)
    , _pCurrentReply(NULL)
    , _pFile(NULL)
    , _nDownloadTotal(0)
    , _bAcceptRanges(false)
    , _nDownloadSize(0)
    , _nDownloadSizeAtPause(0)
    {
    }


    اینجا ما کلاسمون رو فراخوانی کردیم همراه با آبجکت هاش و هر یک از کلاس های مشتق شده آن که به نوعی کپی از کلاس ها برای استفاده از آن گرفته شده اند در اینجا آمده است که ابتدا برای هر یک مقادیر پیشفرض بر اساس نوع آنها مشخص شده است.

    در خط بعدی به صورت زیر ...


    MyHttp::~MyHttp()
    {
    if (_pCurrentReply != NULL)
    {
    pause();
    }
    }




    در بدنه کلاس ویرانگر دستور شرطی آمده که اگر پاسخی ارسال شده از طرف سرور به صورت NULL نباشد تابع pause اجرا خواهد گردید.

    حالا در مرحله بعدی به صورت زیر....


    void MyHttp::download(QUrl url)
    {
    qDebug() << "download: URL=" << url.toString();




    _URL = url;
    {
    QFileInfo fileInfo(url.toString());
    _qsFileName = fileInfo.fileName();
    }
    _nDownloadSize = 0;
    _nDownloadSizeAtPause = 0;




    _pManager = new QNetworkAccessManager(this);
    _CurrentRequest = QNetworkRequest(url);




    _pCurrentReply = _pManager->head(_CurrentRequest);




    _Timer.setInterval(5000);
    _Timer.setSingleShot(true);
    connect(&_Timer, SIGNAL(timeout()), this, SLOT(timeout()));
    _Timer.start();




    connect(_pCurrentReply, SIGNAL(finished()), this, SLOT(finishedHead()));
    connect(_pCurrentReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));
    }


    تابع download رو فراخوانی کردیم که حاوی پارامتر Url از نوع QUrl هستش که در حین اجرا ابتدا آدرسی که مختص فایل قابل دانلود هستش رو میگیره و به صورت زیر...


    qDebug() << "download: URL=" << url.toString();


    یک کد چاپ برای آدرسی که ارسال کردیم برای دانلود.


    _URL = url;
    {
    QFileInfo fileInfo(url.toString());
    _qsFileName = fileInfo.fileName();
    }


    اینجا آدرس ارسال شده توسط کاربر دریافت و مشخصات آدرس توسط کلاس QFileInfo بررسی و نام فایل از آدرس گرفته شده و به متغیر از قبل تعریف شده یعنی _qsFileName ارسال میشود.
    در خط بعدی کد های زیر...


    _nDownloadSize = 0;
    _nDownloadSizeAtPause = 0;




    مقدار 0 رو به متغیر های _nDownloadSize و همچنین _nDownloadSizeAtPause اختصاص میدیم.

    حالا اینجا کلاس اصلی ما که ازش استفاده خواهیم کرد وار کار خواهد شد به صورت زیر...


    _pManager = new QNetworkAccessManager(this);
    _CurrentRequest = QNetworkRequest(url);


    اینجا مقدار کلاس مشتق شده _pManager رو برابر کلاس اصلی QNetworkAccessManager مشخص میکنیم و همچنین کلاس های _CurrentRequest رو با درخواست کننده آدرس یعنی QNetworkRequest با پارامتر url اختصاص میدیم.

    در این خط به صورت زیر ...


    _pCurrentReply = _pManager->head(_CurrentRequest);


    مقدار _pCurrentReply رو برابر میکنیم با هیدر (Header) ای که توسط کلاس _CurrentRequest گرفته شده.
    خط های زیر...


    _Timer.setInterval(5000);
    _Timer.setSingleShot(true);


    خب ایجا ما نیاز داریم به مدت زمانی که باید توسط تایمرمون ایجاد کنیم برای مثال در اینجا میانگین زمانی رو برابر 5000 میلی ثانیه قرار دادیم و در خط بعدیش مقدار SingleShot یا همان تایمر شات که یکی از پراپرتی های QTimer هستش رو برابر با true قرار دادیم.

    و در خط های زیر...


    connect(&_Timer, SIGNAL(timeout()), this, SLOT(timeout()));
    _Timer.start();


    توسط تابع connect سیگنال ارسالی توسط تایمر رو توسط تابع timeout ارسال و مجددا سیگنال بازگشتی یا همان اسلات رو توسط تابع timeout ارسال میکنیم.


    connect(_pCurrentReply, SIGNAL(finished()), this, SLOT(finishedHead()));
    connect(_pCurrentReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));


    این دو کد نهایی عمل اتصال بین سیگنال و اسلات برای ارسال و دریافت جواب به عنوان اتمام کار انجام خواهند داد و در خط بعدی همین کار رو برای زمانی که ارتباط با مشکل برخورده باشه ایجاد میکنیم.
    آخرین ویرایش به وسیله کامبیز اسدزاده : پنج شنبه 25 اردیبهشت 1393 در 17:50 عصر

  5. #45

    نقل قول: معرفی و آموزش C++‎‎‎‎‎/Qt به صورت گام به گام

    ادامه مرحله سی دوم : معرفی و کار با شبکه / استفاده از پروتکل های HTTP و FTP

    و اما تابع pause به صورت زیر تعریف شده است :


    void MyHttp::pause()
    {
    qDebug() << "pause() = " << _nDownloadSize;
    if (_pCurrentReply == NULL)
    {
    return;
    }
    _Timer.stop();
    disconnect(&_Timer, SIGNAL(timeout()), this, SLOT(timeout()));
    disconnect(_pCurrentReply, SIGNAL(finished()), this, SLOT(finished()));
    disconnect(_pCurrentReply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadProgress(qint64, qint64)));
    disconnect(_pCurrentReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));


    _pCurrentReply->abort();
    // _pFile->write( _pCurrentReply->readAll());
    _pFile->flush();
    _pCurrentReply = 0;
    _nDownloadSizeAtPause = _nDownloadSize;
    _nDownloadSize = 0;
    }




    موارد ابتداییش مشخص هست میرم سراغ Timert.Stop به این خط که میرسیم از نام تابع هم مشخص وظیفش متوقف کردن عملیات هست که در اینجا توسط تابع disconnect تمامی ارتباطات موجود بین سیگنال ها و اسلات ها ازبین خواهند رفت یعنی در این صورت اگه فایلی در حال دانلود باشه یا مثلا وظیفه دانلود به اتمام رسیده باشه توسط این تابع هست که میشه عمل توقف رو انجام داد.
    نمیخوام ریز به ریز توضیحات خط به خطی بدم چون واقعا هر کدوم از این کلاس ها چندین سطر توضیحات اختصاصی داره برا همین سعی میکنیم توضیح مختصری در نحوه کار این ها بدم که شاید مفید باشه.

    در این تابع در کل با استفاده از تابع disconnect تمامی ارتباط ها از بین رفته و بعد از آن دستور از بین بردن تمامی درخواست ها توسط تابع abort ارسال می شود.
    در خط بعد این ها یک گزینه ای داریم به نام Flush به صورت زیر ازش استفاده شده :


    _pFile->flush();


    میدونید این چیکار میکنه !؟ اگر در طول دریافت فایل اطلاعات به درستی و کامل بدون هیچگونه خرابی روی فیال به Buffer انتقال پیدا کنند در این حالت Flush مقدار true رو ارسال میکنه و در غیر اینصورت مقدار false رو ارسال خواهد کرد در واقع توسط این میتونیم راحت مشخص کنیم که فایلمون با موفقیت و بدون هیچگونه خرابی دانلود شد یا خیر !

    خط های بعدی هم که مشخص هست میریم ادامه مطلب...

  6. #46

    نقل قول: معرفی و آموزش C++‎‎‎‎‎‎/Qt به صورت گام به گام

    ادامه مرحله سی دوم : معرفی و کار با شبکه / استفاده از پروتکل های HTTP و FTP

    خب و اما تابع resume در باره این تابع هم اینطور توضیح بدم که وظیفش ادامه عملیات دانلود هست درواقع با اجرای این تابع مسلما باید تابع دیگری به نام download عملیات خودش رو انجام بده به صوت زیر...


    void MyHttp::resume()
    {
    qDebug() << "resume() = " << _nDownloadSizeAtPause;


    download();
    }




    خیلی راحت تابع فراخوانی شده و در بدنه تابع توسط qDebug متنیرو هنگام درخواست ادامه با عنوان مقدار سایز از متغیری که در تابع pause مقدار دهی شده بود دریافت میکنه.
    و در نهایت ادامه کار توسط اجرا شدن تابع download صورت خواهد گرفت.

  7. #47

    نقل قول: معرفی و آموزش C++‎‎‎‎‎‎‎/Qt به صورت گام به گام

    ادامه مرحله سی دوم : معرفی و کار با شبکه / استفاده از پروتکل های HTTP و FTP

    خب اینجا دوباره ما تابعی نوشتیم با نام download ولی با این تفاوت که دیگه اینجا آدرس فایلی برای دانلود نمیخواد این تابع کی استفاده میشه اگه گفتین !؟! خب همین پست قبلی من در نهایت تابع download رو فراخوانی کردم چون قرار بود ادامه کار رو انجام بده !!! پس نباید از تابع download ای که شامل پارامتر URL بود استفاده می کردیم.

    و اما تابع finishedHead که وظیفه این تابع دریافت اطلاعات از هیدر و ارسال اون برای کاربر هستش.


    void MyHttp::finishedHead()
    {
    _Timer.stop();
    _bAcceptRanges = false;


    QList<QByteArray> list = _pCurrentReply->rawHeaderList();
    foreach(QByteArray header, list)
    {
    QString qsLine = QString(header) + " = " + _pCurrentReply->rawHeader(header);
    addLine(qsLine);
    }


    if (_pCurrentReply->hasRawHeader("Accept-Ranges"))
    {
    QString qstrAcceptRanges = _pCurrentReply->rawHeader("Accept-Ranges");
    _bAcceptRanges = (qstrAcceptRanges.compare("bytes", Qt::CaseInsensitive) == 0);
    qDebug() << "Accept-Ranges = " << qstrAcceptRanges << _bAcceptRanges;
    }


    _nDownloadTotal = _pCurrentReply->header(QNetworkRequest::ContentLengthHeader).toIn t();


    // _CurrentRequest = QNetworkRequest(url);
    _CurrentRequest.setRawHeader("Connection", "Keep-Alive");
    _CurrentRequest.setAttribute(QNetworkRequest::Http PipeliningAllowedAttribute, true);
    _pFile = new QFile(_qsFileName + ".part");
    if (!_bAcceptRanges)
    {
    _pFile->remove();
    }
    _pFile->open(QIODevice::ReadWrite | QIODevice::Append);


    _nDownloadSizeAtPause = _pFile->size();
    download();
    }


    ور در صورت کلی تابع اتمام دانلود به صورت زیر هستش ...


    void MyHttp::finished()
    {
    qDebug() << __FUNCTION__;


    _Timer.stop();
    _pFile->close();
    QFile::remove(_qsFileName);
    _pFile->rename(_qsFileName + ".part", _qsFileName);
    _pFile = NULL;
    _pCurrentReply = 0;
    emit downloadComplete();
    }


    این جا یک موردی هست که باید یک توضیحی بدم که گمراه کننده نباشه... نوشتیم چاپ کن __FUNCTION__ رو ! __FUNCTION__ نوعی ماکرو (MACRO) هستش که به صورت پیش پردازنده عمل میکنند و برای ما اطلاعاتی در رابطه با وضعیت کاری این تابع ارسال خواهد کرد ! یعنی فقط به درد برنامه نویس و توسعه دهنده میخوره یجور LOG میشه بهش گفت که برای کامپایلر های موجود در C++‎ و PHP قابل شناسایی هستش.

    موارد زیادی هستش از این ماکروهای استاندارد از پیش تعریف شده که میتونید در رابطه با اینها تحقیق کنید : __FILE__, __LINE__, و __FUNCTION__


    و تابع downloadProgress از اسمش هم مشخصه وظیفه این تابع مشخص کردن وضعیت و اطلاعات کلی در رابطه با مقدار اندازه دریافت شده و یا مقدار اندازه باقی ماندده همراه با زمانش رو مشخص و نمایش خواهدد داد.


    void MyHttp::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
    {
    _Timer.stop();
    _nDownloadSize = _nDownloadSizeAtPause + bytesReceived;
    qDebug() << "Download Progress: Received=" << _nDownloadSize << ": Total=" << _nDownloadSizeAtPause + bytesTotal;


    _pFile->write(_pCurrentReply->readAll());
    int nPercentage = static_cast<int>((static_cast<float>(_nDownloadSiz eAtPause + bytesReceived) * 100.0) / static_cast<float>(_nDownloadSizeAtPause + bytesTotal));
    qDebug() << nPercentage;
    emit progress(nPercentage);


    _Timer.start(5000);
    }




    و باز هم یک تابعی برای مشخص سازی مشکلات ممکن..


    void MyHttp::error(QNetworkReply::NetworkError code)
    {
    qDebug() << __FUNCTION__ << "(" << code << ")";
    }


    و تابع آخر هم برای مشکلات ناشی در timeout


    void MyHttp::timeout()
    {
    qDebug() << __FUNCTION__;
    }



  8. #48

    نقل قول: معرفی و آموزش C++‎‎‎‎/Qt به صورت گام به گام

    ادامه مرحله سی دوم : معرفی و کار با شبکه / استفاده از پروتکل های HTTP و FTP

    خب حالا من میخوام در حالت طراحی از این توابع استفاده کنم قبل از هر چیزی فرم زیر رو طراحی میکنیم ...

    کد های مربوط به فایل هیدر فرمم به صورت زیر خواهد بود که شامل سیگنال ها و متغیر ها و آبجکت های مورد نظرمون هستش...


    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H


    #if QT_VERSION >= 0x050000
    #include <QtWidgets/QMainWindow>
    #else
    #include <QMainWindow>
    #endif


    #include "downloadmanager.h"




    namespace Ui {
    class MainWindow;
    }


    class MainWindow : public QMainWindow
    {
    Q_OBJECT


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


    private slots:
    void addLine(QString qsLine);
    void progress(int nPercentage);
    void finished();


    void on_downloadBtn_clicked();
    void on_pauseBtn_clicked();
    void on_resumeBtn_clicked();




    protected:
    void changeEvent(QEvent *e);


    private:
    Ui::MainWindow *ui;
    DownloadManager* mManager;




    };


    #endif // MAINWINDOW_H




    یه توضیحی در رابطه با کد زیر بدم شاید برای خیلی ها مشخص نشده باشه چیه...


    #if QT_VERSION >= 0x050000
    #include <QtWidgets/QMainWindow>
    #else
    #include <QMainWindow>
    #endif




    ما در C++‎ انواع ماکرو هارو داریم که وظیفه اینها قبل از پیش پردازش شدن هست تا اجرا بشن اینا چکار میکنن دقیقا قبل از اینکه کد های ما خونده بشن اجرا میشن شرایط رو بررسی و بر اساس اون شرایط بین کد های ما سوئیچ خواهند شد مثلا در این کد گفتین اگر ماکروی QT_VERSION مقدارش بزرگتر از 0x050000 یعنی کیوت نسخه 5.0 بود برو فلان مسیر فایل فلان رو فراخوانی کن در غیر اینصور از مسیر زیر فایل ها و هیدر هارو برام فراخوانی کن...

    این ها قواعد خاصی دارن برای خودشون در رابطه با اینجور چیزا تحقیق کنید مثلا 0x050000 رو میتونید به اینصورت هم بنویسید : 5.0

    حالا بریم سراغ فرم لود که لازمه کد های زیر رو بنویسیم...


    ui->urlEdit->setText("http://qt.digia.com/Static/Images/QtLogo.png");


    QStandardItemModel *model = new QStandardItemModel(0, 1, this);
    ui->listView->setModel(model);


    mManager = new DownloadManager(this);


    connect(mManager, SIGNAL(addLine(QString)), this, SLOT(addLine(QString)));
    connect(mManager, SIGNAL(downloadComplete()), this, SLOT(finished()));
    connect(mManager, SIGNAL(progress(int)), this, SLOT(progress(int)));


    طبق فرمی که طراحی کردم نام تکست باکسم رو گذاشتم urlEdit که ابتدا به صورت پیشفرض آدرس تصویر لوگوی Qt رو بهش اختصاص میدم.
    درخط بعدی یک کپی از کلاس QStandardItemModel ساختم که وظیفش فراهم کردن یک مدل عمومی برای ذخیره سازی داده های دلخواه هستش.
    مدلم رو به شیئ listView که روی فرمم قرار دادم تخصیص میدم و در خط بعد یک کپی از کلاس download و سه خط بعدی توسط تابع connect سیگنال ها و اسلاتها باهم دیگه ارتباط برقرار می کنند.

    روی دکمه Download اسلاتش رو ایجاد و کد زیر رو مینویسم ...


    ui->listView->reset();
    QUrl url(ui->urlEdit->text());
    mManager->download(url);
    ui->downloadBtn->setEnabled(false);
    ui->pauseBtn->setEnabled(true);


    دکمه Pause به صورت زیر...


    mManager->pause();
    ui->pauseBtn->setEnabled(false);
    ui->resumeBtn->setEnabled(true);


    دکمه Resume به صورت زیر...


    mManager->resume();
    ui->pauseBtn->setEnabled(true);
    ui->resumeBtn->setEnabled(false);


    و برای نمایش دادن اطلاعات مربوطه متغیری داشتم به نام AddLine از نوع QString بود تو فایل .h طرح فرمم بگردین پیداش میکنید... تابع مربوط به اینرو باید به این صورت بنویسیم...


    void MainWindow::addLine(QString qsLine)
    {
    int nRow = ui->listView->model()->rowCount();
    ui->listView->model()->insertRow(nRow);
    ui->listView->model()->setData(ui->listView->model()->index(nRow, 0), qsLine);
    }




    و تابع مربوط به ProgressBar به صورت زیر...


    void MainWindow::progress(int nPercentage)
    {
    ui->progressBar->setValue(nPercentage);
    }




    تابع Finished ...


    void MainWindow::finished()
    {
    ui->downloadBtn->setEnabled(true);
    ui->pauseBtn->setEnabled(false);
    ui->resumeBtn->setEnabled(false);
    }




    و نتیجه کار به صورت زیر خواهد بود....
    در رابطه با پروتکل FTP هم دقیقا مثل HTTP هستش در فایل ضمیمه شده کد ها همراه با FTP وجود دارند.
    فایل های ضمیمه فایل های ضمیمه

  9. #49

    نقل قول: معرفی و آموزش C++‎‎‎‎‎‎/Qt به صورت گام به گام

    ادامه مرحله سی سوم: معرفی و با باینری و سریالیز کردن آبجکن ها

    در رابطه با بحث Serialization میتونم اینگونه توضیح دهم که به طور کلی در کامپیوتر و سیستم های ذخیره سازی محتویات فایل ها به صورت های متنی و باینتری ذخیره می شوند.
    حالا در حالت عادی یا همان پیشفرض اگر شما طبق مثال زیر رشته ای رو در داخل یک فایل بنویسیم ...


    // writing on a text file
    #include <iostream>
    #include <fstream>
    using namespace std;


    int main () {
    ofstream myfile ("example.txt");
    if (myfile.is_open())
    {
    myfile << "This is a line.\n";
    myfile << "This is another line.\n";
    myfile.close();
    }
    else cout << "Unable to open file";
    return 0;
    }


    کاملا به صورت عادی و متنی در فایل مورد نظر ذخیره خواهد شد ولی در حالت باینری تمامی اشیاء به صورت یک حالت منحصر بفرد و خاصی ذخیره می شوند یعنی قبل از ذخیره مستقیم محتویات در فایل اشیاء مورد نظر به صورت
    Byte stream تبدیل شده و سپس در فایل ذخیره می شود.

    ما در کل شاید شنیده باشید دو حالت Serialization و DeSerialization رو در بحث برنامه نویسی و مبحث ذخیره سازی داده ها داریم که به عمل تبدیل آبجکت به صورت باینری همان
    Serialization و به عکس آن عمل DeSerialization میگویند.

    حالا در این مثال من روشی رو برای خواندن و نوشتن اطلاعات در داخل یک فایل رو به صورت Serialization
    و
    DeSerializationبه کمک کلاس QDataStream توضیح خواهم داد.

    یه پروژه از نوع کنسول ایجاد میکنم و میرم سر اصل مطلب...

    من میخوام یه متنی رو به صورت زیر وارد کنم ...



    C++‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎ 1
    C++‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎ 2
    C++‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎ 3



    و در نهایت نتیجه ذخیره شده در فایل به صورت باینری باشه ! چطور باید عمل کنم به صورت زیر...


    #include <QCoreApplication>
    #include <QFile>
    #include <QString>
    #include <QDebug>
    #include <QMap>




    void SaveObject()
    {


    int iNum = 64;
    QMap<int,QString> iMap;
    iMap.insert(1,"C++‎‎‎‎‎‎‎‎‎‎‎ ‎‎‎‎‎");
    iMap.insert(2,"C++‎‎‎‎‎‎‎‎‎‎‎ ‎‎‎‎‎ 2");
    iMap.insert(3,"C++‎‎‎‎‎‎‎‎‎‎‎ ‎‎‎‎‎ 3");


    //Save to file.
    QFile iFile("c:/Test/itest.txt");


    if(!iFile.open(QIODevice::WriteOnly))
    {


    qDebug() << "Could not open file !";
    return;
    }


    QDataStream iOut (&iFile);
    iOut.setVersion(QDataStream::Qt_5_2);


    iOut << iNum << iMap;




    iFile.flush();
    iFile.close();


    }


    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);


    SaveObject();


    return a.exec();
    }




    ابتدا هیدر های QFile , QString و QMap رو فراخوانی میکنم چون هدفم نوشتن در داخل یک فایل هستش از مدل QIODevice::WriteOnly استفاده کردم.
    بعد اومدم یک تابع تعریف کردم که ابتدا به صورت سلیقه ای یک نوع صحیح در نظر گرفتم برای اینکه میخوام همراه با متن مورد نظرم مخلوط بشه و دنبال اون یک نوع رشته ای از نوع Qmap لیست ساختم و یک سری اطلاعات رو به صورت لیست ایجاد کردم.
    توسط دستور زیر یک کپی از کلاس QFile گرفتم و مسیر مورد نظرم رو برای ذخیره سازی محتوا در فایل رو دادم...


    QFile iFile("c:/Test/itest.txt");


    دستور بعدیش یک شرط تعریف کردم که اقا اگه فایل باز نشد پیغام فلان رو بده د رغیر اینصورت برو ادامه مراحل... البته دقت کنید که چون قصدم نوشتن در فایل هست از
    اصلی ترین قسمتش QDataStream هست که وظیفه این کلاس فراهم کردن امکان انتقال داده های باینری رو به مجرای QIODevice میده که اینجا من یک کپی ازش ساختم و گفتم فایلم رو در نظر بگیر و بر اساس نسخه تعیین شده که اینجا من از 5.2 خود Qt استفاده کردم رو بهش اختصاص دادم که اصولا از نسخه های اولیه Qt_1_0 بگیرید برید تا Qt_5_3 که الان هست در لیستم موجوده میتونم استفاده کنم.

    خب در خط بعدیش گفتم iNum رو که از نوع عدد صحیح هستش رو همراه با iMap مخطول و در iOut بریز که به ترتیب اولویت از راست به چپ وارد خواهد شد.
    در خط بعدی فلاش زدم که در پست های قبلی توضیح دادم کارش چیه و در نهایت فایل رو بعد از نوشتن و فلاش بستمش.

    نتیجه باید در مسیر ذکر شده به صورت باینری ذخیره شده باشه !!! به صورت ضمیمه شده میتونید دریافت و بررسیش کنید فقط مسیر فایل رو طبق شرایط خودتون تغییر بدین.

    طبق تصویر مشاهده میکنید که اطلاعات به صورت باینری ذخیره شده است ...
    نتیجه خروجی حاصل مخلوط شدن متن و اون عددی هستش که اون بالا تعریف کردم یعنی 64.

    فایل های ضمیمه فایل های ضمیمه
    آخرین ویرایش به وسیله کامبیز اسدزاده : سه شنبه 30 اردیبهشت 1393 در 01:07 صبح

  10. #50

    نقل قول: معرفی و آموزش C++‎‎‎‎/Qt به صورت گام به گام

    ادامه مرحله سی و سوم : معرفی و با باینری و سریالیز کردن آبجکن ها

    خب بریم سراغ DeSerialize کردن یا همون خواندن اطلاعات از داخل فایلی که اطلاعاتش باینری شده به صورت زیر ...

    تابع رو به صورت زیر مینویسم...


    void ReadObject()
    {


    int iNum;
    QMap<int,QString> iMap;


    //Read from file.
    QFile iFile("c:/Test/itest.txt");


    if(!iFile.open(QIODevice::ReadOnly))
    {


    qDebug() << "Could not open file !";
    return;
    }


    QDataStream iIn (&iFile);
    iIn.setVersion(QDataStream::Qt_5_2);


    iIn >> iNum >> iMap;
    iFile.close();


    qDebug() << "iNum = " << iNum;


    foreach(QString Item , iMap.values())
    {
    qDebug() << Item;
    }


    }


    خب حالا اینجا ببینید چه تغییراتی دادیم ابتدا مقدار صحیح رو خالی گذاشتم چون اینجا هدفم خوندن اطلاعات هست پس مقدار از طرف فایل گرفته و برگشت داده میشه به همین متغیر از نوع صحیح (البته منظورم از مقدار همون مقدار 64 هست که به صورت باینری ذخیره شده بود)

    مراحل بعدش دیگه از لیست QMap خبری نیست چون بازم هدف فقط خوندن هست پس میرم سر اصل مطلب...اینبار گفتم QIODevice::ReadOnly و اطلاعات رو به صورت یک رشته به من در کنسول نمایش بده توسط دستور زیر...

    ابتدا مقدار بازگشتی عدد رو در متغیر iNum ریخته و چاپش میکنم و برای محتویات رشته ای هم به صورت زیر...


    foreach(QString Item , iMap.values())
    {
    qDebug() << Item;
    }




    یه Item از نوع رشته مشخص کردم و بعد مقادیر iMap رو که بازگشت دادم دریافت و در نهایت همرو چاپ کردم.

    و نتیجه در نهایت به صورت زیر چاپ خواهد شد...


    فایل های ضمیمه فایل های ضمیمه

  11. #51

    نقل قول: معرفی و آموزش C++‎‎‎/Qt به صورت گام به گام

    ادامه مرحله سی و چهارم: معرفی و کار با TextStream ها

    در رابطه با خواندن نوشتن در رشته ها کلاسی داریم به نام QTextStream که امکان نوشتن و خواندن رو برای ما فراهم میکنه... روش کارش مشابه QDataStream در پست قبلی هستش با این تفاوت که در اینجا با رشته ها سرو کار داریم...

    پروژه ای ایجاد میکنم از نوع کنسول و میرم سراغ کد نویسی که ابتدا تابعی مینویسم برای خواندن با نام Read و تابعی مینویسم برای نوشتن با نام Write به صورت زیر...


    فایل های زیر رو فراخوانی میکنم :


    #include <QTextStream>
    #include <QFile>


    کد مربوط به Read


    void Read()


    {
    QFile MyFile("d://MyFile.txt");
    if(MyFile.open(QIODevice::ReadOnly | QIODevice::Text))
    {
    QTextStream MyStream(&MyFile);
    QString MyLine;


    do


    {


    MyLine = MyStream.readLine();
    qDebug() << MyLine;


    }


    while(!MyLine.isNull());


    }
    MyFile.close();
    qDebug() << "MyFile Read.";




    }


    و کد مربوط به Write


    void Write()


    {
    QFile MyFile("d://MyFile.txt");
    if(MyFile.open(QIODevice::WriteOnly | QIODevice::Text))
    {
    QTextStream MyStream(&MyFile);
    MyStream << "Hello \r\n";
    MyStream << "World \r\n";




    MyStream.flush();
    MyFile.close();
    qDebug() << "MyFile Written.";


    }


    }


    و در نهایت به صورت پشت سرهم هر دو تابع رو به ترتیب اول نوشتن و بعد خواندن فراخوانی میکنم...


    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);


    Write(); //First step
    Read(); //Second step


    return a.exec();
    }




    توضیحات برای این مورد لازم نیست چون همانند QDataStream پیاده سازی شده فقط با این تفاوت که از نوع انحصاری QTextStream استفاده کردیم.

  12. #52

    نقل قول: معرفی و آموزش C++‎‎‎‎/Qt به صورت گام به گام

    مرحله 35 :معرفی انواع حالت های کامپایل در Qt :

    در رابطه با حالت داینامیک (Dynamic) توضیح مختصر :
    در این حالت شما در بسیاری از موارد برای توسعه نرم افزار در دو حالت OpenSource و انحصاری قادر خواهید بود.

    جوانب مثبت و منفی زیر است:

    مزایا :


    • معمولا برنامه برای کاربر نهایی یا همان End user یک بسته جمع و جور و کامل رو فراهم میکنید و همچنین فایل اجرائی در کم حجمترین و فشرده ترین حالت خارج خواهد شد.
    • کتابخانه های Qt رو شما میتونید بدون تغییر و کامپایل مجدد پروژه آن ها را برای توسعه دهندگان بازخورد داده و یا به روز رسانی نمایید و حتی آن ها را تغییر دهید.
    • نیاز به منابع سخت افزاری بسیار کمی میباشد برای مثال اشغال حافظه Ram بسیار کمتر از حالت Static میباشد.


    معایب :


    • برای مطمئن شدن از کارائی درست برنامه در هر سیستم و هر سکویی نیاز است بارها و بارها از هر جوانبی برنامه رو نسبت به کتابخانه بررسی نمایید تا وقتی مورد استفاده توسط کاربر یا همان End - User قرار میگیرد بدون بروز مشکل یا خطایی اجرا شود , معمولا بر روی سیستم های Linux نیز باید کتابخانه های به درستی نصب گردد.
    • شما باید مطمئن شوید که تمام کتابخانه های مورد نیاز در سیستم هدف (End User) در دسترس هستند در صورتی که بر روی سیستم مورد نظر در دسترس نیستند باید راه حل مناسبی برای ارائه کتابخانه های مورد نظر فراهم نمایید و خدمات آن را در اختیار کاربر قرار دهید.




    در رابطه با حالت استاتیک (Static) توضیح مختصر :
    در این حالت شما می توانیدا مطمئن باشید که برنامه شما در هر سیستمی بدون نیاز به پیش نیازی قابل اجرا خواهد بود.

    جوانب مثبت و منفی زیر است:

    مزایا :


    • معمولا برنامه برای کاربر نهایی یا همان End user یک بسته جمع و جور و کامل رو فراهم میکنید.
    • برنامه شما میتوایند مستقل از هر نسخه از کتابخانه های موجود بر روی سیستم کاربر برنامه رو اجرا کنید حالا چه Qt4 باشه چه Qt5.3.1 باشه هیچ تداخلی نخواهد داشت.
    • کمی سریع نسبت بع حالت داینامیکی اجرا میشود که (در CPU های امروز شما به سختی آن را متوجه خواهید شد)


    معایب :


    • درخواست های برنامه شما به کتابخانه بسیار زیاد و سنگین خواهد بود زیرا کتابخانه ها نیز به برنامه شما متصل و لینک شده هستند.
    • ممکن است برای رفع مشکلات کتابخانه و تغییر / به روز رسانی و ... مجبور به کامپایل مجدد برنامه شوید.
    • مصرف منبع Ram در صورت درخواست های پی در پی و چند گانه بسیار زیاد خواهد بود.
    • در حالت Runtime شما قادر به اجرای plugins توسط QPluginLoader نخواهید بود.
    • کامپایل استاتیک بدون داشتن لیسانس مربوطه از طرف Digia مجاز نیست.


    آخرین ویرایش به وسیله کامبیز اسدزاده : جمعه 31 مرداد 1393 در 11:34 صبح

  13. #53

    Thumbs up نقل قول: معرفی و آموزش C++‎‎‎‎/Qt به صورت گام به گام

    مرحله 36 : نحوه افزودن دیگر کتابخانه های C++‎‎‎ در محیط Qt Creator و استفاده همراه با کتابخانه Qt

    سلام ؛

    امروز قصد دارم نحوه افزودن کتابخانه های دیگه رو در محیط Qt توضیح بدم با این روش شما میتونید هر کتابخانه ای رو وارد پروژه کرده و همراه با کتابخانه Qt ازش استفاده کنید برای مثال من خودم به شخصه همیشه رابط کاربری رو با Qt طراحی میکنم و برای برنامه نویسی اصلی از کتابخانه های استاندارد C++‎ و یا دیگر کتابخانه های اختصاصی مثل Boost و Poco استفاده میکنم.

    در این آموزش من نحوه وارد کردن کتابخانه Poco رو براتون توضیح میدم.


    زبان C/C++‎‎‎‎‎‎‎‎‎‎‎‎‎ یکی از قابلیت هایی که نسبت به زبان های دیگری مانند C#‎‎‎‎‎‎‎‎‎‎‎‎‎ یا غیره داره نامحدود بودن استفاده از کتابخانه های این زبان هست که به صورت پیشفرض کتابخانه های استاندارد و از قبل تعریف شده در زبان C++‎‎‎‎‎‎‎‎‎‎‎‎‎ قابل استفاده هستند مانند کلاس های iostream و ... که کاملا پیشفرض روز این زبان ارائه شده است.
    حالا در رابطه با این موضوع باید توضیحی بدم که اگر برنامه نویس یا توسعه دهنده ای نیازمند استفاده از کتابخانه ای منحصربفرد رو داره میتونه اون رو به زبان C++‎‎‎‎‎‎‎‎‎‎‎‎‎ اضافه کنه و ازش استفاده کنه برای مثال من برای کار با شبکه و اینترنت کتابخانه POCO رو ترجیح میدم پس برای استفاده از این ابتدا باید پیکربندی و آماده سازی لازم رو انجام بدم به صورت زیر عمل میکنم.


    ابتدا کتابخانه رو دانلود میکنم و در مسیر مقابل به صورت دلخواه قرار میدم : C:\poco-1.5.3-all (من امروز در محیط ویندوز هستم برای همین روی ویندوز این رو توضیح میدم توضیحات دقیقا روی محیط Linux هم صدق میکنه تفاوت چندانی نداره فقط باید کتابخانه رو از قبل کامپایل کرده باشید)


    قبل از هر چیزی باید بدونید که هر کتابخانه دارای libs و include هستش هر نوع کتابخانه ای که دانلود کنید این دو تا گزینه رو باید داشته باشه که بعد از کامپایل کتابخانه فایل lib و dll هاش در ویندوز یا Linux ایجاد خواهد شد.


    من به دلیل پیچیده بودن کتابخانه POCO (پوکو) رو انتخاب کردم چون شامل کتابخانه های مربوط به Net و ... هستش که برای آموزش هدف من کار با Net هست بنابراین پوشه های include و libs در کنار هم نخواهند بود لذا include مربوط به هر کتابخانه در داخل خودش قرار گرفته.

    خب بریم سر اصل مطلب ابتدا یه پروژه ای ایجاد میکنم با نام MyLibs از هر نوعی ایجاد میکنید مهم نیست.

    روی پروژه طبق تصویر راست کلیک کنید و گزینه Add library رو بزنید.


    بعد چنجره زیر نماین میشه که شامل گزینه های زیر هستش :



    1. گزینه Internal Library مربوط هست برای زمانی که شما کتابخانه رو در داخل پروژه خودتون ایجاد کردین که معمولا مسیر واقع توسط فایل .pro مشخص خواهد شد به طور کلی کتابخانه های داخلی و غیر External رو میتونید از این قسمت شناسایی کنید.
    2. گزینه External library از این گزینه زمانی استفاده میشه که کتابخانه ما در مسیر پروژه ما نیستش یا به طور کلی در داخل پروژه ما قرار نگرفته دقیقا برعکس گزینه اول که میشه همون کتابخانه خارجی یا خارج از پروژه.
    3. گزینه System library هم مربوط میشه به کتابخانه های سیستمی هستش.
    4. و یک گزینه ای هم خواهیم داشت در محیط های Unix که به نام Package Library قابل مشاهده خواهد بود این گزینه هم زمانی مورد استفاده قرار میگیره که شما نیاز دارید کتابخانه رو از طریق سرویس pkg-config در ایستگاه های Unix که شامل Mac OS X و Linux هستش تنظیم کنید.


    حالا ما با این ها کاری نداریم و در استاندارد ترین حالت از External Library استفاده خواهیم کرد بنابراین گزینه External Library رو انتخاب و Next میزنیم.

    l3.png

    خب در این قسمت ما گزینه هایی داریم که مربوط به پیکربندی و مشخص کردن مسیر کتابخانه ای هستش که از قبل کامپایل و خروجی های lib و یا dll اون مشخص شده است.
    بنابراین گزینه ها وظایف زیر رو دارند :

    1. گزینه Library file مربوط هست به مسیر فایل های مربوط به libs موجود در کتابخانه برای مثال مسیر lib برای کتابخانه Poco در ایستگاه ویندوزی من هستش : C:\poco-1.5.3-all\lib پس روی گزینه Browse کلیک کرده و این مسیر رو با انتخاب فایل مورد نظرم مثلا PocoNetd.lib مشخص میکنم در نهایت مسیر میشه به صورت : C:\poco-1.5.3-all\lib\PocoNetd.lib
    2. گزینه Include path مربوط هستش به پوشه Include مربوط به کتابخانه که شامل فایل های .h یا همون هدر هاست بنابراین برای اینکه Include مربوط به کلاس های Net رو انتخاب کنم میرم به مسیر : C:\poco-1.5.3-all\Net\include که شامل Include های مشخص برای فایل Net هست.
    3. گزینه Platforms مشخص کننده مسیر در فایل .pro برای نوع سیستم عامل هستش.
    4. گزینه Linkage - Dynamic مشخص کننده کتابخانه از نوع Dynamic یا Static و گزینه Framework هستش.
    5. و در آخر گزینه ای داریم که مختص ویندوز هست.


    تنظیمات رو به صورت زیر انجام میدیم و Next رو میزنیم.

    l4.png

    و در نهایت Finished و سپس در داخل فایل .pro کد های زیر رو خواهیم دید.


    win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../../../../../poco-1.5.3-all/lib/ -lPocoNet
    else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../../../../../poco-1.5.3-all/lib/ -lPocoNetd
    else:unix: LIBS += -L$$PWD/../../../../../poco-1.5.3-all/lib/ -lPocoNet


    INCLUDEPATH += $$PWD/../../../../../poco-1.5.3-all/Net/include
    DEPENDPATH += $$PWD/../../../../../poco-1.5.3-all/Net/include


    کتابخانه من آماده هستش ولی چون در Poco برای استفاده از کلاس مورد نظر پیش نیازی داریم به نام Foundation پس اون گزینه رو هم باید طبق روشی که گفتم اضافه کنیم که در نهایت به صورت زیر خواهد بود :


    win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../../../../../poco-1.5.3-all/lib/ -lPocoNet
    else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../../../../../poco-1.5.3-all/lib/ -lPocoNetd
    else:unix: LIBS += -L$$PWD/../../../../../poco-1.5.3-all/lib/ -lPocoNet


    INCLUDEPATH += $$PWD/../../../../../poco-1.5.3-all/Net/include
    DEPENDPATH += $$PWD/../../../../../poco-1.5.3-all/Net/include


    win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../../../../../poco-1.5.3-all/lib/ -lPocoFoundation
    else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../../../../../poco-1.5.3-all/lib/ -lPocoFoundationd
    else:unix: LIBS += -L$$PWD/../../../../../poco-1.5.3-all/lib/ -lPocoFoundation


    INCLUDEPATH += $$PWD/../../../../../poco-1.5.3-all/Foundation/include
    DEPENDPATH += $$PWD/../../../../../poco-1.5.3-all/Foundation/include


    خب حالا فایل .pro رو Save کرده و روی گزینه build و بعد Run qmake کلیک میکنیم تا پروژه با تغییراتی که داده شد پیکربندی و آماده شود.

    برای آزمایش کد زیر رو مینویسم و کتابخانه بدون مشکل قابل دسترسی و استفاده هستش :


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


    #include <Poco/Net/Net.h>
    #include <Poco/Net/MailMessage.h>


    using namespace Poco::Net;


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


    MailMessage mail;
    }


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




    فقط بازم تاکید میکنم نوع کامپایلری که کتابخانه رو باهاش کامپایل کردین خیلی مهمه مثلا من از قبل این کتابخانه رو با MSVC 2013 نسخه 32 بیت در مد Debug کامپایل کردم پس در Qt هم باید از مد Debug و کامپایلر MSVC 2013 با معماری 32 بیت استفاده کنید.

    نه تنها Poco من این مثال رو فقط برای آموزش مراحل تعریف کتابخانه زدم بنابراین از تمامی کتابخانه ها به همین روش میتونید استفاده کنید.

    شاد و پیروز باشید.

  14. #54

    نقل قول: معرفی و آموزش C++‎‎‎/Qt به صورت گام به گام

    دوستان همانطور که از قبلا اشاره شده بود طی این مدت سعی کردم با بهینه سازی آموزش های جاری و توسعه آن و همچنین اشاره به سوالاتی که درخواست شده بود کرده ام که در نهایت منجر به ویرایش و دریافت مجوز برای کتاب به صورت رسمی شد بنابراین شما میتوانید برای دریافت "آموزش زبان ++C همراه با کتابخانه Qt 5.5.x (سطح مقدماتی ویرایش ۲)" اقدام نمایید.

    بررسی و دریافت نسخه رسمی کتاب

    برای مشاهده ادامه فعالیت‌ها به انجمن‌های https://forum.iostream.ir رجوع نمایید.
    آخرین ویرایش به وسیله کامبیز اسدزاده : دوشنبه 07 خرداد 1397 در 17:55 عصر دلیل: انتشار کتاب

صفحه 2 از 2 اولاول 12

تاپیک های مشابه

  1. آموزش Crystal Report (به صورت حرفه ای کار کنید)
    نوشته شده توسط In_Chan_Nafar در بخش گزارش سازی با Crystal Report
    پاسخ: 27
    آخرین پست: جمعه 29 فروردین 1393, 11:54 صبح
  2. آموزش: آموزش برنامه نویسی به زبان اسمبلی به صورت گام به گام
    نوشته شده توسط JaVa در بخش برنامه نویسی اسمبلی خانواده x86
    پاسخ: 8
    آخرین پست: سه شنبه 08 بهمن 1392, 09:19 صبح
  3. سری آموزش ado.net به صورت فایل word
    نوشته شده توسط zarrin_306 در بخش VB.NET
    پاسخ: 7
    آخرین پست: چهارشنبه 06 آبان 1388, 17:35 عصر
  4. آموزش Intraweb به صورت گام به گام
    نوشته شده توسط حمیدرضاصادقیان در بخش توسعه نرم افزار تحت وب
    پاسخ: 3
    آخرین پست: دوشنبه 03 تیر 1387, 21:07 عصر
  5. آموزش گام به گام کار با پلت کامپوننتهای دلفی
    نوشته شده توسط nasr در بخش برنامه نویسی در Delphi
    پاسخ: 15
    آخرین پست: شنبه 30 خرداد 1383, 18:36 عصر

برچسب های این تاپیک

قوانین ایجاد تاپیک در تالار

  • شما نمی توانید تاپیک جدید ایجاد کنید
  • شما نمی توانید به تاپیک ها پاسخ دهید
  • شما نمی توانید ضمیمه ارسال کنید
  • شما نمی توانید پاسخ هایتان را ویرایش کنید
  •