Мы — долго запрягаем, быстро ездим, и сильно тормозим.
www.lissyara.su —> статьи —> FreeBSD —> Programming —> Создание программ на QT4/С++

Создание программ на QT4/С++

Автор: Fastman.


  Это статья не претендует на руководство 'как правильно', это описание удобного мне окружения для написания программ при помощи кросплатформенного набора классов Trolltech QT4. Почему QT4? Не в обиду другим средствам разработки - это наиболее вменяемый тулкит который вмещает в себя как классы для создания GUI так и множество полезных классов например для работы с xml, сокетами, файлами, директориями итд...
 На сегодняшний день в портах версия 4.3.1, поэтому все что будет тут написано - относится именно к этой версии QT. Для тех кому интересно уже сейчас есть возможность скачть версию QT4.4 в которой появились WEBkit(классы для разработки web-приложений) и Phonon(классы для работы с мультимедиа). А еще за что я полюбил продукт QT - так это за документацию....не поленитесь после установки сразу запустить Assistant и вы поймете о чем я говорю.
Обновляем порты и ставим QT:
fast# cd /usr/ports/devel/qt4

fast#make install clean

Если собираетесь работать с базами данных(mysql,postgree,sqlite etc) отметьте пункт:
[ ] SQL_PLUGINS Database connectivity plugins for QtSql

в этом случае соберутся плагины для работы с базами данных.
Приготовьтесь, потащится довольно много.. в итоге мы получим следующие модули:

Qt Core Module — ядро Qt
Qt GUI Module — Qt классы и модули для создания GUI
Network Module — платформо-независимые классы для работы с сокетами, TCP, FTP и DNS.
OpenGL 3D Graphics Module — OpenGL классы для 3D визуализации.
Database Module — модули для работы с SQL базами данных.
XML Module — XML парсер (SAX2 и DOM Level 2 интерфейсы)
Если все собралось без ошибок, проверим:
fast# qmake-qt4 -v
QMake version 2.01a
Using Qt version 4.3.1 in /usr/local/lib

Теперь добавим в .cshrc переменную QMAKESPEC которая будет указывать для какой платформы qmake-qt4 будет производить сборку, у меня это так выглядит:
fast# cat .cshrc | grep QMAKESPEC
setenv QMAKESPEC freebsd-g++

В принципе этого в начале достаточно чтобы писать под QT. Но очень неудобно ;) Поэтому нужно выбрать IDE(или текстовый редактор с ф-циями IDE). Это тема многих религиозных войн, я не буду навязывать какой либо редактор и советовать только его. Я для себя выбрал QDevelop. Вот примерно как это выглядит:


Это в принципе не совсем полноценная IDE, но писать код можно, автодополнение кода можно настроить, отладка приложения тоже присутствует... что еще надо? Мне этого хватает. Кто будет юзать эту IDE, вот что нужно прописать в настройках. Почему make выдает ошибку я не разбирался, работает и так.


Конечно все это интересно, но без примеров - это пустой звук. Удобность любого инструмента можно узанть только в процессе работы. Поэтому я решил привести тут небольшой 'hello world'. В кавычках - потому что никому не интересно вывести на форму этот текст... обычно хочется сразу увидеть особонности инструмента и функционал. Поэтому сейчас я приведу пример небольшого приложения с минимальным GUI которое позволит скачать на локальный диск видео с youtube.com. То есть вставив ссылку из строки браузера в приложение и нажав одну кнопку на форме - вы получите на локальном диске файл с расширением flv который можно просмотреть допустим mplayer-ом.
Придумаем минимальный дизайн нашей формы.


Окошко будет содержать строку ввода ссылки (элемент lineEdit), кнопку (элемент pushButton), и область в которой будет отображаться ход обработки нашего задания (элемент listWidget).
Окошко будем рисовать в QtDesigner, он входит в состав Qt 4.3.1, все предельно просто, этому инструменту посвящена целая глава документации. Вот скриншот того как это происходит:


После того как мы создали 'дизайн' окошка, можно наполнять смыслом наше приложение. Вообще, хочу предостеречь тех кто начинает программирование на С++, дизайн конечно дело не последнее, но лучше изначально продумать архитектру своего приложения, и поверьте если вы это сделаете правильно, то написав все приложение вы ЛЕГКО подцепите к нему дизайн. Если же функционал вашего приложения жестко зависит от визуальной части - вы что то перемудрили и сделали неправильно. Qt4 позволяет писать и консольные приложения которые не требуют наличия X-ов в вашей системе.
Прежде чем приводить код приложения поясню. Во первых, это приложение можно написать 10-30 строчками на том же перле или любом другом скриптовом языке, это факт. Это приложение можно легко переписать и сделать его более изящным и красивым. Я сделал его специально таким 'угловатым', некрасивым с точки зрения архитектуры и построения чтобы показать максимальное количество возможностей в таком маленьком приложении и чтобы вы сами могли увидеть что можно допилить до удобоваримого вида.Комментарии будут приведены минимальные, по просьбам трудящихся в дальнейшем откомментирую непонятные куски.
main.cpp
Тут мы строим главное окно приложения, и говорим что будем ловить сигнал закрытия приложения.
#include <QtGui/QApplication>
#include "youtubed.h"

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	YouTubeD w;
	w.show();
	a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
	return a.exec();
}

youtubed.h
Этот класс у нас будет отвечать за визуальную часть приложения.
#ifndef YOUTUBED_H
#define YOUTUBED_H

#include <QtGui/QMainWindow>
#include "ui_youtubed.h"
#include "Thread.h"
#include <QString>

class YouTubeD : public QMainWindow
{
	Q_OBJECT

public:
	YouTubeD(QWidget *parent = 0, Qt::WFlags flags = 0);
	~YouTubeD();

protected:
    //Не очень весело когда рабочие задания выполняются в главном потоке
    //Поэтому все что не относится к отображению на форме элементов 
    //мы выносим в отдельный поток
    //Вот и обьявляем переменную класса Thread
	Thread *TubeThread;

private:
    //Ui - это класс который автоматически генерируется 
    //из формы которую вы нарисовали
    //Там обьявлены все графические элементы/виджеты которые есть на форме
    //Но никто не запрещает вам самим динамически их создавать.
	Ui::YouTubeDClass ui;

private slots:
    //Этот слот сработает если вы жмякнете на кнопку
	void on_pushButton_clicked();
    //А этот когда прийдет сообщение из потока. 
    //Нельзя напрямую из потока дергать ф-ции графики
    //на форме, поэтому один из методов - передача сигналов.
	void GUImsg(QString msg);
	

};
#endif // YOUTUBED_H

youtubed.cpp
#include "youtubed.h"

YouTubeD::YouTubeD(QWidget *parent, Qt::WFlags flags)
	: QMainWindow(parent, flags)
{
	ui.setupUi(this);
}

YouTubeD::~YouTubeD()
{

}

void YouTubeD::on_pushButton_clicked()
{
    //Надеюсь все понятно, все до боли знакомо :)
	QString cUrl("");
	ui.listWidget->clear();
	cUrl = ui.lineEdit->text();
        
    //Ну по хорошему надо придумать как проверять на валидность URL 
    //а не проверять не пустой ли он вообще
	if (cUrl.size())
	{
    //Если URL не пустой - выделяем память под наш поток
	TubeThread = new Thread(cUrl);
    //Будем ловить сигнал из нашего потока с сообщениями
    connect(TubeThread, SIGNAL(msgToGUI(QString)), this, SLOT(GUImsg(QString)));
	TubeThread->start();
	}
	else
		ui.listWidget->addItem("URL empty !");
	
}

void YouTubeD::GUImsg(QString msg)
{
	ui.listWidget->addItem(msg);
}

Thread.h
Потоковый класс.
#ifndef THREAD_H
#define THREAD_H
#include <QThread>
#include "TubeDownload.h"

class Thread : public QThread
{
	Q_OBJECT

public:
	Thread(QString cUrl, QObject *parent = 0);
	~Thread();

	CTubeDownload *nDownld;
	QString cUrl;

protected:
	void run();

private slots:
	void FinishProc();	

signals:
	void msgToGUI(QString cMesage);
};
#endif // THREAD_H

Thread.cpp
#include "Thread.h"

Thread::Thread(QString cUrl, QObject *parent)
	: QThread(parent), cUrl(cUrl)
{
	
}

Thread::~Thread()
{
	if (nDownld != NULL)
		delete nDownld;
	QThread::exit();
	QThread::wait();
	
}

void Thread::run()
{
	nDownld = new CTubeDownload;
	connect(this, SIGNAL(finished()), this, SLOT(FinishProc()));
	connect(nDownld, SIGNAL(msgToGUI(QString)), this, SIGNAL(msgToGUI(QString)));
	QString lnk = nDownld->GetDownloadLink(cUrl);
	QString file = nDownld->DownloadFLV(lnk);
}

void Thread::FinishProc()
{
	this->~Thread();	
}

TubeDownload.h
#pragma once
#include <QString>
#include <QFile>
#include <QProcess>
#include <QTextStream>
#include <QtDebug>
#include <QDir>
#include <QUrl>
#include <QCoreApplication>
#include <QTime>

class CTubeDownload : public QObject
{
	Q_OBJECT

public:
	CTubeDownload(void);
	~CTubeDownload(void);

	QString GetDownloadLink(const QString cUrl);
	QString DownloadFLV(const QString cLink);
	
private:
	QProcess *zProc;
	QString cTmpPath;

signals:
	void msgToGUI(QString cMesage);

};

TubeDownload.cpp
Тут мы пользуемся wget-ом. Не совсем хорошо. Лучше подумать и сделать
на основе QHttp класса все. Я просто хотел показать как из своей программы
запускать другую, и как работать с файлами в QT4.
#include "TubeDownload.h"
CTubeDownload::CTubeDownload(void)
{
//Таким макаром можно сделать кроссплатформ дефайны
#ifdef Q_OS_WIN32
	#define cPWget  "d:\\wget.exe";
#endif 

#ifdef Q_OS_FREEBSD 
	#define cPWget  "/usr/local/bin/wget";
#endif 

}

CTubeDownload::~CTubeDownload(void)
{

}

QString CTubeDownload::GetDownloadLink(const QString cUrl)
{
	QString cLink(cUrl);
	QString cWgetLine("");
	QString cTmpFile("tmp.file");

    cTmpPath = QDir::tempPath();
	cTmpFile.prepend(cTmpPath);

	cWgetLine = cPWget;
	cWgetLine += " -O ";
	cWgetLine += cTmpFile;
	cWgetLine += " ";
	cWgetLine += cLink;
	
	zProc = new QProcess(this);
	emit msgToGUI("Get file to parse. Please wait...");
	zProc->execute(cWgetLine);
	emit msgToGUI("Get file to parse - ok !");

	QFile file(cTmpFile);
	if(!file.open(QIODevice::ReadOnly))
		return NULL;
 	
	QTextStream in(&file);
	QString idFlv("");
	QString FullPathURL("");
	
	emit msgToGUI("Parse file.");

	while (!in.atEnd()) 
	{
		QString line = in.readLine();
		if((line.contains("fullscreenUrl", Qt::CaseInsensitive)))
		{
			idFlv = line.simplified();
		}
	} 

	file.close();
	file.remove();

	emit msgToGUI("Parse file - ok !");
	emit msgToGUI("Create full link to file.");
    //Грязный хак ! Не делайте так никогда :) 
    //Нормально распарсите полученный файл :)
	idFlv = idFlv.mid(38, idFlv.length()-(38+2));
	
	FullPathURL = "http://www.youtube.com/get_video";
	FullPathURL += idFlv;

	emit msgToGUI("Create full link to file - ok !");
	
	return FullPathURL;
}

QString CTubeDownload::DownloadFLV(const QString cLink)
{
	QString cDwnldFileName("");
	QString cLinkFLV("");

	qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
	
	cLinkFLV = cPWget;
	cLinkFLV += " -O ";
	cLinkFLV += QDir::homePath();
	cLinkFLV += "/";
	cLinkFLV += QString::number((int)(qrand()));
	cLinkFLV += ".flv  ";
	cDwnldFileName = cLinkFLV;
	cLinkFLV += cLink;

	zProc = new QProcess(this);
	emit msgToGUI("Download FLV file. Please wait...");
	zProc->start(cLinkFLV);
	zProc->waitForFinished(-1);
	emit msgToGUI(cDwnldFileName);
	emit msgToGUI("Download FLV file - ok !");
   
	return cDwnldFileName;
}

Вот готовый проект который вы можете скачать и поиграться.

YouTubeD
файл скачан размер размещён примечание
YouTubeD.tar
2118 26.5kb 2008-01-20 Если у вас установлен и правильно настроен QT4.3.1 то после развертывания архива необходимо сделать только make. Приложение требует установленного в системе wget.

Вот рабочий скрин:



У меня есть неплохая книга с примерами для нее отдельно. Как только починят и будет доступ к ftp - выложу.

Сссылки и ресурсы:
http://trolltech.com - Офф. сайт разработчиков.
http://www.qtcentre.org - Супер ресурс с просто офигительным форумом.



размещено: 2008-01-21,
последнее обновление: 2008-01-21,
автор: Fastman


Happy_demon, 2008-01-21 в 16:48:29

Это просто здорово! Респект и уважуха! Буквально только что на форуме задавал именно такой вопрос про скачку с ютуба. домой приду - обязательно соберу.

lissyara, 2008-01-21 в 17:10:49

А что, поиск по портам давно отменили?
Насколько я помню, там валяется прога с почти таким же названием =)

Fastman, 2008-01-22 в 16:30:28

Happy_demon :)
Это не для того чтобы качать видео с ютуба вообще то :)
Это пример как в принципе это можно сделать :)

JAM, 2008-04-04 в 12:30:45

Супер пример! Автору уважуха!

melanye, 2008-07-19 в 2:13:49

под Виндой wget сохраняет лишь HTML-код странички :( =)
может нужна ссыль на сам flv? а то там одни удобочитаемые и человекупонятные modrewrite-ы...

Fastman, 2008-07-19 в 10:48:24

to melanye:
Виндовый и Unix-овый wget-ы отличаются.
Если хочешь разобраться - пиши в форум.

melanye, 2008-07-19 в 12:40:56

я так и думала, под линухом прога наверное сама все делает, а под виндой нужны какие то модули добавлять:(

очепятка, 2008-09-08 в 21:41:17

Че означает слово "узанть"?

EugeneVC, 2008-11-21 в 11:36:06

Добавьте еще
www.prog.org.ru - русский форум по QT

Ilja, 2008-12-21 в 13:28:30

Большое спасибо!
Теперь я с QT разобрался!
если честно, lissyara- ты мой кумир )

lissyara, 2008-12-21 в 15:17:00

Та я то тут причём... =(
Автора кроме низа страницы, приписали вверху, до кучи.
Всё равно не видят =(

IceD, 2009-03-12 в 8:54:00

по поводу юзабилити и автора приписали -
наверху напиши его слева или справа, а то он под заголовком теряется, шрифт сделай другой (пожирнее чтоли)

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

adre, 2009-06-18 в 14:58:59

Пойду поточу - забористая вешь )

VampireNF, 2009-11-01 в 13:47:06

Может вопрос и простой, но всё же :) Как этот QDevelop заставить авто-дополнять код? Не пойму никак. Да и вместо ctags он сам поставил exctags, на обычный ctags ругается и говорит, что старьё.

Fastman, 2009-11-04 в 13:30:19

Пишите на форум товарщи.. сообщение тут - могу просто пропустить. В свете последних дней, юзайте Qt Creator IDE.
Он есть в портах.

fox, 2010-07-31 в 17:50:28

А какие IDE оболчки под Qt или вообще С/C++ бывают с русской локализацией кроме Qt Creator и Qdevelop???

Zeka13, 2013-01-06 в 15:24:22

не QT, а Qt!



 

  Этот информационный блок появился по той простой причине, что многие считают нормальным, брать чужую информацию не уведомляя автора (что не так страшно), и не оставляя линк на оригинал и автора — что более существенно. Я не против распространения информации — только за. Только условие простое — извольте подписывать автора, и оставлять линк на оригинальную страницу в виде прямой, активной, нескриптовой, незакрытой от индексирования, и не запрещенной для следования роботов ссылки.
  Если соизволите поставить автора в известность — то вообще почёт вам и уважение.

© lissyara 2006-10-24 08:47 MSK

Время генерации страницы 0.0782 секунд
Из них PHP: 31%; SQL: 69%; Число SQL-запросов: 83 шт.
Исходный размер: 56176; Сжатая: 13010