QPushButton when subclassed draws box around icon - qt

I am trying to customize a QPUshButton by subclassing it and overriding the paintEvent. I am writing the text, followed by the icon as below:
paintEvent(QPaintEvent *paint)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
//Draw the base
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
//Draw the text
style()->drawItemText(&p,this->rect(),Qt::AlignCenter,(this->palette()), true, this->text());
if(!this->icon().isNull())
//Draw the icon at 75% button height
style()->drawItemPixmap(&p, this->rect(),Qt::AlignRight|Qt::AlignVCenter, this->icon().pixmap(this->rect().height() * 0.75));
}
However, the button I get is as below:
If you can see, there is a box around the icon image. How do I remove that? (The icon size appears bigger because I took the snapshot before I reduced the size. However, the box appears even if the image is much smaller and fits into the image).

Related

How can I show/hide background drawing on QGraphicsScene or QGraphicsView?

I would like to have certain things drawn on QGraphicsScene, but not be QGraphicsItem (it would interfere with the processing of the QGraphicsItem collection).
Example: a scene bounding rectangle, a grid
I am overriding the drawBackground(QPainter *painter, const QRectF &rect) for that purpose. (I should subclass the scene... )
void MyView::showHideBounds()
{
m_showBackgroundBounds = !m_showBackgroundBounds;
// can't triger an update ???
update(); // neither does anything
viewport()->update();
}
void MyView::drawBackground(QPainter *painter, const QRectF &rect)
{
QPen pen;
if(m_showBackgroundBounds)
pen = QPen(QColor(0, 0, 0), 10, Qt::PenStyle(Qt::SolidLine));
else
pen = QPen(QColor(255, 255, 255), 10, Qt::PenStyle(Qt::SolidLine));
painter->setPen(pen);
painter->drawRect(QRect(QPoint(-scene()->sceneRect().size().toSize().width()/2,
-scene()->sceneRect().size().toSize().height()/2),
scene()->sceneRect().size().toSize()));
}
I would like the option to show/hide either the bounding rectangle or the grid.
The only thing I can think of is paint over them with the color of the background brush ? Is there any other option ?
As I have written it above, it works - except I need user action on items (or a zoom or some other scene changing action) to trigger refresh, or call an update... (the function showHideBounds doesn't - not sure how to make it force a refresh)
I would call the drawBackground from the showHideBounds function - but I don't know how to get the painter
[Also, the drawBackground seems to be drawn automatically... how can I give it the rect argument it needs ? (it seems if I draw the rect it does draw the scene rectangle but I only see the right and bottom edges)]
In order to redraw a particular section of scene, you can call
QGraphicsScene->invalidate(rect_to_redraw, Backgroundlayer)
Note that if drawBackground(*painter, rect) paints over area outside rect, it will not update automatically. In that case invalidate has to be called with appropriate rect parameters.

increase selection outline width in QGraphicsTextitem

i have a QGraphicsTextitem with text interaction where user can edit the current text and add the new text . but my new requirement is to increase the selection outline width and can be controlled by a QSlider. is it possible to increase the dotted selection width of the QGraphicsTextItem.
i wanted to increase the pen thickness or size of the selection box coming around the text ..
in the image a dotted lines bound the text . is it possible to increase the dotted line pen size or thickness.
This question is ancient, but I'll do my civic duty to try an answer:
There are a few things you must do.
Subclass your QGraphicsTextItem
Override the paint method, and inside it remove the default selection style, and draw your own
void TextItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
QStyleOptionGraphicsItem opt(*option);
// Remove the selection style state, to prevent the dotted line from being drawn.
opt.state = QStyle::State_None;
// Draw your fill on the item rectangle (or as big as you require) before drawing the text
// This is where you can use your calculated values (as member variables) from what you did with the slider
painter->setPen(Qt::NoPen);
painter->setBrush(Qt::green);
painter->drawRect(whateverRectangle());
// Call the parent to do the actual text drawing
QGraphicsTextItem::paint(painter, &opt, widget);
// You can use these to decide when you draw
bool textEditingMode = (textInteractionFlags() & Qt::TextEditorInteraction);
bool isSelected = (option->state & QStyle::State_Selected);
// Draw your rectangle - can be different in selected mode or editing mode if you wish
if (option->state & (QStyle::State_Selected))
{
// You can change pen thickness for the selection outline if you like
painter->setPen(QPen(option->palette.windowText(), 0, Qt::DotLine));
painter->setBrush(Qt::magenta);
painter->drawRect(whateverRectangle());
}
}
You may have to override the boundingRect, opaqueArea and shape functions to account for your increased size.

QImage overlay with mouse selection

How to highlight the pixels in a QImage to highlight or draw a overlay on the pixels which user selected using mouse. I just want to know how i can specify the particular area.
Ex: With a 400x400 QImage data how i can increase or decrease the pixel intensity or overlap an image on top of it where the user selected.
You can involve QPainter (please refer to the documentation) to draw over your QImage. It allows drawing another images, rectangles, lines etc.
void View::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
// Draws your original image.
painter.drawImage(0, 0, myImage);
// Draws a blue rectangle over the image.
QPen rectPen(Qt::blue);
rectPen.setStyle(Qt::DashLine);
painter.setPen(rectPen);
painter.drawRect(0, 0, 100, 100);
[..]
}
You can maintain your mouse clicks and movement and draw corresponding stuff in paint event handler.

QLinearGradient doesn't work properly with QBrush

I want to draw 1 digit on the screen by the graphic framework classes. I want the fill approach of '1' to be something like
(source: qt-project.org)
but the brush of my drawn '1' is just like a yellow SolidBrush by the below code (an ugly bold yellow '1'). Can you help me what's wrong with it?
QGraphicsSimpleTextItem digit_1 = new QGraphicsSimpleTextItem;
digit_1->setText(QString::number(1));
digit_1->setPen(QPen(QColor("black")));
QLinearGradient gradient(digit_1->boundingRect().topLeft(),
digit_1->boundingRect().bottomRight());
gradient.setColorAt(0, Qt::white);
gradient.setColorAt(1, Qt::yellow); // yellow is for example
QBrush brush(gradient);
brush.setStyle(Qt::BrushStyle::LinearGradientPattern);
digit_1->setBrush(brush);
digit_1->setFont(QFont("courier", 35, QFont::Black));
Thanks in advanced.
Your issue most likely comes from the fact that you're basing your gradient's "area" on the bounding rect of your item before you set the font size to something much larger than the default.
The bounding rect you're getting is thus much smaller than your actual bounding rect. Since the default spread method is padding, you're seeing most likely just one color (or not enough of the gradient for it to be actually visible).
So move your setFont call to the top, before you create the gradient. You can drop the setStyle on your brush, that's determined automatically from the gradient. (In fact, you can drop that brush entirely and use the gradient in setBrush.)
With the way you set up the gradient, you'll get a "diagonal" gradient. If you want it from top to bottom, use the top left and bottom left points instead.
Demo
#include <QtGui>
class W: public QGraphicsView
{
Q_OBJECT
public:
W(QWidget *parent = 0)
: QGraphicsView(parent)
{
QGraphicsSimpleTextItem *item = new QGraphicsSimpleTextItem;
item->setText("Stack Overflow");
item->setPen(QPen(Qt::red));
item->setFont(QFont("courier", 60, QFont::Bold));
QLinearGradient lgrad(item->boundingRect().topLeft(),
item->boundingRect().bottomLeft());
lgrad.setColorAt(0.0, Qt::red);
lgrad.setColorAt(1.0, Qt::yellow);
item->setBrush(lgrad);
QGraphicsScene *scene = new QGraphicsScene;
scene->setBackgroundBrush(QBrush(Qt::black));
scene->addItem(item);
setScene(scene);
}
};

how to get the end position of drawItemText in Qt

I am trying to customize a QPUshButton by subclassing it and overriding the paintEvent. I am writing the text, followed by the icon as below:
paintEvent(QPaintEvent *paint)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
//Draw the base
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
//Draw the text
style()->drawItemText(&p,this->rect(),Qt::AlignCenter,(this->palette()), true, this->text());
//How do I make the image immediately follow the text
if(!this->icon().isNull())
//Draw the icon at 75% button height
style()->drawItemPixmap(&p, this->rect(),Qt::AlignRight|Qt::AlignVCenter, this->icon().pixmap(this->rect().height() * 0.75));
}
I am center aligning the text, and right aligning the icon. However, this causes a gap between the text and the icon. Is there any way for me to draw the icon immediately after the text, instead of aligning?
In other words, is there any way to get the position where the drawItemText finished?
QStyle::itemTextRect() will tell you where the text will be laid down with given rectangle, font metrics and alignment.
QFontMetrics will tell you how wide your text is. It doesn't know about your rectangle, so you will have to do the alignment calculation yourself.

Resources