Просмотр сообщений
|
Страниц: 1 ... 66 67 [68] 69
|
1008
|
Qt / 2D и 3D графика / Re: сохранение элементов QGraphicsScene в файл
|
: Май 08, 2011, 17:26
|
при этом проще добавить в наследники итемов методы загруски и сохранения. как я делал: для базового класса, который наследуется от graphicsITem добавил 2 виртуальных метода loadFromStream и saveToStream, которые отвеяают за загрузку и сохранение item в поток(но я на самом деле храню в XML-дереве). такой подход позволяет расширять возможности загрузки/сохранения в наследниках. вот пример базового класса для элементов (для виджетов на сцене у меня свой класс, но суть таже) class QRailItem : public QObject, public QGraphicsItem { Q_OBJECT Q_INTERFACES (QGraphicsItem) public: virtual void loadFromStream(QDomDocument * doc,QDomElement * node); virtual void saveToStream(QDomDocument * doc,QDomElement * node); };
вот реализация void QRailItem::loadFromStream(QDomDocument * /*doc*/, QDomElement * node) { QDomElement railItemNode = node->firstChildElement("RailItemData"); //нода класса QRailItem if(!railItemNode.isNull()) { bool ok; QPointF pos; id = railItemNode.attribute("ObjectID","0").toLong(&ok); setRotation(railItemNode.attribute("Angle").toFloat(&ok)); pos.setX(railItemNode.attribute("PosX").toFloat(&ok)); pos.setY(railItemNode.attribute("PosY").toFloat(&ok)); this->setPos(pos); setZValue(railItemNode.attribute("ZValue","0").toFloat(&ok)); } }
void QRailItem::saveToStream(QDomDocument * doc, QDomElement * node) { QDomElement railItemNode = doc->createElement("RailItemData"); //создаю ноду класса QRailItem railItemNode.setAttribute("ObjectID",id); railItemNode.setAttribute("PosX",pos().x()); railItemNode.setAttribute("PosY",pos().y()); railItemNode.setAttribute("Angle",rotation()); railItemNode.setAttribute("ZValue",zValue()); node->appendChild(railItemNode); }
теперь пример наследника class QSection: public QRailItem { Q_OBJECT public: void loadFromStream(QDomDocument * doc,QDomElement * node); void saveToStream(QDomDocument * doc,QDomElement * node); };
сохраняем наследника void QSection::loadFromStream(QDomDocument * doc,QDomElement * node) { QRailItem::loadFromStream(doc,node); //загрузка части предка QDomElement sectionNode = node->firstChildElement("SimpleSectionData"); //находим часть этого класса if(!sectionNode.isNull()) //далее все грузится все что касается этого класса, так как размер, позицию и прочее мы узнали при загрузке базового класса { QDomElement anchorsNode = sectionNode.firstChildElement("Anchors"); if(!anchorsNode.isNull()) for(QDomNode anchorNode = anchorsNode.firstChildElement("Anchor");!anchorNode.isNull();anchorNode = anchorNode.nextSibling()) { QDomElement anchorElement = anchorNode.toElement(); if(!anchorElement.isNull()) { bool ok; QPointF currentAnchor; currentAnchor.setX(anchorElement.attribute("PosX").toFloat(&ok)); currentAnchor.setY(anchorElement.attribute("PosY").toFloat(&ok)); fpolygon.addPoint(currentAnchor); } } } }
void QSection::saveToStream(QDomDocument * doc,QDomElement * node) { QRailItem::saveToStream(doc,node); //сохраняем часть базового класса
QDomElement sectionNode = doc->createElement("SimpleSectionData"); //теперь все что связано с этим классом
//получаем список опорных точек полигона секции QList<QPointF>* anchors_list = fpolygon.anchors(); QPointF current_acnchor;
QDomElement anchors = doc->createElement("Anchors");
for(QList<QPointF>::iterator current_anchor_it=anchors_list->begin();current_anchor_it!=anchors_list->end();current_anchor_it++) { current_acnchor = *current_anchor_it; QDomElement anchor = doc->createElement("Anchor"); anchor.setAttribute("PosX",current_acnchor.x()); anchor.setAttribute("PosY",current_acnchor.y()); anchors.appendChild(anchor); }
sectionNode.appendChild(anchors); node->appendChild(sectionNode); }
а вот кусок как грузить сцену: //находим секцию с эелементами поля QDomElement fieldObjects = root.firstChildElement("FieldObjects"); if(fieldObjects.isNull()) return false;
scene()->setLastId(fieldObjects.attribute("LastId","0").toLong(&ok));
for(QDomNode fieldNode = fieldObjects.firstChildElement("FieldObject");!fieldNode.isNull();fieldNode = fieldNode.nextSibling()) { QDomElement fieldObject = fieldNode.toElement(); if(fieldObject.isNull()) continue;
object_type = fieldObject.attribute("ObjectType"); //тут грузятся много разных объектов разных классов //**** //находим наш объект if(object_type=="Section") { QSection * section = new QSection(false); //создаем объект section->loadFromStream(&doc,&fieldObject); //грузим ноду объекта section->recalculate(); //внутренние пересчеты fscene->addSection(section); //добавляем на сцену continue; //дальше нет смысла идти, ищем следующий объект ... } //*** }
пример сохранения //теперь сохраняем данные о графических объектах QDomElement fieldObjects = doc.createElement("FieldObjects"); fieldObjects.setAttribute("LastId",scene()->lastId()); root.appendChild(fieldObjects);
for(QList<QGraphicsItem*>::iterator items_it = fitems.begin();items_it!=fitems.end();items_it++) //проходимся по всей сцене { gi = *items_it; if((item = dynamic_cast<QRailItem*>(gi))==NULL) continue; //если не наследник от QRailItem проходим далее //пишем новую секцию <FieldObject>
object_type = item->type();
switch(object_type) { case otRailItem: param = "RailItem"; break; //**** case otSection: param = "Section"; break; //**** default: //остальные игнорируем continue; }
QDomElement fieldObject = doc.createElement("FieldObject"); //создаем ноду объекта сцены fieldObject.setAttribute("ObjectType",param); //пишем тип объекта
switch(object_type) { //*** case otSection: { if((section = dynamic_cast<QSection*>(item))!=NULL) section->saveToStream(&doc,&fieldObject); } break;
//**** default: break; } //завершаем секцию <FiledObject> fieldObjects.appendChild(fieldObject); }
надеюсь идею поняли. по сути это можно грубо назвать сериализацией, но более примитивная и сохраняю/гружу только выбранные поля объектов.
|
|
|
1011
|
Программирование / С/C++ / Один интерфейс для нескольких классов
|
: Май 06, 2011, 12:36
|
Использую на QGraphicsScene множество item-ов и несколько widget-ов. Все item-ы наследуются от класса QRailItem class QRailItem : public QObject, public QGraphicsItem { Q_OBJECT Q_INTERFACES (QGraphicsItem)
protected:
QFont ffont; bool fupdating; QString fname; QRectF fboundRect; TObjectType fobjectType; quint32 id; ... };
Как мне сделать грамотно интерфейс, в который бы вынести все эти поля из базового класса, что бы они так же были и в классе QGraphicsProxyWidget? Простым дублированием не охота делать.
|
|
|
1012
|
Qt / 2D и 3D графика / Re: Виджеты на QGraphicsScene
|
: Май 06, 2011, 00:29
|
Если кому то интересно, сделал класс наследник QMovableGraphicsProxyWidget, который как раз компенсирует этот недостаток + позволяет динамически менять размеры виджета (с помощью анкеров). Итого имеем полноценное петераскивание виджетов и изменение их размеров в рантайме. Если нужно, выложу исходник.
|
|
|
1014
|
Qt / 2D и 3D графика / QGLWidget + QGraphicsView = как добиться сглаживания?
|
: Май 05, 2011, 16:10
|
Столкнулся с такой проблемой, что при использовании рендеринга QGLWidget отсутствует сглаживание, и картина принимает рубленный вид, что очень не красиво по сравнению с Software rendering с включенным Antialias. Кто то уже сталкивался с подобным, как решить сию проблему? QGLFormat с выставлением разных опций не помогает.
|
|
|
1017
|
Qt / 2D и 3D графика / Re: Виджеты на QGraphicsScene
|
: Май 05, 2011, 11:43
|
#include <QLCDNumber> #include <QDateTime> #include <QGraphicsWidget> #include <time.h>
class SCB_DigitalClock : public QLCDNumber ,public QGraphicsWidget { Q_OBJECT Q_INTERFACES(QGraphicsWidget)
QDateTime dt; time_t oldTime;
public: explicit SCB_DigitalClock(QWidget *parent = 0); void showTime(time_t * time_value);
signals:
public slots:
void updateTime(time_t ATime);
};
При компиляции ругается Error: Undefined interface
|
|
|
1018
|
Qt / 2D и 3D графика / Виджеты на QGraphicsScene
|
: Май 05, 2011, 11:29
|
На сцене нужно отобразить кучу itemов (в основном полигоны, линии, круги и прочее, наследованы от QGraphicsItem). Теперь возникла задача, на этой же сцене отображать виджеты (QLCDNumber, QListWidget, QPushButton). С отображением через addWidget проблем нет. Но виджет, который добавился на сцену не передвигается мышью, как например другие элементы, которые наследованы от QGraphicsItem. И еще впорос: Если я в наследнике QGraphicsItem (назевоем его QRailItem), добавил поля (qint32 objectType, и прочее ...), потом от QRailItem тоже наследуется много классов. Мне нужно что бы виджеты, которые добавляются на сцену тоже были наследниками QRailItem, или имели такие же поля как в QRailItem. Как сделать? Догадываюсь про множественное наследование, но пока еще не пойму как конкретно. Вот частичное описание класса QRailItem, от которого наследуются все классы отображаемых элементов на сцене class QRailItem : public QObject, public QGraphicsItem { Q_OBJECT Q_INTERFACES (QGraphicsItem)
protected:
bool fupdating; QString fname; TObjectType fobjectType; ... };
Как видно, класс наследуется от QObject и QGraphicsItem. Подозреваю что виджеты мне надо наследовать так? class QRailItem : public QLCDNumber, public QGraphicsWidget { Q_OBJECT Q_INTERFACES (QGraphicsWidget) ... }
А как получить теже поля что и у QRailItem? Или вынести их все в отдельный класс, и множественным наследованием получить их уже в QRailItem и наследнике QGraphicsWidget?
|
|
|
1019
|
Qt / Многопоточное программирование, процессы / Re: Несколько TCP клиентов в одной программе
|
: Апрель 28, 2011, 18:01
|
В отладчике на this ругается : <unavailable synchroneous data> ощущение что стек покоцался...
также связал сигнал дочернего сетевого потока и основного ГУИ с поправкой connect(mmnClientThread->mmnClient,SIGNAL(frameReceived(int)),this,SLOT(data_receive(int)),Qt::DirectConnection);
все равно SIGSEGV.
нашёл ошибку, банально копировал не в тот указатель, что надо... пока все работает.
|
|
|
1020
|
Qt / Многопоточное программирование, процессы / Re: Несколько TCP клиентов в одной программе
|
: Апрель 28, 2011, 17:32
|
С сокетами вроде разобрался, теперь возникла проблема с синхронизацией. Код моего клиента (асинхронный) class QMMNClient : public QObject { Q_OBJECT
QTcpSocket * fsocket; QTimer * freqTimer; QMutex * fmutex;
quint16 fblockSize; quint16 fleftBytes; quint32 freconnTimeot;
public:
explicit QMMNClient(QObject *parent = 0); ~QMMNClient();
int id;
QString remoteHost; quint16 remotePort;
void connectToServer(); void disconnectFromServer(); void moveToThread(QThread *thread); bool safeGetData(mmn_frame_t * destFrame, size_t frameSize);
signals:
void connected(int id); void disconnected(int id); void frameReceived(int id);
private slots:
void readyRead(); void onConnected(); void onDisconnected(); void doRequest();
public slots:
void sendRequest();
};
//реализация
QMMNClient::QMMNClient(QObject *parent) : QObject(parent) { id = 0; fsocket = new QTcpSocket; remoteHost = "127.0.0.1"; remotePort = 10000; freconnTimeot = 2; freqTimer = new QTimer; freqTimer->setInterval(250); fmutex = new QMutex; //эти соыбтия обрабатываю внутри потока сетевого клиента connect(fsocket,SIGNAL(connected()),this,SLOT(onConnected())); connect(fsocket,SIGNAL(disconnected()),this,SLOT(onDisconnected())); connect(fsocket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(onDisconnected())); connect(fsocket,SIGNAL(readyRead()),this,SLOT(readyRead())); //здесь читаю connect(freqTimer,SIGNAL(timeout()),this,SLOT(doRequest())); //переодический запрос на сервер }
QMMNClient::~QMMNClient() { freqTimer->stop(); fsocket->abort(); delete fsocket; delete freqTimer; delete fmutex; if(frawBuffer) free(frawBuffer); }
void QMMNClient::readyRead() { if(fblockSize==0) { if(fsocket->bytesAvailable()<sizeof(scb_msg_t)) return; fblockSize = fsocket->read(frawBuffer,sizeof(scb_msg_t)); if(fframeBuffer.msg_head->size==0) { fblockSize = 0; return; } qDebug("block %d\n, header.size %d",fblockSize,fframeBuffer.msg_head->size); }
fblockSize=fsocket->bytesAvailable(); fleftBytes = fframeBuffer.msg_head->size-sizeof(scb_msg_t);
if(fblockSize>=(fleftBytes)) { fmutex->lock(); fblockSize = fsocket->read(&frawBuffer[sizeof(scb_msg_t)],fleftBytes); fmutex->unlock(); qDebug("fblockSize %d\n",fblockSize); fblockSize = 0; emit frameReceived(id); //надо это событие обработать в потоке GUI } }
bool QMMNClient::safeGetData(mmn_frame_t * destFrame, size_t frameSize) { if(destFrame && (frameSize==fframeSize)) { fmutex->lock(); qMemCopy(destFrame,&fframeBuffer,fframeSize); fmutex->unlock(); return true; } return false; }
void QMMNClient::onConnected() { fblockSize = 0; // qDebug("connected channel %d\n",id); emit connected(id); freqTimer->start(250); }
void QMMNClient::onDisconnected() { // qDebug("disconnected channel %d\n",id); freqTimer->stop(); fsocket->close(); emit disconnected(id); sleep(freconnTimeot); fsocket->connectToHost(remoteHost,remotePort); }
void QMMNClient::doRequest() { sendRequest(); }
void QMMNClient::connectToServer() { fsocket->connectToHost(remoteHost,remotePort); }
void QMMNClient::disconnectFromServer() { fsocket->close(); }
void QMMNClient::sendRequest() { fsocket->write((const char*)&frequest,frequestSize); //отправляем некую структурку на сервер, на которую он должен ответить }
void QMMNClient::moveToThread(QThread *thread) { QObject::moveToThread(thread); //двигаем себя в нужный поток if(fsocket) fsocket->moveToThread(thread); //сокет if(freqTimer) freqTimer->moveToThread(thread); //и таймер }
Код потока, в котором будет крутиться сокет class QMMNClientThread : public QThread { Q_OBJECT
void run();
public: explicit QMMNClientThread(QObject *parent = 0); ~QMMNClientThread();
QMMNClient * mmnClient;
signals:
public slots:
};
// реализация
QMMNClientThread::QMMNClientThread(QObject *parent) : QThread(parent) { mmnClient = new QMMNClient; mmnClient->moveToThread(this); }
QMMNClientThread::~QMMNClientThread() { quit(); wait(); }
void QMMNClientThread::run() { mmnClient->connectToServer(); exec(); }
В объекте главного потока создаю потоки TCP клиентов, связываю сигналы, которые будут генериться при событиях в потоках клиентов, и должны обрабатываться в главном потоке. mmnClientThread = new QMMNClientThread(this); mmnClientThread->mmnClient->remoteHost = ecHost[i]; mmnClientThread->mmnClient->remotePort = ecPort[i]; connect(mmnClientThread->mmnClient,SIGNAL(frameReceived(int)),this,SLOT(data_receive(int)),Qt::BlockingQueuedConnection);//здесь будет обращение к GUI connect(mmnClientThread->mmnClient,SIGNAL(connected(int)),this,SLOT(chan_connected(int))); connect(mmnClientThread->mmnClient,SIGNAL(disconnected(int)),this,SLOT(chan_disconnected(int))); mmnClientThread->start();
так вот при emit frameReceived(id) я захожу в обработчик data_receive(id), но указатель на класс в отладчике не показывается, и вообще все данные объекта как бы испорчены, и вылеатет SIGSEGV.
|
|
|
|
|