Russian Qt Forum
Апрель 27, 2024, 01:20 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало Форум WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  
  Просмотр сообщений
Страниц: 1 ... 66 67 [68] 69
1006  Qt / Пользовательский интерфейс (GUI) / Re: listWidget: как с каждой строкой хранить произвольный указатель? : Май 08, 2011, 22:01
а если не пользуюсь моделью? по сути мне нужно выводить простые строки, но к каждой строке привязан указатель на объект с которым связана эта строка.
1007  Qt / Пользовательский интерфейс (GUI) / listWidget: как с каждой строкой хранить произвольный указатель? : Май 08, 2011, 17:33
К примеру в Делфи у ListBox помимо Strings есть еще классная вещь как Objects, по сути хранится пара строка + произвольный указатель. Как такое реализовать в Qt? все что нашел, это data() для listITem, но как в нем хранить указатель я так и не понял или делать своего наследника?
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);
        }

надеюсь идею поняли. по сути это можно грубо назвать сериализацией, но более примитивная и сохраняю/гружу только выбранные поля объектов.
1009  Qt / 2D и 3D графика / Re: Виджеты на QGraphicsScene : Май 06, 2011, 16:21
с перемещением и изменением размеров разобрался.
проблема в следующем - сцена никак не реагирует на выделение виджетов.
1010  Программирование / С/C++ / Re: Один интерфейс для нескольких классов : Май 06, 2011, 13:14
вот набросал диаграмму того что хочу получить
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, который как раз компенсирует этот недостаток + позволяет динамически менять размеры виджета (с помощью анкеров).
Итого имеем полноценное петераскивание виджетов и изменение их размеров в рантайме.
Если нужно, выложу исходник.
1013  Qt / 2D и 3D графика / Re: QGLWidget + QGraphicsView = как добиться сглаживания? : Май 06, 2011, 00:28
Спасибо, помогло!
1014  Qt / 2D и 3D графика / QGLWidget + QGraphicsView = как добиться сглаживания? : Май 05, 2011, 16:10
Столкнулся с такой проблемой, что при использовании рендеринга QGLWidget отсутствует сглаживание, и картина принимает рубленный вид, что очень не красиво по сравнению с Software rendering с включенным Antialias. Кто то уже сталкивался с подобным, как решить сию проблему?
QGLFormat с выставлением разных опций не помогает.
1015  Qt / 2D и 3D графика / Re: Виджеты на QGraphicsScene : Май 05, 2011, 15:26
Сделал. Но одна проблема, такие виджеты не перемещаются и не выделяются мышью на сцене.
Установка флагов ничего не дает. Есть идеи?
1016  Qt / 2D и 3D графика / Re: Виджеты на QGraphicsScene : Май 05, 2011, 14:41
хорошо, тогда как мне создать виджет, который бы повторял собой QLCDNumber, но был наследником от QGraphicsObject?
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.
Страниц: 1 ... 66 67 [68] 69

Страница сгенерирована за 0.054 секунд. Запросов: 23.