Russian Qt Forum

Qt => Вопросы новичков => Тема начата: demaker от Май 08, 2014, 13:38



Название: Graphics View Framework
Отправлено: demaker от Май 08, 2014, 13:38
Хочу закрасить произвольную область при нажатии кнопки мыши.

Код
C++ (Qt)
 
class Item: public QGraphicsItem
{
public:
   Item(QGraphicsItem*parent = 0)
       :QGraphicsItem(parent),down(false){}
 
   QRectF boundingRect() const
   {
       return QRectF(0,0,100,70);
   }
 
   void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
   {
       QPen pen(QBrush(Qt::black),3, Qt::SolidLine);
       painter->setBrush(down ? Qt::red : Qt::green);
       painter->setPen(pen);
 
       painter->drawLine(10,10,200,10);
       painter->drawLine(200,10,200,50);
       painter->drawLine(200,50,50,50);
       painter->drawLine(50,50,50,70);
       painter->drawLine(50,70,100,70);
       painter->drawLine(100,70,100,100);
       painter->drawLine(10,10,10,100);
       painter->drawLine(10,100,100,100);
   }
 
protected:
 
   void mousePressEvent(QGraphicsSceneMouseEvent* event)
   {
       if(!down)
       {
           down = true;
           update();
           qDebug()<<down;
       }
   }
 
   void mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
   {
       if(event->buttons() == 0)
       {
           down = false;
           update();
           qDebug()<<down;
       }
   }
 
private:
   bool down;
};
 
 

Но закраска не происходит, хотя события по нажатию кнопки мыши срабатывают.
Возможно ли закрасить произвольную область???


Название: Re: Graphics View Framework
Отправлено: Hellraiser от Май 08, 2014, 13:58
Заливку области надо делать через fillRect(boundingRect(), QBrush(Qt::red)).


Название: Re: Graphics View Framework
Отправлено: demaker от Май 08, 2014, 14:11
Да и каккую же область он мне закрасит???
Код:
boundingRect();
А не которую я линиями нарисовал.
Разве нет???


Название: Re: Graphics View Framework
Отправлено: Bepec от Май 08, 2014, 14:17
Вы чего хотите?  Закрасить произвольную область за пределами объекта ? Так он и закрасит. А перед этим painter clip'ом обрежет до размеров вашего объекта.

Сформулируйте свою хотелку полностью :)


Название: Re: Graphics View Framework
Отправлено: xokc от Май 08, 2014, 14:26
Вы чего хотите? 
Судя по единственному заданному вопросу,
Возможно ли закрасить произвольную область???
он хочет ответ да/нет. Мой ответ - да.
Если вопрос всё же "как это сделать?", то мой ответ использовать QPainter::drawPolygon. Только, как совершенно справедливо заметил Верес, в качестве координат рисуемого полигона стоило бы использовать точки внутри видимой области виджета, а не за её пределами.


Название: Re: Graphics View Framework
Отправлено: Hellraiser от Май 08, 2014, 14:27
Да и каккую же область он мне закрасит???
Код:
boundingRect();
А не которую я линиями нарисовал.
Разве нет???
Он закрасит ту область в пределах фигуры, которую вернет boundingRect(), который сам же и определил. В программировании не бывает произвольных областей, любую надо определить.


Название: Re: Graphics View Framework
Отправлено: demaker от Май 08, 2014, 15:10
А вот я сделал так - это правильно???
Код
C++ (Qt)
class Item: public QGraphicsItem
{
public:
   Item(QGraphicsItem*parent = 0)
       :QGraphicsItem(parent),down(false){}
 
   QRectF boundingRect() const
   {
       return QRectF(0,0,300,200);
   }
 
   QPainterPath shape() const
   {
       QPainterPath path;
 
       QPolygon polygon;
       polygon << QPoint(10 ,10)
               << QPoint(200,10)
               << QPoint(200,50)
               << QPoint(100,50)
               << QPoint(100,80)
               << QPoint(150,80)
               << QPoint(150,200)
               << QPoint(10,200)
               << QPoint(10,10);
 
       path.addPolygon(polygon);
       return path;
   }
 
   void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
   {
       QPen pen(QBrush(Qt::black),3, Qt::SolidLine);
       painter->setBrush(down ? Qt::red : Qt::green);
       painter->setPen(pen);
       painter->drawPath(shape());
   }
 
protected:
 
   void mousePressEvent(QGraphicsSceneMouseEvent* event)
   {
       if(!down)
       {
           down = true;
           update();
           qDebug()<<down;
       }
   }
 
   void mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
   {
       if(event->buttons() == 0)
       {
           down = false;
           update();
           qDebug()<<down;
       }
   }
 
private:
   bool down;
};
 
 


Название: Re: Graphics View Framework
Отправлено: demaker от Май 12, 2014, 10:00
Скажите, можно ли таким же образом
взять контур из bmp-файла и закрасить его?


Название: Re: Graphics View Framework
Отправлено: kamre от Май 12, 2014, 11:26
взять контур из bmp-файла
Это как? Контур по определению векторная штука, представляемая набором точек (если состоит только из прямолинейных отрезков). А в bmp только растр.

и закрасить его?
Можно bmp загрузить в QImage, взять матрицу пикселей и самому заполнить нужные, которые как-бы в "контуре".

Вот кстати похожая тема (http://www.qtcentre.org/threads/47137-How-to-draw-a-Qgraphicsitem-on-a-Qimage).


Название: Re: Graphics View Framework
Отправлено: demaker от Май 12, 2014, 14:58
Хочу в загруженной картинки изменить цвет пиксиля,
координаты которго получаю при нажатии мыши

Код
C++ (Qt)
 
explicit GraphicsScene(QObject*parent = 0): QGraphicsScene(parent)
   {
       addPixmap(QPixmap("D:/Qt/Qt5.2.1/Tools/QtCreator/bin/Graphics/lodka.bmp"));
       sceneImage = new QImage("D:/Qt/Qt5.2.1/Tools/QtCreator/bin/Graphics/lodka.bmp");
   }
 
...
void mousePressEvent(QGraphicsSceneMouseEvent* event)
   {
       qDebug()<<event->scenePos();    //положнеие курсора относительно сцены        
       QPointF scenePoint = event->scenePos();
       sceneImage->setPixel( (int)(scenePoint.x()), (int)(scenePoint.y()) ,???);      
   }
 

Пытаюсь сделать с помощью функции
Код:
void QImage::setPixel ( int x, int y, uint index_or_rgb )This is an overloaded function.
Sets the pixel index or color at (x, y) to index_or_rgb.

но эффекта никакого.

Подскажите как сделать???




Название: Re: Graphics View Framework
Отправлено: xokc от Май 13, 2014, 09:02
А сцена в курсе, что её изменили и надо перерисоваться?


Название: Re: Graphics View Framework
Отправлено: demaker от Май 13, 2014, 09:40
это типа
Код:
update()
сделать???

Подскажите конкретнее пожалуйста


Название: Re: Graphics View Framework
Отправлено: xokc от Май 13, 2014, 10:09
это типа update() сделать???
Вроде того.

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


Название: Re: Graphics View Framework
Отправлено: demaker от Май 13, 2014, 10:12
Спасибо всем, разобрался.
Код
C++ (Qt)
class GraphicsScene: public QGraphicsScene
{
   Q_OBJECT
 
public:
 
   explicit GraphicsScene(QObject*parent = 0): QGraphicsScene(parent)
   {
       sceneImage = new QImage("D:/Qt/Qt5.2.1/Tools/QtCreator/bin/Graphics/lodka.bmp");
       QPixmap pixmap;
       addPixmap(pixmap.fromImage(*sceneImage));
   }
 
   virtual ~GraphicsScene()
   {
       delete sceneImage;
   }
 
protected:
   void mousePressEvent(QGraphicsSceneMouseEvent* event)
   {
       qDebug()<<event->scenePos();    //положнеие курсора относительно сцены
       QPointF scenePoint = event->scenePos();
       sceneImage->setPixel( (int)(scenePoint.x()), (int)(scenePoint.y()) ,155);
       QPixmap pixmap;
       addPixmap(pixmap.fromImage(*sceneImage));
    }
 
private:
   QImage *sceneImage;
};
 
 

Но почему так сложно.
Т.е я беру каждый раз и перезагружаю изображение.
А проще нельзя???


Название: Re: Graphics View Framework
Отправлено: Bepec от Май 13, 2014, 11:44
Можно. Но это будет сложнее :D Можно перегружать только изменившуюся часть и её же только отрисовывать :)


Название: Re: Graphics View Framework
Отправлено: demaker от Май 13, 2014, 11:53
Подскажите как через RGB задавать цвет, который я хочу отрисовывать, а то никак не могу понять.


Название: Re: Graphics View Framework
Отправлено: Bepec от Май 13, 2014, 12:16
QColor(R,G,B).


Название: Re: Graphics View Framework
Отправлено: demaker от Май 13, 2014, 12:18
Код:
 sceneImage->setPixel( (int)(scenePoint.x()), (int)(scenePoint.y()) ,QColor(R,G,B));
так?


Название: Re: Graphics View Framework
Отправлено: xokc от Май 13, 2014, 18:26
Код:
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent* event)
    {
        QPixmap pixmap;
        addPixmap(pixmap.fromImage(*sceneImage));
     }
};

Но почему так сложно.
Т.е я беру каждый раз и перезагружаю изображение.
А проще нельзя???
Можно и нужно. Для начала тут при каждом клике мышью в сцену добавляется новый pixmap. Боюсь при таком подходе много раз вам покликать не удастся. Делайте так (тоже плохо, но гораздо лучше чем у Вас)

Код
C++ (Qt)
explicit GraphicsScene(QObject*parent = 0): QGraphicsScene(parent)
{
   sceneImage = new QImage("D:/Qt/Qt5.2.1/Tools/QtCreator/bin/Graphics/lodka.bmp");
   QPixmap pixmap;
   item= addPixmap(pixmap.fromImage(*sceneImage));
}
 
void mousePressEvent(QGraphicsSceneMouseEvent* event)
{
   QPointF scenePoint = event->scenePos();
   sceneImage->setPixel( (int)(scenePoint.x()), (int)(scenePoint.y()) ,155);
   QPixmap pixmap;
   item->setPixmap(pixmap.fromImage(*sceneImage));
}



Название: Re: Graphics View Framework
Отправлено: Old от Май 13, 2014, 18:28
Для чего создавать ненужный экземпляр QPixmap?
Код
C++ (Qt)
void mousePressEvent(QGraphicsSceneMouseEvent* event)
{
   QPointF scenePoint = event->scenePos();
   sceneImage->setPixel( (int)(scenePoint.x()), (int)(scenePoint.y()) ,155);
   item->setPixmap( QPixmap::fromImage(*sceneImage) );
}


Название: Re: Graphics View Framework
Отправлено: demaker от Май 23, 2014, 11:17
Скажите как можно в QGraphicsItem добавить QImage?


Название: Re: Graphics View Framework
Отправлено: Hellraiser от Май 23, 2014, 12:25
В QGraphicsItem - никак. В QGraphicsPixmapItem - конвертируя QImage в QPixmap и указав в конструкторе. В свой класс, унаследованный от QGraphicsItem - аналогично.


Название: Re: Graphics View Framework
Отправлено: demaker от Май 23, 2014, 14:34
Добавляю item в сцену отображает,
но почему-то при нажатии кнопки мыши по итему метод не срабатывает(в консоль не выводит "mousePressEvent")
Подскажите что может быть неправильно?
Код
C++ (Qt)
Item::Item(QGraphicsItem *parent):
       QGraphicsItem(parent)
{
}
 
Item::~Item()
{
}
 
void Item::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
 
   qDebug()<<"mousePressEvent";
   event->accept();
}
 

Код
C++ (Qt)
 
GraphicsScene::GraphicsScene(QString path, QObject*parent)
   : QGraphicsScene(parent)
{
   sceneImage = new QImage(path);
   QPixmap pixmap;
 
   Item* item = (Item *)(addPixmap(pixmap.fromImage(*sceneImage)));  
 
}
 
GraphicsScene:: ~GraphicsScene()
{
   delete sceneImage;
}
 

Код
C++ (Qt)
   GraphicsScene scene(filepath);
   QGraphicsView view(&scene);
   view.show();
 


Название: Re: Graphics View Framework
Отправлено: demaker от Май 26, 2014, 10:16
 ???
нет никаких вариантов?


Название: Re: Graphics View Framework
Отправлено: demaker от Май 26, 2014, 11:39
Попробовал с двумя итемами
Код
C++ (Qt)
Item::Item(QGraphicsItem *parent):
       QGraphicsItem(parent)
{
}
 
Item::~Item()
{
}
 
void Item::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
   qDebug()<<"mousePressEvent";
}
 

Код
C++ (Qt)
class Item1: public QGraphicsItem
{
public:
   Item1(QGraphicsItem*parent = 0)
       :QGraphicsItem(parent),down(false){}
 
   QRectF boundingRect() const
   {
       return QRectF(0,0,100,70);
   }
 
   void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
   {
       painter->setBrush(down ? Qt::red : Qt::green);
       QPen pen(QBrush(down ? Qt::red : Qt::blue),3, Qt::DotLine);
       painter->setPen(pen);
       painter->drawEllipse(boundingRect());
   }
 
protected:
 
   void mousePressEvent(QGraphicsSceneMouseEvent* event)
   {
       if(!down)
       {
           down = true;
           update();
       }
   }
 
   void mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
   {
       if(event->buttons() == 0)
       {
           down = false;
           update();
       }
   }
 
private:
   bool down;
};
 

Код
C++ (Qt)
GraphicsScene::GraphicsScene(QString path, QObject*parent)
   : QGraphicsScene(parent)
{
   sceneImage = new QImage(path);
   QPixmap pixmap;
 
   Item* item =(Item *)(addPixmap(pixmap.fromImage(*sceneImage)));  
   addItem(new Item1);  
}
 
GraphicsScene:: ~GraphicsScene()
{
   delete sceneImage;
}
 

получается события,происходящие при нажатии мыши на Item1 обрабатываются, а на Item нет ???
Скажите почему, не могу понять! Спасибо!


Название: Re: Graphics View Framework
Отправлено: _OLEGator_ от Май 26, 2014, 11:50
Не вижу определенной функции boundingRect для Item. Как ты его вообще в таком случаем смог использовать не понятно.


Название: Re: Graphics View Framework
Отправлено: Hellraiser от Май 26, 2014, 11:58
А там Item и не используется. Код просто ужасен - может стоит подучить плюсы? В сцену сначала добавляется QGraphicsPixmapItem (именно этот объект создаст и возвратит указатель на него addPixmap). А полученный указатель приводится к другому классу и после этого не используется. Да и приведенный указатель, скорее всего, будет невалидным. Я  :'(


Название: Re: Graphics View Framework
Отправлено: demaker от Май 26, 2014, 12:24
Спасибо за разъяснение понял все
сделал так

Код
C++ (Qt)
GraphicsScene::GraphicsScene(QString path, QObject*parent)
   : QGraphicsScene(parent)
{
   sceneImage = new QImage(path);    
   QPixmap pixmap;
 
   item = new Item;
   item->setPixmap(pixmap.fromImage(*sceneImage));
 
   addItem(item);
   addItem(new Item1);
}
 


Название: Re: Graphics View Framework
Отправлено: Hellraiser от Май 26, 2014, 12:41
Зачем хранить в сцене imageScene? После конвертации пиксмапа он не нужен. Да и fromImage статический метод.


Название: Re: Graphics View Framework
Отправлено: xokc от Май 29, 2014, 12:39
Зачем хранить в сцене imageScene? После конвертации пиксмапа он не нужен.
Он же потом там пиксели меняет. Как ему это сделать напрямую в QGraphicsPixmapItem? Конвертировать item->pixmap() во локальный QImage, менять пиксел и потом обратно в pixmap? Тут я с автором согласен.


Название: Re: Graphics View Framework
Отправлено: Hellraiser от Май 29, 2014, 14:27
А где их автор предполагает менять? Если в обработчике нажатия мыши для айтема, то этот айтем ничего не знает о наличии какого-то QImage. Ему в конструкторе передан QPixmap, вот с ним он и работает. Хранить sceneImage есть смысл только при изменении пикселя в обработчике нажатия самой сцены. А потом его все-равно придется переустановить для айтема, т.к. setPixmap принимает константную ссылку и изменение оригинала его не затронут.


Название: Re: Graphics View Framework
Отправлено: xokc от Июнь 02, 2014, 13:41
А где их автор предполагает менять? Если в обработчике нажатия мыши для айтема
Именно там.
А потом его все-равно придется переустановить для айтема, т.к. setPixmap принимает константную ссылку и изменение оригинала его не затронут.
Всё так и делается. Сначала в оригинале QImage меняется пиксель, а потом делается item->setPixmap(QPixmap::fromImage(*sceneImage))
Если бы QImage нигде не хранился, то где бы взять его текущий экземпляр с изменёнными пикселями? Только преобразовать из item->pixmap(), изменить пиксель и обратно в QPixmap? Можно и так. Всё равно и то и другое решение "боевым" назвать сложно.