|
|
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
|
Если собираетесь работать с базами данных(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
|
файл
|
скачан
|
размер
|
размещён
|
примечание
|
|
2133
|
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
|
|
|
|
2014-07-27, lissyara
gmirror
Удалённое создание софтверного зеркала средствами gmirror, на диске разбитом с использованием gpart. Использование меток дисков для монтирования разделов.
2013-08-20, zentarim
Scan+Print server FreeBSD 9
Настройка сервера печати и сервера сканирования под управлением операционной системы FreebSD 9 для МФУ Canon PIXMA MP540
2011-11-20, BlackCat
Разъём на WiFi-карту
Делаем съёмной несъёмную антену на WiFi-карте путём установки ВЧ-разъёма
2011-09-14, manefesto
Настройка git+gitosis
Настройка системы контроля версия исходного кода в связке git+gitosis+ssh
2011-08-14, zentarim
Wi-FI роутер + DHCP + DNS
Настройка Wi-Fi роутера на Freebsd 8 + DNS сервер + DHCP сервер: чтобы Wi-Fi клиенты были в одной подсети с проводными, проводные и беспроводные клиенты получали адреса автоматически по DHCP, кэширующ
2011-06-15, -ZG-
Охранная система на FreeBSD+LPT
В этой статье описана попытка реализации простой охранной системы на базе FreeBSD с подключением к ней охранных устройтсв на LPT порт и видеорегистрацией.
2011-03-13, terminus
ng_nat
Описание работы ng_nat, практическое использование, достоинства и недостатки в сравнении с ipfw nat
2011-02-20, Капитан
Nagios+Digitemp
Статья описывает создание системы оповещения о превышении температуры в специальных помещениях на основе Nagios с использованием программы Digitemp.
2011-02-17, Le1
Zyxel Configuration
Скрипт для массового изменения конфига свичей Zyxel. Берет из файла iplist список ip-шек, заходит последовательно на каждый и выполняет комманды из файла commands, записывая происходящее в лог файл.
2011-02-16, fox
hast carp zfs ucarp cluster
HAST (Highly Available Storage), CARP, UCARP, ZFS, Cluster настройка и одаптация плюс личные размышления…
2011-02-04, BlackCat
Восстановление ZFS
История о том, как был восстановлен развалившийся RAIDZ ZFS-пул (перешедший в FAULTED) с помощью скотча и подручных средств. Или о том, какие приключения ожидают тех, кто не делает резервных копий.
2011-02-03, Капитан
1-Wire
Статья описывает самостоятельное изготовление контроллера DS9097 для съёма показаний с датчиков температуры DS1820 с помощью программы Digitemp.
2011-01-28, Капитан
Температура в серверной
Статья описывает построение системы наблюдения за температурой в помещении серверной с использованием программы Digitemp и выводом графиков в MRTG
2011-01-21, m4rkell
Syslog server
Как то буквально на днях, у нас завалилось, что то в еве) или не в еве не суть. Суть в том, что когда захотели снять логи с хостов esx обнаружили, что хранят эти негодяи логии только за последнии сутк
2011-01-07, lissyara
Canon/gphotofs
Монтирование цифровых фотоаппаратов Canon (PTP) как файловой системы, автоматизация этого процесса через события devd и внешние скрипты.
2010-12-13, Al
IPSec
Описание принципов работы IPSEC и способов аутентификации.
2010-12-07, manefesto
FreeBSD on flash
Было принято решении переехать на USB Flash и установить минимальный джентельменский набор для работы своего роутера. Делаем =)
2010-12-05, Fomalhaut
root ZFS, GPT
Инструкция по установке FreeBSD с использованием в качестве таблицы разделов GPT и в качестве основной файловой системы - ZFS
2010-09-05, Cancer
Настройка аудиоплеера на ximp3
Цели: Простенький аудиоплеер, для того что бы тетя продавец в магазине утром пришла нажала на кнопку Power и заиграла в зале музыка, так же был доступ по сети, общая шара куда можно заливать музыку, к
2010-08-31, Cancer
Установка и настройка OpenVPN
На днях появилась задача - объединить головной офис и 3 филиала в одну сеть через интернет посредством OpenVPN, чтобы люди могли подключаться через RDP к базам 1С на серверах.
2010-08-25, manefesto
freebsd lvm
Использование linux_lvm для работы с LVM разделами из-под FreeBSD. Проблемы которые возники при монтирование lvm раздела
2010-04-30, gonzo111
proftpd file auth"a
Proftpd - квоты и авторизация из файлов, без использования базы данных и/или системных пользователей
2010-04-22, lissyara
tw_cli
Пошаговая инструкция по восстановлению RAID на контроллере 3ware, из которого выпал один диск. Настройка мониторинга состояния рейда и отчётов о его состоянии на email.
2010-04-14, fox
MySQL Master+Master
MySQL (Master Master) and (Master Slave) Как настроить репликацию…
2010-03-09, terminus
DNS zones
Краткий ликбез про управление DNS зонами. Примеры проведения делегирования прямых и обратных DNS зон.
2010-03-09, aspera
Squid+AD (group access)
Настройка прокси сервера SQUID с автроризацией пользователей в AD. Разделение пользователей на группы
2010-03-02, BlackCat
Шлюз: Часть 4
Настройка дополнительных сервисов: синхронизация времени (OpenNTPD), клиент DynDNS.org.
2010-03-01, BlackCat
Шлюз: Часть 3
Настройка DHCP и DNS серверов для работы внутри частной сети, c поддержкой внутренних (частных зон) DNS, а так же интеграция DHCP и DNS сервисов.
2010-03-01, BlackCat
Шлюз: Часть 2
Конфигурация МСЭ pf для проброса портов с изменением порта назначения и без, а так же поддержки активного режима FTP и ограничения максимального размера сегмента
2010-03-01, BlackCat
Шлюз: Часть 1
Быстрая настройка шлюза/маршрутизатора с установлением PPPoE-соединения, поддержкой NAT и DNS-forwarding.
2010-02-23, Morty
darkstat
Простая считалка траффика, со встроенным веб-сервером. Очень маленькая, может делать отчеты трафика по хостам, портам, протоколам, а также строить графики
2010-01-23, gonzo111
squid+sams+sqstat
Пилим squid и sams - примеры конфигов с объяснениями. Установка SqStat.
2009-12-19, schizoid
mpd5 + radius + ng_car + Abills
Настройка pppoe-сервера с биллинговой системой Abills и шейпером ng_car
2009-11-16, lissyara
UFS->ZFS
Удалённая миграция с UFS на ZFS. Загрузка с раздела zfs. Настройка для работы с малым количеством памяти под архитектурой i386.
2009-11-13, gx_ua
fusefs-ntfs
Установка, настройка и использование fusefs-ntfs, драйвер NTFS, предназанченного для монтирования NTFS разделов под FreeBSD
2009-11-12, Morty
LiveCD
Создание собственного LiveCD с необходимыми вам изменениями, автоматизирование данного процесса, а так же вариант скоростной сборки СД.
2009-09-27, lissyara
Samba как PDC
Контроллер домена - аналог M$ NT4 домена под самбой, без использования LDAP и прочей хиромантии. Просто и быстро =)
2009-08-30, terminus
ipfw nat
Подробное руководство по ipfw nat, сложные случаи конфигурации.
2009-08-24, levantuev
HotSpot
Установка Hotspot системы в общественное заведение.
2009-08-18, lissyara
diskless
Создание бездисковых терминалов под управлением FreeBSD - с загрузкой по сети. Используются для старта rdesktop и подключения к виндовому серверу терминалов.
2009-07-29, BAV_Lug
Видеонаблюдение
Настройка бюджетного варианта видеонаблюдения на удаленном объекте
2009-07-22, Cancer
OpenLDAP адресная книга
Настройка и создание адресной книги на базе OpenLDAP + phpLDAPadmin
2009-06-30, SergeySL
AimSniff
Руководство по созданию системы мониторинга ICQ-переписки на базе AimSniff, использующей базу данных MySQL для хранения и Web-интерфейс WAS (Web Aim Sniff) для просмотра перехваченных сообщений
2009-06-25, atrium
Управление правами доступа
Полномочия пользователей и файлов, принадлежащих им, формирует концепцию ОС UNIX.
|
Комментарии пользователей [17 шт.]