Custom border around QGraphicsView - c++

I have this image :
I want the border of my GraphicsViewbecome exactly like this image.
(consider the bellow image I want the top white rectangle become that shape)
I inherit a class from QGraphicsView and tried drawing this image in both drawBackground and paintEvent but none of them works.
My code :
.h file
class GraphicsTraxSuggestionView : public QGraphicsView {
Q_OBJECT
public:
GraphicsTraxSuggestionView(QWidget* widget);
protected:
// void paintEvent(QPaintEvent *event);
void drawBackground(QPainter *p, const QRectF &rect);
private:
};
.cpp file
GraphicsTraxSuggestionView::GraphicsTraxSuggestionView(QWidget* widget)
: QGraphicsView(widget)
{
//setFrameShadow(QFrame::Raised);
setFrameStyle(QFrame::NoFrame);
setStyleSheet("QGraphicsView { border-style: none; }");
}
void GraphicsTraxSuggestionView::drawBackground(QPainter *painter, const QRectF &rect)
{
painter->drawImage(rect, QImage("suggestionBorder.png"));
}
result of my code : http://i.stack.imgur.com/r0waP.png
Any suggestion ?

1) Create a QGraphicsScene having the size of you image
2) Set it as the view's scene
3) Draw in the drawBackground as you're doing now

I tried setMask() and now it works fine .
GraphicsTraxSuggestionView::GraphicsTraxSuggestionView(QWidget* widget,QGraphicsScene* scene)
: QGraphicsView(widget),
scene_(scene)
{
setStyleSheet("background-color: transparent;");
QPixmap myPixmap = QPixmap(":/Game/Tiles//suggestionBorder.png").scaled
(scene_->sceneRect().size().width(),scene_->sceneRect().size().height());
setMask(myPixmap.mask());
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
}
void GraphicsTraxSuggestionView::drawBackground(QPainter *painter, const QRectF &rect)
{
painter->drawImage(scene_->sceneRect(), QImage(":/Game/Tiles//suggestionBorder.png"));
}
result :

Related

How to create a click effect on a QLabel?

How i could create a click effect similar to push buttons on a QLabel?
QPixmap pixmap;
pixmap.load(":/files/hotkeys.png");
int w = 131;
int h = 71;
pixmap = pixmap.scaled(w, h, Qt::KeepAspectRatio);
// Label
ui.label->setGeometry(220, 220, w, h);
ui.label->setPixmap(pixmap);
// Button
QIcon icon(pixmap);
ui.toolButton->setIconSize(QSize(w, h));
ui.toolButton->setIcon(icon);
ui.toolButton->setStyleSheet("QToolButton { background-color: transparent }");
By click effect i mean like when you click on a push button containing a picture:
Ideally you'd just use a QToolButton or QPushButton, but if you must use a QLabel, you could do it by subclassing QLabel with a custom paintEvent() to give the desired effect, something like this:
class MyLabel : public QLabel
{
public:
MyLabel(const QPixmap & pm) : _isMouseDown(false) {setPixmap(pm);}
virtual void mousePressEvent( QMouseEvent * e) {_isMouseDown = true; update(); e->accept();}
virtual void mouseReleaseEvent(QMouseEvent * e) {_isMouseDown = false; update(); e->accept();}
virtual void paintEvent(QPaintEvent * e)
{
QPainter p(this);
const int offset = _isMouseDown ? 2 : 0;
p.drawPixmap(QPoint(offset, offset), *pixmap());
}
private:
bool _isMouseDown;
};

QPainter paints only part of the rectangle over QImage

I'm loading image into QImage from data in memory, I've managed successfully paint it with QPainter onto QWidget. Then I'm trying to change some pixels of this QImage to highlight rectangle area using rubber band. My problem is that I'm getting only part of the rectangle, and sometimes nothing at all (see picture below). Code .h:
class PaintWidget : public QWidget
{
Q_OBJECT
public:
using QWidget::QWidget;
void setSourceSample(Sample src) ;
void drawRectangle(OCRRectangle rect);
protected:
void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *ev) override;
void mouseMoveEvent(QMouseEvent *ev) override;
void mouseReleaseEvent(QMouseEvent *ev) override;
private:
QRectF target=QRectF(0, 0, 1000, 1000);
QImage p_source;
QPoint origin, end;
QRubberBand * rubberBand;
QPair<float, float> rsz_ratio;
void calcROI();
QPoint translateCoordinates(cv::Point point);
};
Code .cpp:
void PaintWidget::paintEvent(QPaintEvent *event) {
QPainter p(this);
p.drawImage(target, p_source);
}
void PaintWidget::mousePressEvent(QMouseEvent *ev) {
origin=ev->pos();
rubberBand=new QRubberBand(QRubberBand::Rectangle, this);
rubberBand->setGeometry(QRect(origin, QSize()));
rubberBand->show();
}
void PaintWidget::mouseMoveEvent(QMouseEvent *ev) {
rubberBand->setGeometry(QRect(origin, ev->pos()).normalized());
}
void PaintWidget::mouseReleaseEvent(QMouseEvent *ev) {
end=ev->pos();
rubberBand->hide();
delete rubberBand;
calcROI();
}
void PaintWidget::calcROI() {
int p1x=min(end.x(),origin.x())*rsz_ratio.first;
int p2x=max(end.x(),origin.x())*rsz_ratio.first;
int p1y=min(end.y(), origin.y())*rsz_ratio.second;
int p2y=max(end.y(), origin.y())*rsz_ratio.second;
drawRectangle(OCRRectangle(cv::Point(p1x, p1y),cv::Point(p2x, p2y)));
}
void PaintWidget::setSourceSample(Sample src) {
QImage inter=src.toQImage();
p_source=inter.convertToFormat(QImage::Format::Format_RGB32);
rsz_ratio.first=(float)src.size().width/(float)(target.width());
rsz_ratio.second=(float)src.size().height/(float)target.height();
}
QPoint PaintWidget::translateCoordinates(cv::Point point) {
QPoint qtpoint;
qtpoint.setX(point.x);
qtpoint.setY(point.y);
return qtpoint;
}
void PaintWidget::drawRectangle(OCRRectangle rect) {
QPoint p1(translateCoordinates(rect.p1)), p2(translateCoordinates(rect.p2));
for (int i=p1.x(); i<=p2.x(); i++) {
p_source.setPixelColor(i,p1.y(),QColor(255,0,0));
p_source.setPixelColor(i, p2.y(), QColor(255,0,0));
}
for (int i=p1.y(); i<=p2.y(); i++) {
p_source.setPixelColor(p1.x(),i,QColor(255,0,0));
p_source.setPixelColor(p2.x(),i,QColor(255,0,0));
}
}
UPDATE: it seems that the problem lies within rescaling of original image. When I'm drawing filled red rectangle it goes absolutely fine, my guess is that rescaling 1px border rectangle is just erasing borders. But setting thicker borders (up to 5 pixels) doesn't provide me with solution.
Making thicker borders solved this problem.

Custom QGraphicsItem That Contains Child QGraphicsItems

I am new at Qt and I want to write my custom QGraphicsItem which contains a rectangle and couple of buttons. I want to write a single custom component that could be easily added to QGraphicsScene and moved or resized with contents(buttons and rectangles) in it. In the end I want to add multiple customized QGraphicsItem to my QGraphicsScene. My question is how can I write this customized QGraphicsItem that contains buttons and rectangles which relative positions to each other are constant.
In this drawing green colored rectangles represent buttons and their relative position to each other always stays same (as if they are placed using qlayouts)
Thanks to #replete, from the example at http://doc.qt.io/qt-5/qtwidgets-graphicsview-dragdroprobot-example.html I was able to create a custom QGraphicsItem with clickable sub-parts in it. In code below BboxItem represents container QGraphicsItem and BboxItemContent represents childs of it. By emitting signals whith mause click events I was able to implement button like features. And I can move the BboxItem by setting its bounding rectangle.
BboxItem related source code:
BboxItemContent::BboxItemContent(QGraphicsItem *parent, int type, QColor color,QRectF *rect)
: QGraphicsObject(parent)
{
content_rectangle = rect;
content_type = type;
switch (type)
{
case 0:
rectangle_color = color;
icon = 0;
break;
case 1:
icon = new QImage(":/resource/assets/info_btn.png");
break;
case 2:
icon = new QImage(":/resource/assets/close_btn.png");
break;
}
}
BboxItemContent::~BboxItemContent()
{
delete icon;
}
QRectF BboxItemContent::boundingRect() const
{
return QRectF(content_rectangle->x(), content_rectangle->y(), content_rectangle->width(), content_rectangle->height());
}
void BboxItemContent::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget)
{
if (icon == 0)
{
QPen pen(rectangle_color, 3);
painter->setPen(pen);
painter->drawRect(*content_rectangle);
}
else
{
painter->drawImage(*content_rectangle, *icon);
}
}
void BboxItemContent::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
emit bboxContentClickedSignal();
}
void BboxItemContent::setRect(QRectF *rect)
{
content_rectangle = rect;
update();
}
BboxItem::BboxItem(QGraphicsItem *parent,QRectF *itemRect) : BboxItemContent(parent,0,Qt::red, itemRect)
{
setFlag(ItemHasNoContents);
bbox_area = new BboxItemContent(this, 0, Qt::red, itemRect);
info_btn = new BboxItemContent(this, 1, Qt::red, new QRectF(itemRect->x() - 30, itemRect->y(), 30, 30));
connect(info_btn, &BboxItemContent::bboxContentClickedSignal, this, &BboxItem::onInfoClickedSlot);
delete_btn= new BboxItemContent(this, 2, Qt::red, new QRectF((itemRect->x()+itemRect->width()), itemRect->y(), 30, 30));
connect(delete_btn, &BboxItemContent::bboxContentClickedSignal, this, &BboxItem::onDeleteClickedSlot);
}
void BboxItem::onDeleteClickedSlot()
{
//delete clicked actions
}
void BboxItem::onInfoClickedSlot()
{
//info clicked actions
}
void BboxItem::setRect(QRectF *rect)
{
bbox_area->setRect(rect);
info_btn->setRect(new QRectF(rect->x() - 30, rect->y(), 30, 30));
delete_btn->setRect(new QRectF((rect->x() + rect->width()), rect->y(), 30, 30));
}
Related Headers:
class BboxItemContent : public QGraphicsObject
{
Q_OBJECT
public:
BboxItemContent(QGraphicsItem *parent = 0, int type = 0, QColor color = Qt::red, QRectF *rect=nullptr);
~BboxItemContent();
// Inherited from QGraphicsItem
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) override;
void setRect(QRectF *rect);
signals:
void bboxContentClickedSignal();
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
private:
QImage *icon;
QColor rectangle_color;
QRectF *content_rectangle;
int content_type;
};
class BboxItem : public BboxItemContent {
Q_OBJECT
public:
BboxItem(QGraphicsItem *parent = 0,QRectF *itemRect=nullptr);
void setRect(QRectF *rect);
private slots:
void onDeleteClickedSlot();
void onInfoClickedSlot();
private:
BboxItemContent *delete_btn;
BboxItemContent *bbox_area;
BboxItemContent *info_btn;
};

Calling Qpainter's method paint to refresh image and change color

I have created a object call Player which inherits from QGraphicsObject.
What I am trying to do is to change the image of the player and the colour of the bounding shape when I click on it with the mouse. The thing is i don't know what values to send to player->paint() to update the image.
I override the two pure virtual functions as follows
In player.h :
class Player : public QGraphicsObject
{
public:
Player();
QRectF boundingRect() const;
QPainterPath shape() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget);
void mousePressEvent(QGraphicsSceneMouseEvent *event);
}
in player.cpp
Player::Player()
{
QPixmap m_playerPixmap(":/images/images/chevalier/test1.png");
}
QRectF Player::boundingRect() const
{
return QRectF(-15, 0, 128, 130);
}
QPainterPath Player::shape() const
{
QPainterPath path;
path.addEllipse(-15, 70, 100, 60);
return path;
}
void Player::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget)
{
QPen linepen;
linepen.setWidth(5);
linepen.setColor(Qt::red);
painter->setPen(linepen);
painter->drawPath(shape());
painter->drawPixmap(0, 0, m_playerPixmap);
}
void Player::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
this->paint();
}
Thanks a lot for your help.
You have to call update().
This will mark the item to be updated, and issue a paint event, which will then call paint with the correct parameters

Qt tableView - add color

How do I add color on the sides of a tableView?
You should subclass QHeaderView and implement your own class like:
#include<QtWidgets>
class HeaderView: public QHeaderView
{
public:
HeaderView():QHeaderView(Qt::Vertical)
{}
void paintSection(QPainter * painter, const QRect & rect, int logicalIndex) const
{
QBrush brush;
if(logicalIndex == 0)
brush.setColor(QColor(Qt::red));
else
brush.setColor(QColor(Qt::blue));
painter->fillRect(rect, brush);
QPen pen(Qt::white);
painter->setPen(pen);
painter->drawText(rect,QString("Row %1").arg(logicalIndex));
}
};
Next set an instance of HeaderView as the vertical header of the QTableView:
HeaderView vView;
tableview.setVerticalHeader(&vView);