crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

4 страниц V   1 2 3 > »   
Ответить в данную темуНачать новую тему
> QGraphicsRectItem и setPos()
lifrost
  опции профиля:
сообщение 10.3.2011, 11:48
Сообщение #1


Студент
*

Группа: Участник
Сообщений: 38
Регистрация: 4.3.2011
Из: Миасс
Пользователь №: 2468

Спасибо сказали: 0 раз(а)




Репутация:   0  


Создаю в конструкторе:

pRight = new QGraphicsRectItem;
pRight->setRect(580, 300, 20, 300);
pRight->setPen(QPen(Qt::black));
pRight->setBrush(QBrush(Qt::green));
addItem(pRight);


Хочу поменять положение своего rect, делаю следующее

void WindowScene::mousePressEvent(QGraphicsSceneMouseEvent *e)
{
    if(e->button() == Qt::LeftButton)
    {
        plastPos = pRight->scenePos();

        leftButton = true;
        mX = e->buttonDownScenePos(Qt::LeftButton).x();
    }
}

void WindowScene::mouseMoveEvent(QGraphicsSceneMouseEvent *e)
{
    int x, y;
    x = e->scenePos().x();
    y = e->scenePos().y();

    if(leftButton)
    {
        dx = x - mX;
        dy = plastPos.y();

        pRight->setPos(dx, dy);

        sceneUpdate();
    }
}

void WindowScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *e)
{
    e->accept();
    leftButton = false;
}


Квадрат перемещается, НО! Я не понимаю, почему при повторном перемещение он "соскакивает" в первоначальную позицию?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
abc
  опции профиля:
сообщение 12.3.2011, 21:34
Сообщение #2


Участник
**

Группа: Участник
Сообщений: 221
Регистрация: 16.12.2010
Из: СПб
Пользователь №: 2272

Спасибо сказали: 26 раз(а)




Репутация:   4  


держи код, который работает, но это в классе итема, а не сцены:
void TextItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
point=event->pos();
}
void TextItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
setPos(event->scenePos()-point);
}


сложный код ты наворотил
mouseReleaseEvent тебе не нужен, т.к. if(leftButton) тебе не нужно

подумай, стоит ли делать свой класс сцены, чтобы забубенить движение итема? если ты, конечно, только для этого влез в класс сцены... К тому же, куда не ткнёшь на сцене, твой итем будет двигаться... а ты ведь хочешь, чтобы он двигался только, когда на него тыкаешь... тут тебе понадобится проверка "а под мышью ли итем"... а если будешь реализовывать поведение итема в классе итема, таких проблем не будет... всякому коду своё место)

Сообщение отредактировал abc - 12.3.2011, 22:15
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lifrost
  опции профиля:
сообщение 14.3.2011, 7:51
Сообщение #3


Студент
*

Группа: Участник
Сообщений: 38
Регистрация: 4.3.2011
Из: Миасс
Пользователь №: 2468

Спасибо сказали: 0 раз(а)




Репутация:   0  


спасибо, значит я просто пошел не той дорогой.
у меня были сомнения делать ли класс от сцены или от итема....теперь вроде понятно.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lifrost
  опции профиля:
сообщение 14.3.2011, 14:07
Сообщение #4


Студент
*

Группа: Участник
Сообщений: 38
Регистрация: 4.3.2011
Из: Миасс
Пользователь №: 2468

Спасибо сказали: 0 раз(а)




Репутация:   0  


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

WindowItem::WindowItem(QGraphicsItem *parent) : QGraphicsObject(parent)
{
    setAcceptDrops(true);
}


// Левая створка
LeftGlume::LeftGlume(QGraphicsItem *parent) : WindowItem(parent)
{
}

QRectF LeftGlume::boundingRect() const
{
     return QRectF(100, 100, 20, 500);
}

void LeftGlume::paint(QPainter *painter,
           const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);

    painter->drawRect(100,100,20,500);
}

void LeftGlume::mousePressEvent(QGraphicsSceneMouseEvent *e)
{

}

void LeftGlume::mouseMoveEvent(QGraphicsSceneMouseEvent *e)
{

}

// Верхняя створка
TopGlume::TopGlume(QGraphicsItem *parent) : WindowItem(parent)
{
}

QRectF TopGlume::boundingRect() const
{
     return QRectF(100, 100, 500, 20);
}

void TopGlume::paint(QPainter *painter,
           const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);

    painter->drawRect(100,100,500,20);
}

void TopGlume::mousePressEvent(QGraphicsSceneMouseEvent *e)
{

}

void TopGlume::mouseMoveEvent(QGraphicsSceneMouseEvent *e)
{

}

// Нижняя створка
BottomGlume::BottomGlume(QGraphicsItem *parent) : WindowItem(parent)
{
}

QRectF BottomGlume::boundingRect() const
{
     return QRectF(100, 580, 500, 20);
}

void BottomGlume::paint(QPainter *painter,
           const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);

    painter->drawRect(100,580,500,20);
}

void BottomGlume::mousePressEvent(QGraphicsSceneMouseEvent *e)
{

}

void BottomGlume::mouseMoveEvent(QGraphicsSceneMouseEvent *e)
{

}

// Правая створка
RightGlume::RightGlume(QGraphicsItem *parent) : WindowItem(parent)
{
}

QRectF RightGlume::boundingRect() const
{
     return QRectF(580, 100, 20, 500);
}

void RightGlume::paint(QPainter *painter,
           const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);

    painter->drawRect(580,100,20,500);
}

void RightGlume::mousePressEvent(QGraphicsSceneMouseEvent *e)
{
    if(e->button() == Qt::LeftButton)
    {
        point = e->pos();
    }
}

void RightGlume::mouseMoveEvent(QGraphicsSceneMouseEvent *e)
{
    RightGlume *rightG = new RightGlume;

    int y;
    y = rightG->pos().y();

    setPos(e->scenePos().x() - point.x(), y);

    QPainter *p = new QPainter;
    p->drawArc(100,100,500,20,20,3);

    scene()->update(0,0,2000,2000);
}


// Окно квадратное
RectWindow::RectWindow(QGraphicsItem *parent)
    : WindowItem(parent)
{
    QGraphicsObject *leftItem = new LeftGlume(this);
    QGraphicsObject *rightItem = new RightGlume(this);
    QGraphicsObject *topItem = new TopGlume(this);
    QGraphicsObject *bottomItem = new BottomGlume(this);

    leftItem->setPos(leftItem->pos().x(),leftItem->pos().y());
    rightItem->setPos(rightItem->pos().x(),rightItem->pos().y());
    topItem->setPos(topItem->pos().x(),topItem->pos().x());
    bottomItem->setPos(bottomItem->pos().x(), bottomItem->pos().y());

}

QRectF RectWindow::boundingRect() const
{
    return QRectF();
}

void RectWindow::paint(QPainter *painter,
                  const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(painter);
    Q_UNUSED(option);
    Q_UNUSED(widget);
}


пока вот что получилось. На Сцене отображается квадрат, правая створка двигается, а как организовать дорисовку верхней и нижней створки ума не приложу....
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
abc
  опции профиля:
сообщение 15.3.2011, 13:31
Сообщение #5


Участник
**

Группа: Участник
Сообщений: 221
Регистрация: 16.12.2010
Из: СПб
Пользователь №: 2272

Спасибо сказали: 26 раз(а)




Репутация:   4  


Вот код, двигающий левую и верхнюю грани... Надеюсь, он наставит тебя на путь...
Тебе не нужны ректитемы, достаточно в твоём классе нарисовать в paint() четыре линии. В маусэвенте изменять координаты вершин образовавшегося четырёхугольника

item.h
Раскрывающийся текст

class Item : public QGraphicsItem
{
public:
    Item();

    void paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 );
    QRectF boundingRect () const;

    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    QPointF point;
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);

//вершины
    QPointF left_top;
    QPointF left_bottom;
    QPointF right_bottom;
    QPointF right_top;

};



item.cpp
Раскрывающийся текст

Item::Item()
{
    left_top=QPointF(0,0);
    left_bottom=QPointF(0,100);
    right_bottom=QPointF(100,100);
    right_top=QPointF(100,0);
}


void Item::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QLineF left_line(left_top,
                     left_bottom);
    painter->drawLine(left_line);

    QLineF bottom_line(left_bottom,
                       right_bottom);
    painter->drawLine(bottom_line);

    QLineF right_line(right_bottom,
                      right_top);
    painter->drawLine(right_line);

    QLineF top_line(right_top,
                     left_top);
    painter->drawLine(top_line);
}


QRectF Item::boundingRect() const        //область, ассоциируемая с итемом - в ней ловится мышь и рисует paint()
{
    return QRectF(-100,-100,200,200);
}


void Item::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    point=event->pos()-left_top;
//если уберёшь -left_top, будет прыгать в начальное значение на старте нового перетаскивания, как, кажется, было у тебя
}


void Item::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    left_top=event->pos()-point;
    update();
}



P.S. Когда хочешь показать большой код, оборачивай тег "код" в тег "раскрывающийся текст"

Сообщение отредактировал abc - 15.3.2011, 13:35
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lifrost
  опции профиля:
сообщение 15.3.2011, 14:51
Сообщение #6


Студент
*

Группа: Участник
Сообщений: 38
Регистрация: 4.3.2011
Из: Миасс
Пользователь №: 2468

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(abc @ 15.3.2011, 15:31) *
Вот код, двигающий левую и верхнюю грани... Надеюсь, он наставит тебя на путь...
Тебе не нужны ректитемы, достаточно в твоём классе нарисовать в paint() четыре линии. В маусэвенте изменять координаты вершин образовавшегося четырёхугольника

item.h
Раскрывающийся текст

class Item : public QGraphicsItem
{
public:
    Item();

    void paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 );
    QRectF boundingRect () const;

    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    QPointF point;
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);

//вершины
    QPointF left_top;
    QPointF left_bottom;
    QPointF right_bottom;
    QPointF right_top;

};



item.cpp
Раскрывающийся текст

Item::Item()
{
    left_top=QPointF(0,0);
    left_bottom=QPointF(0,100);
    right_bottom=QPointF(100,100);
    right_top=QPointF(100,0);
}


void Item::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QLineF left_line(left_top,
                     left_bottom);
    painter->drawLine(left_line);

    QLineF bottom_line(left_bottom,
                       right_bottom);
    painter->drawLine(bottom_line);

    QLineF right_line(right_bottom,
                      right_top);
    painter->drawLine(right_line);

    QLineF top_line(right_top,
                     left_top);
    painter->drawLine(top_line);
}


QRectF Item::boundingRect() const        //область, ассоциируемая с итемом - в ней ловится мышь и рисует paint()
{
    return QRectF(-100,-100,200,200);
}


void Item::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    point=event->pos()-left_top;
//если уберёшь -left_top, будет прыгать в начальное значение на старте нового перетаскивания, как, кажется, было у тебя
}


void Item::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    left_top=event->pos()-point;
    update();
}



P.S. Когда хочешь показать большой код, оборачивай тег "код" в тег "раскрывающийся текст"



Круто! Я походу понял, спасибо большое!!!!
Тема закрыта.

P.S. на счет кода учту )
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lifrost
  опции профиля:
сообщение 24.3.2011, 10:26
Сообщение #7


Студент
*

Группа: Участник
Сообщений: 38
Регистрация: 4.3.2011
Из: Миасс
Пользователь №: 2468

Спасибо сказали: 0 раз(а)




Репутация:   0  


Что-то после нескольких дней экспериментов я понял, что метод который предложил ABC не совсем мне подходит ((.
Да действительно при наследование от QGraphicsItem и рисование линий квадрат растягивается.....но нужно нечто иное.

Как образец рассматриваю программу IT-Окна, там есть графический редактор...если присмотреться там отчетливо видно что каждая створка и стекло - это отдельный элемент.

Сейчас пробую унаследовать класс от QGraphicsPolygonItem. Задал в нем общие 8-мь QPointF. Далее наследую от этого класса 4е класса где создаются 4е полигона - каждый по форме створки окна.

В итоге опять прихожу к вопросу - как при перемещение одного полигона дорисовать другие? Я пробовал делать глобальными эти 8-мь точек, но перерисовка идет если кликаю, после перемещения к примеру правого итема, по итему к примеру верхнему.

Я что-то столько времени уже потратил, может это нереально сделать? Я уже в отчаянии =(
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
abc
  опции профиля:
сообщение 24.3.2011, 12:31
Сообщение #8


Участник
**

Группа: Участник
Сообщений: 221
Регистрация: 16.12.2010
Из: СПб
Пользователь №: 2272

Спасибо сказали: 26 раз(а)




Репутация:   4  


что-то я не понял, какой результат нужно получить, полигон меня совсем запутал.. официальное задание есть?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lifrost
  опции профиля:
сообщение 24.3.2011, 12:45
Сообщение #9


Студент
*

Группа: Участник
Сообщений: 38
Регистрация: 4.3.2011
Из: Миасс
Пользователь №: 2468

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(abc @ 24.3.2011, 14:31) *
что-то я не понял, какой результат нужно получить, полигон меня совсем запутал.. официальное задание есть?

Если не трудно скачай IT-Окна (у них есть урезанная версия, она бесплатная), там есть создание чертежа окна, думаю все сразу будет понятно. Нужно сделать аналог.

А вообще:
1) Должно быть главное окно приложение - это QMainWindow.
2) Должен быть набор справочников: Цвет, Номенклатура (перечень имеющихся болтиков, винтоков, рам и тп), Профили.
3) Графический редактор - пользователь имеет возможность создать окно(рама, причем и квадратную и прямоугольную и с аркой). Может вставлять внутрь различные импосты (перекладины) и створки (поворотную, откидную и тп), может мышкой масштабировать окно. При чем когда он все это рисует из номеклатуры по формулам в зависимости от выбранного профиля формируется заказ (составляющие этого окна).
4) Ну и сохранить это результат - заказ с рисунком и размерами.

Я начал с простого окна, т.е. профиль материала для каждой части окна может быть разным, я начал с реализации каждого элемента по отдельности - поэтому и начал делать классы для каждой части (4е створки и по середине квадрат - он же стеклопакет).

Отталкивался от уже готовых продуктов, но в основном у них много ненужных функций, а плотить за лишнее добро не охота, вот и пытаюсь сделать урезанный аналог.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
abc
  опции профиля:
сообщение 24.3.2011, 13:48
Сообщение #10


Участник
**

Группа: Участник
Сообщений: 221
Регистрация: 16.12.2010
Из: СПб
Пользователь №: 2272

Спасибо сказали: 26 раз(а)




Репутация:   4  


IT Окна. Конструктор
?
установил, не запускается - "напишите микрософту"

изначально под "резиновым квадратом" я понимал квадрат, который может стать параллелепипедом... эта функция нужна? Или ты просто хочешь изменять размеры граней прямоугольника, не кособоча его? окна ведь могут быть кособокими, я б такое хотел)
тебе нужна не тонкая линия рамы, а толстая? Чем толще линия, тем нелепее будут выглядеть скособоченные углы... тут нужно ещё с ними мучиться... арка тоже интересненько.. полуэллипс...
короче, надо как-то сцеплять грани, задача ясна)
про полигон всё равно идея не дошла... зачем там 8 точек... вроде ведь нужно 4
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

4 страниц V   1 2 3 > » 
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 26.11.2024, 0:36