Why does the border of QWidget cover the contents? - css

I have a custom widget derived from QWidget, which has a minimumSize of (30, 30) and a QLabel as a childWidget:
MyWidget::MyWidget (QWidget *parent, QPoint p,
QWidget *childWidget) : QWidget (parent)
{
childWidget = this->childWidget;
setAttribute (Qt::WA_DeleteOnClose);
this->move (p);
verticalLayout = new QVBoxLayout (this);
if (childWidget != NULL)
{
childWidget->setParent (this);
childWidget->releaseMouse();
childWidget->setAttribute (Qt::WA_TransparentForMouseEvents, true);
verticalLayout->addWidget (childWidget);
}
this->setLayout(verticalLayout);
};
MyWidget::mouseMoveEvent (QMouseEvent *e)
{
if (! (e->button() == Qt::RightButton))
{
this->update();
this->raise();
}
}
void MyWidget::mouseReleaseEvent (QMouseEvent *evt)
{
QWidget::mouseReleaseEvent(evt);
this->update();
}
MyWidget::mousePressEvent (QMouseEvent *e)
{
if (! (e->button() == Qt::RightButton))
{
this->update();
this->raise();
}
}
void MyWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(Qt::darkGreen);
painter.drawRect(1, 2, 6, 4);
painter.setPen(Qt::darkGray);
painter.drawLine(2, 8, 6, 2);
}
//And some getter/setter methods.
In order to set a border to the widget I use the following code:
customWidget->setStyleSheet("*{border-width:" +
2 +
";border-style:solid;border-color:" +
#FFFFFF + " ;color:white;}");
It looks like this (the parent widget has an orange background):
.
When I change the border-width to 10, the border covers the contents:
Both images show the widget in its minimum height.
To me it looks as if the border were applied inwards. What shall I modify to point the border outwards, so for a larger border-width the text remains visible?

Cause
The border does go outwards:
You have a problem with the size. (30, 30) is too small for this border. 30 - 2*10 (the minimum height - 2 times the width of the border) equals 10. Your font is larger than 10px, so it does not fit in the remaining space.
Solution
You might want to set a reasonable size, e.g. (100, 50). However, setting the minimum size is not flexible, meaning, that it does not account for changes in the widget's content. If the sizeHint and minimumSizeHint are implemented though, the necessary space will be reported whenever needed, as it is done in QLabel for example.
Since you already have a QLabel as a child widget, just avoid setting the minimumSize of your custom widget and the correct size will be calculated automatically.

Related

Inside a QWidget, Qwt plot is there then if i am trying to resize widget simultaneously plot should resize. how to apply resizeevent to QWidget

I have applied resizeEvent to a QWidget. I am trying to resize the widget inside another widget. I have a QWT plot that should also resize.
I have applied resizeEvent to the QWidget and resized to the plot:
void SampleWidget:: resizeEvent(QResizeEvent* event)
{
QWidget::resizeEvent(event);
int diffofWidth = event->size().width() - event->oldSize().width();
int diffofHeight = event->size().height() - event->oldSize().height();
QSize size = plot->size();
if ((event->oldSize().width() >= 0) && (event->oldSize().height() >= 0))
{
if (event->size().width() <= this->minimumWidth() && event->size().height() <= this->minimumHeight())
{
return;
}
else
{
plot->resize(size.width() + diffofWidth, size.height() + diffofHeight);
plot->replot();
}
}
}
The widget is able to resize, but after resizing many times, the plot is only displayed partially in the widget. I am not able to see whole content in the widget. What's going on here?
Assuming you are asking why your widget isn't resizing properly, you likely have minimum sizes set within the layouts. Be sure that your minimum size of the parent is greater than or equal to the sum of it's children, that could cause the child elements to be partially hidden.
Also, check sizehint and the minimum size set for each object, increase them as needed.

Qt size policy and stretch factors

How do the options size policy and stretch factors influence the size of a widget?
The image below shows previews of three differently arranged windows. For all three windows (W1-W3) the widget on the right is a QFrame widget with the horizontal and vertical size policies set to Preferred (this is the default setting). The horizontal stretch factor is set to 2. The widget on the left is a QListView widget which also has the size policies set to Preferred (by default this would be Expanding) and the horizontal stretch factor set to 1.
The three windows differ in the way the two widget are layout against each other.
(W1) The window on the left in the image above has a central widget set to a horizontal layout resulting in a size ratio of 2/3 of the widgets that I would expect because of the stretch factors set to 2 and 1.
(W2) The two widget are "connected" with each other through a QSplitter widget. The central widget is set to t horizontal layout. The results of the size of the widgets differ from W1 and are not in the ratio of 2/3.
(W3) The right window "connects" the two widget also with a QSplitter like in window W2. Howevert, The QListView widget is child to a QVBoxLayout. So the QSplitter has the QFrame and a QVBoxLayout as its children.
In detail the setup for the three different windows is shown in the image below:
I have the following questions:
Why do the ratios of the two widgets differ between W1, W2 and W3?
The ratio in W2 seems to be affected by the stretch factors, however not with the results expected. But W3 does not seem to be influenced by the stretch factors at all. Why is that the case?
The behavior of the splitter with relation to stretch factors is documented to be different than the behavior of a layout: you shouldn't expect them to look the same.
The W2 & W3 should look identical if implemented as you claim. Your ui file has a mistake in it.
Here's a test case that doesn't use a .ui file:
// https://github.com/KubaO/stackoverflown/tree/master/questions/layout-stretch-triad-37680657
#include <QtWidgets>
struct Window : public QMainWindow {
QWidget central;
QHBoxLayout layout{&central};
QListView view;
QFrame frame;
Window(const QString & title) {
setWindowTitle(title);
setCentralWidget(&central);
view.resize(300, 300);
view.setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
frame.resize(300, 300);
frame.setLineWidth(3);
frame.setFrameStyle(QFrame::Box);
resize(500, 200);
show();
}
};
struct Window1 : Window {
Window1() : Window("W1") {
layout.addWidget(&view, 1);
layout.addWidget(&frame, 2);
}
};
struct Window2 : Window {
QSplitter splitter;
Window2() : Window("W2") {
layout.addWidget(&splitter);
splitter.addWidget(&view);
splitter.addWidget(&frame);
splitter.setStretchFactor(0, 1);
splitter.setStretchFactor(1, 2);
}
~Window2() { frame.setParent(0); view.setParent(0); }
};
struct Window3 : Window {
QSplitter splitter;
QWidget leftWidget;
QVBoxLayout leftLayout{&leftWidget};
Window3() : Window("W3") {
layout.addWidget(&splitter);
splitter.addWidget(&leftWidget);
splitter.addWidget(&frame);
splitter.setStretchFactor(0, 1);
splitter.setStretchFactor(1, 2);
leftLayout.setMargin(0);
leftLayout.addWidget(&view);
}
~Window3() { frame.setParent(0); view.setParent(0); }
};
int main(int argc, char ** argv) {
QApplication app{argc, argv};
Window1 w1;
Window2 w2;
Window3 w3;
w2.move(w1.pos() + QPoint(0, 75));
w3.move(w2.pos() + QPoint(0, 75));
return app.exec();
}

QT paintEvent for a QWidget

I've a class that inherits QPushButton widget. I want to have custom look of that button so i've overrided paintEvent method. All buttons that I want to paint are childs of QFrame object.
And there I have a problem. I can't repaint those objects.
My paintEvent function:
void Machine::paintEvent(QPaintEvent*) {
QPainter painter(this);
QRect geo = this->geometry();
int x, y, width, height;
x = geo.x()-10;
y = geo.y()-10;
width = geo.width()-3;
height = geo.height()-5;
painter.fillRect(x, y, width, height, QColor(220,220,220));
painter.drawText(x+10, y+10, "Machine " + QString::number(id));
}
When a widget is in top left corner of QFrame, desired effect is ok. But when I move button somewhere else, widget starts to disappear. On images you can see whats going on:
Button is just moved some px down-left. Why it works like this? QFrame which is a container for that button is big enough.
Thanks in advance ;)
The reason is in coordinate system: geometry method returns position relatively to parent, but QPainter::drawRect accepts rectangle in local coordinates. Try this code:
void Machine::paintEvent(QPaintEvent*) {
QPainter painter(this);
int width = size().width() - 3;
int height = size().height() - 5;
painter.fillRect(0, 0, width, height, QColor(220,220,220));
painter.drawText(10, 10, "Machine " + QString::number(id));
}

QGraphicsItem doesn't detect its own boundingRect change

// QT 4.8
I've implemented a resizable QGraphicsItem, which works pretty fine.
However, now, I need to include child items in this resizable item.
Child items size/position will obviously depend on parent one.
My problem is to notify childs when parent one is resized.
But so far, the parent itself doesn't detect its own size change (whereas on the scene, everything behave as expected!)
In the parent item (= the resizable one) item I've tried to override
QVariant itemChange(QGraphicsItemChange, QVariant)
in order to dump change events. I can see all events, but itemChange method never get called when item is (being) resized.
Any help greatly appreciated.
NB:
In my resizable QGraphicsItem constructor, I've enabled the flag QGraphicsItem::ItemSendGeometryChange
ResizableGraphicsItem::ResizableGraphicsItem(QGraphicsItem *p_parent,
qreal p_initialWidth,
qreal p_initialHeight)
: QGraphicsItem(p_parent), _width(p_initialWidth),
_height(p_initialHeight), _resized(true)
{
setFlag(ItemSendsGeometryChanges);
...
}
The resize method looks like the following:
void ResizableGraphicsItem::setSize(qreal p_width, qreal p_height)
{
prepareGeometryChange();
if ((_width != p_width) ||
(_height != p_height))
{
_width = p_width;
_height = p_height;
_resized = true;
}
}
with:
QRectF ResizableGraphicsItem::boundingRect() const
{
return QRectF(0, 0, _width, _height);
}

How to create round shape buttons in Qt and set a round shape background image on it? How can we activate pixels of specific part of image in Qt

i am trying to add a round shape button in my project and i want to set round shape background image on it but the problem is that while setting any background image it is always taking the rectangular image.
You must use bitmap images with transparent background as buttons.
CustomButton::CustomButton(QString file,QString pressedfile,QWidget *parent,int id)
: QPushButton(parent),FileName(file),PressedName(pressedfile),ID(id)
{
connect(this,SIGNAL(clicked()),SLOT(slotClicked()));
setStyleSheet("border: 2px");
QPixmap pixmap(file) ;
setMinimumHeight(pixmap.height());
setMinimumWidth(pixmap.width());
setMaximumHeight(pixmap.height());
setMaximumWidth(pixmap.width());
}
void CustomButton::slotClicked()
{
emit clicked(ID);
}
void CustomButton::setColor(const QColor &c)
{
fontColor=c;
}
//Paint event of button
void CustomButton::paintEvent(QPaintEvent *paint)
{
QPainter p(this);
p.save();
p.setPen(Qt::blue);
QPixmap pixmapdown;
if(PressedName>0)
pixmapdown.load(PressedName);
else
pixmapdown.load(FileName);
QPixmap pixmap;
pixmap.load(FileName);
if(isDown())
p.drawPixmap(1,1,pixmapdown);
else
p.drawPixmap(1,1,pixmap);
if(text().length()>0)
{
p.setPen(fontColor);
p.drawText(rect(), Qt::AlignCenter|Qt::AlignHCenter, text());
}
p.restore();
p.end();}
You could also use a QStyle derived class, although this might be over the top if you really only want these round buttons and not tons of widgets with custom styling.

Resources