Создаю в конструкторе:
pRight = new QGraphicsRectItem;
pRight->setRect(580, 300, 20, 300);
pRight->setPen(QPen(Qt::black));
pRight->setBrush(QBrush(Qt::green));
addItem(pRight);
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;
}
держи код, который работает, но это в классе итема, а не сцены:
void TextItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
point=event->pos();
}
void TextItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
setPos(event->scenePos()-point);
}
спасибо, значит я просто пошел не той дорогой.
у меня были сомнения делать ли класс от сцены или от итема....теперь вроде понятно.
Я сделал, действительно итем двигается без проблем, все нормально. Но моей основной целью было - при движение одного итема, другой должен дорисовываться....вот с последним теперь беда, как дорисовать другой итем?
Я делаю на примере квадрата - сделал четыре створки квадрата.
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);
}
Вот код, двигающий левую и верхнюю грани... Надеюсь, он наставит тебя на путь...
Тебе не нужны ректитемы, достаточно в твоём классе нарисовать в 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::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();
}
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::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();
}
Что-то после нескольких дней экспериментов я понял, что метод который предложил ABC не совсем мне подходит ((.
Да действительно при наследование от QGraphicsItem и рисование линий квадрат растягивается.....но нужно нечто иное.
Как образец рассматриваю программу IT-Окна, там есть графический редактор...если присмотреться там отчетливо видно что каждая створка и стекло - это отдельный элемент.
Сейчас пробую унаследовать класс от QGraphicsPolygonItem. Задал в нем общие 8-мь QPointF. Далее наследую от этого класса 4е класса где создаются 4е полигона - каждый по форме створки окна.
В итоге опять прихожу к вопросу - как при перемещение одного полигона дорисовать другие? Я пробовал делать глобальными эти 8-мь точек, но перерисовка идет если кликаю, после перемещения к примеру правого итема, по итему к примеру верхнему.
Я что-то столько времени уже потратил, может это нереально сделать? Я уже в отчаянии =(
что-то я не понял, какой результат нужно получить, полигон меня совсем запутал.. официальное задание есть?
IT Окна. Конструктор
?
установил, не запускается - "напишите микрософту"
изначально под "резиновым квадратом" я понимал квадрат, который может стать параллелепипедом... эта функция нужна? Или ты просто хочешь изменять размеры граней прямоугольника, не кособоча его? окна ведь могут быть кособокими, я б такое хотел)
тебе нужна не тонкая линия рамы, а толстая? Чем толще линия, тем нелепее будут выглядеть скособоченные углы... тут нужно ещё с ними мучиться... арка тоже интересненько.. полуэллипс...
короче, надо как-то сцеплять грани, задача ясна)
про полигон всё равно идея не дошла... зачем там 8 точек... вроде ведь нужно 4
class WindowItem : public QObject, public QGraphicsPolygonItem
{
Q_OBJECT
public:
WindowItem(QGraphicsItem *parent=0);
void setupPoint();
protected:
// полигоны
QPolygonF lPoly; // левая свт
QPolygonF rPoly; // правая свт
QPolygonF tPoly; // верхняя свт
QPolygonF bPoly; // нижняя свт
QPolygonF packP; // стеклопакет
// вершины
QPointF point1;
QPointF point2;
QPointF point3;
QPointF point4;
QPointF point5;
QPointF point6;
QPointF point7;
QPointF point8;
};
// класс левой створки
class leftGlume : public WindowItem
{
Q_OBJECT
public:
leftGlume(QGraphicsItem *parent=0);
void setupLG();
private:
QPointF oldLeft;
void mousePressEvent(QGraphicsSceneMouseEvent *e);
void mouseMoveEvent(QGraphicsSceneMouseEvent *e);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *e);
};
......
а, да, полигон для грани это выглядит хорошо, надо думать, пробовать...
либо 5 итемов склеивать... как их перерисовывать только...
либо в одном итеме рисовать в методе paint полигоны... тогда вся конструкция как бы будет монолитом... но нужно будет проверять, какой полигон под мышкой... а как его отдельно окрашивать...
а окно может быть не параллелепипедом?
пока не знаю, что сказать, нужно пробовать,
завтра, может быть, или на выходных,
интересная у тебя работа
Я тут подумал....а QGraphicsItemGroup может как-нибудь помочь или это из другой песни?
насколько я понимаю, раз это сделает итемы единым целым, нам это не подходит,
нужно ведь, чтобы каждая итема реагировала на мышь отдельно.
в общем, сейчас пытаюсь реализовать на основе полигонов...
при каждом MoveEvent придётся итему устанавливать новый полигон, с докорректированными точками...
пока не знаю, что из этого выйдет... но звучит не очень приятно)
#include "windowitem.h"
QPointF point1;
QPointF point2;
QPointF point3;
QPointF point4;
QPointF point5;
QPointF point6;
QPointF point7;
QPointF point8;
.......
void RightGlume::mouseMoveEvent(QGraphicsSceneMouseEvent *e)
{
setPos(e->scenePos().x()-oldRight.x(), pos().y());
QRectF rect = sceneBoundingRect();
// Обновляю точки
point1 = QPointF(rect.x()+20, point1.y());
point4 = QPointF(rect.x(), point4.y());
update();
}
......
// Теперь если передвинуть правую створку, а потом нажать на верхнюю
........
void TopGlume::mousePressEvent(QGraphicsSceneMouseEvent *e) // перерисовываем верхний полигон
{
oldTop = e->pos();
tPoly.clear();
tPoly << point8;
tPoly << point1;
tPoly << point4;
tPoly << point7;
setPolygon(tPoly);
setFlag(QGraphicsItem::ItemIsSelectable, true);
setBrush(QBrush(Qt::black,Qt::BDiagPattern));
}
........
верю на слово ))
Я тут ещё подумал, по мимо всего нужно ещё и размеры же показать ширина длинна, расстояние от створок до импоста (перекладины)....
да, сетку неплохо бы ненавязчивую.
чтоб такую программу сделать хорошей, много чего нужно,
задний фон с фоткой коттеджа какого-нибудь, где окно будет "смотреться"..
неплохо бы и дождь прикрутить многие любят дождь на окнах
хотел показать тебе exe.. нифига не позволяет форум "вам запрещено загружать такой тип файлов"... заархивировал, то же самое...
спасибо, Юра)
windows_designer.zip ( 27.21 килобайт )
: 117
квадрат адекватен, только если раздвигать его, скукошивание не обрабатывал
я пытался добиться, чтобы, при раздвигании, грани створок оставались пареллельны, а увеличение эт побочный еффект
я думаю, нужно поставь задачу иначе, потому что я тоже написал с использованием глобальных переменных, код организован просто отвратно, плюс столкнувшись с этой параллельностью, понял, что погоня за этой абсолютной резиновостью нас приведёт к сложным неразберихам.. в частности, чтоб убрать утолщение граней надо сильно посидеть. А код такой оставлять нельзя..
может, получится предусмотреть возможные конфигурации окон?..
Заказчик может захотеть восьмигранник какой-нибудь.. и я его не виню) возможно, нужно предусмотреть меню, где вводишь количество граней, их размеры, и тебе рисуется фигура..
а вот если угол между гранями должен быть 53 градуса, как мы их отмерим? блин, забыл дома попробовать установить ИТ окна
ИТ окна почти запустились - оказалось, что нужно было поставить фаирбёрд. ужас, это не узнать даже из их инструкции по установки... зато можно узнать, что нужно "вставить ключ".. куда?? где он?? ну, какую-то защиту ключа я установил и что? катастрофа! при запуске "ключ не найден"...
по теме - делаю грань, которая одновременно умеет поворачиваться, менять положение любой из вершин и двигаться... вроде бы из таких граней реально состроить любой многоугольник, правда это не самое быстрое занятие... зато гибко
супер окна тоже не запускаются ставил бесплатную версию
написал-таки крутящийся-растягивающийся-двигающийся полигон. могу признать, что с кручением намучился
крутится за середину верхней и середину нижней граней
WD.zip ( 34.5 килобайт )
: 117
теперь хорошо бы сделать сетку и научиться привязывать итемы к ней
Кстати, есть ещё идея со сигналами/слотами...Это я про дорисовку полигонов.
Можно ли как-нибудь сделать общий слот в котором будет происходить перерисовка объектов, а объекты в которых происходит изменение позиции будут слать сигнал с новыми данными в слот..... Что-то типа того, было бы не плохо, но я вообще без понятия реально ли это реализовать.
в реализации new Arс ты столкнулся с той же проблемой, что и я - когда при скашивании граней, они теряют параллельность своих линий. А почему нельзя добавить больше одной перегородки?
в реализации newWindow можно раздвигать и без кликов - глобальные переменные спасае)
а моя грань поможет сделать сложную фигуру, это может быть одной из возможностей программы... чтоб уметь нарисовать совершенно косое кривое извращение
я думаю, что нужно как раз качественно реализовать наиболее часто используемый вид окна - прямоугольник, с возможностью добавлять внутрь перегородки, удалять грани и притютюхивать на их место арку..
можно просто несколько шаблонов сделать - простой прямоугольник, прямоугольник с аркой, ну и что там ещё
ещё тебе нужно уметь изменять ширину граней... а уголки двух граней, которые стыкуются, всегда равны?
я проснулся ночью в поту! я полдня мучился, не знал, как обойтись без глобальных переменных, а ведь это же очевидно - двигать итемы в классе сцены... она будет знать обо всех точках итемов, и всех их перерисовывать... итемам ничего не нужно будет знать друг о друге... я помню, как я в начале нашей работы отвёл тебя от идеи ловить мышь в классе сцены... я, однако, тогда не знал, что квадрат будет составлен из нескольких полигонов, а потом я совершенно не подумал вернуться к твоему изначальному плану.
короче, твой вариант с дорисовыванием по кликам можно доработать... но скашивание всё равно вызовет проблемы, о которых я уже писал
по вопросам:
1) а как ты одну добавляешь? это ведь QGraphicsRectItem?
2) ты не понял, как совместно перерисовывать полигоны? или как это сделать без глобальных переменных?
если грани имеют стандартную ширину, это облегчает дело, но я ещё хочу обратить твоё внимание, что размеры нашего окна должны быть пропорциональны размерам реального окна
2) задаёшь новые координаты вершин, затем устанавливаешь новые полигоны для итемов, в которых эти вершины участвуют
а я вижу пользование этой программой так:
передо мной бумажка, на которой расписаны размеры окна. я в программе ввожу эти размеры, а программа их пропорционально уменьшает и рисует окно.. Зачем мне колбасить окно мышью, если заранее известны размеры? Створки в окно можно добавлять уже вручную... а можно и створки по заданным размерам автоматом рисовать. ну, это с прямоугольным окном. более сложные детали, наверное, пусть пользователь сам рисует
пусть двигается, но изначально строй окно по заданным размерам, пожааааалуйста)
вот двигаю полигоны в классе сцены
красота)
WDesigner.zip ( 30.64 килобайт )
: 187
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)