Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [QT4] Перерисовка части примитива 
:(
    Опции темы
o2n3e
Дата 31.10.2011, 00:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 19.8.2011

Репутация: -1
Всего: -5



Здравствуйте!
Есть сцена, на которой рисуется не сложная векторная графика. Есть 2 типа примитивов: дуга(окружность) и линия.
Эту картинку "рисует" инструмент станка. Я знаю текущую позицию инструмента(в реалтайме). 
Задача - повторять за инструментом.
Как-то так.
Код

#include <QTimer>
#include <QApplication>
#include <QPainter>
#include <QGraphicsView>
#include <QDebug>
#include <QGraphicsItem>

QPainterPath qt_graphicsItem_shapeFromPath(const QPainterPath &path, const QPen &pen) {
    // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0
    // if we pass a value of 0.0 to QPainterPathStroker::setWidth()
    const qreal penWidthZero = qreal(0.00000001);
    if (path == QPainterPath())
        return path;
    QPainterPathStroker ps;
    ps.setCapStyle(pen.capStyle());
    if (pen.widthF() <= 0.0)
        ps.setWidth(penWidthZero);
    else
        ps.setWidth(pen.widthF());
    ps.setJoinStyle(pen.joinStyle());
    ps.setMiterLimit(pen.miterLimit());
    QPainterPath p = ps.createStroke(path);
    p.addPath(path);
    return p;
}

class ALine : public QGraphicsItem {
public:
    ALine(const QLineF& line, QGraphicsItem* parent = 0, QGraphicsScene* scene = 0) : line(line), point(QPointF()) {}
    void nextp(QPoint &p) {point = p;}
private:

    virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0) {
        if (point == QPointF()) {
            painter->setPen(QPen(Qt::red, 3));
            painter->drawLine(line);
        }

        if (point == line.p2()) {
            painter->setPen(QPen(Qt::red, 3));
            painter->drawLine(line);
        }
        else {
            painter->setPen(QPen(Qt::red, 3));
            painter->drawLine(line.p1(), point);
            painter->setPen(QPen(Qt::blue, 3));
            painter->drawLine(point, line.p2());
        }
    }

    virtual QPainterPath shape() const {
        QPainterPath path;
        
        if (line == QLineF())
            return path;
        
        path.moveTo(line.p1());
        path.lineTo(line.p2());
        return qt_graphicsItem_shapeFromPath(path, QPen(Qt::red, 3));
    }

    virtual QRectF boundingRect() const {return shape().controlPointRect();}

    /*******************/
    QLineF line;
    QPointF point;
    /*******************/
};

class mainwin : public QGraphicsView {
    
    Q_OBJECT

public:
    mainwin(QPoint startxy, QPoint end, uint steptime) : xy(startxy), endxy(end), msec(steptime) {
        resize(endxy.x() + 50, endxy.y() + 50);
        timer = new QTimer(this);
        connect(timer, SIGNAL(timeout()), this, SLOT(nextp()));

        sc = new QGraphicsScene;
        setScene(sc);
        setRenderHints(QPainter::Antialiasing);
        sc->setBackgroundBrush(Qt::black);


        QPen pen(Qt::darkCyan, 3);
        line = new ALine(QLine(QPoint(), endxy));
        sc->addItem(line);
    }

    void start() {timer->start(msec);}

protected:

    /*******************/
    uint msec;
    QPoint xy, endxy;
    QTimer * timer;
    QPainter * p;
    QGraphicsScene * sc;
    ALine * line;
    /*******************/

protected slots:

    void nextp() {xy += QPoint(1, 1); line->nextp(xy); if (xy == endxy) timer->stop();line->hide();line->show();}
};



int main(int argc, char ** argv) {
    QApplication app(argc, argv);
    mainwin * mw = new mainwin(QPoint(), QPoint(250, 250), 15);
    mw->show();
    mw->start();
    return app.exec();
}

#include "moc_main.cpp"


Насколько я понимаю, надо вызвать scene()->itemAt() с переданными в него текущими координатами, а дальше делать так, как выше.

P.S. Как перерисовывать итем? Пока юзаю кастыль "item->hide();item->show();"
PM MAIL   Вверх
alexvs11
Дата 31.10.2011, 00:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


hell is here
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 21.8.2010

Репутация: 2
Всего: 10



так QWidget::repaint?
PM MAIL   Вверх
o2n3e
Дата 31.10.2011, 02:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 19.8.2011

Репутация: -1
Всего: -5



Цитата(alexvs11 @ 31.10.2011,  00:26)
так QWidget::repaint?

Ничего из данных класов не наслудет repaint, ибо:
QGraphicsScene : public QObject
QGraphicsView : public QAbstractScrollArea
Да и нужно перерисовывать 1-н итем, а не все.
PM MAIL   Вверх
math64
Дата 31.10.2011, 07:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



shape() не соответствует paint()
Можно же использовать QGraphicsShapeItem вместо самодельного.
Добавить на сцену QGraphicsShapeItem с красным пером и QGraphicsLineItem c синим пером.
В своём QGraphicsItem можно исользовать [protected] prepareGeometryChange() перед началом изменения геометрии, после изменения геометрии нужно будет вызвать update();
стандартные компоненты сделают это сами.

Это сообщение отредактировал(а) math64 - 31.10.2011, 07:35
PM   Вверх
o2n3e
Дата 31.10.2011, 14:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 19.8.2011

Репутация: -1
Всего: -5



Цитата(math64 @ 31.10.2011,  07:33)
shape() не соответствует paint()
Можно же использовать QGraphicsShapeItem вместо самодельного.
Добавить на сцену QGraphicsShapeItem с красным пером и QGraphicsLineItem c синим пером.
В своём QGraphicsItem можно исользовать [protected] prepareGeometryChange() перед началом изменения геометрии, после изменения геометрии нужно будет вызвать update();
стандартные компоненты сделают это сами.

Спасибо!
А почему не соответствует? У меня получется та же линия, только из 2-х частей.
Код

    virtual QPainterPath shape() const {
        QPainterPath path;
        
        if (line == QLineF())
            return path;
        
        path.moveTo(line.p1());
        path.lineTo(point);
        path.lineTo(line.p2());
        return qt_graphicsItem_shapeFromPath(path, QPen(Qt::red, 3));
    }

Так?
QGraphicsShapeItem - это QAbstractGraphicsShapeItem? Если да, то документации на него я с ходу не нашел, кроме 3-х строк описания(которое я не понял). Что это такое? 


Это сообщение отредактировал(а) o2n3e - 31.10.2011, 14:20
PM MAIL   Вверх
math64
Дата 31.10.2011, 16:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



Цитата(o2n3e @  31.10.2011,  14:16 Найти цитируемый пост)
А почему не соответствует? У меня получется та же линия, только из 2-х частей.

В paint() проверяется, задана ли точка point и делается различная отрисовка.
В shape() этого не делается.
При отрисовке нельза выходить за границы shape() - иначе при перерисовке будут оставаться следы, перерисовываться будет boundingRect(),
Для isSelected() компонента можно вылезать за shape(), но в пределах clipPath().

Цитата(o2n3e @  31.10.2011,  14:16 Найти цитируемый пост)
QGraphicsShapeItem - это QAbstractGraphicsShapeItem?

Ошибся в названии: QGraphicsPathItem, QAbstractGraphicsShapeItem - это её базовый класс;
Если хочешь писать свой компонент, можешь наследоваться от него - будет pen и brush.
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets"
JackYF
Любитель
  • В заголовке темы в квадратных скобках обозначьте используемую вами библиотеку, например: [QT],[GTK],[wx].
  • Если вопрос актуален только для некоторой версии библиотеки, либо, если вы пользуетесь не самой последней версией, укажите это. Например: [QT4], [GTK2].
  • Все начинающие изучать Qt - не забудьте зайти сюда.
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • В вопросе укажите полную версию версию библиотеки, а также все дополнительные используемые программные пакеты.
  • Не забывайте пользоваться кнопкой "Код".
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема »


 




[ Время генерации скрипта: 0.0464 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.