Problem with QWidget borders in a QGridLayout - qt

I have a QGridLayout filled with my custom QWidgets (I'll call them CellWidgets). I want to display a grid between all of the CellWidgets so the columns and rows are clearly visible.
Obviously this isn't done from QGridLayout, as that is simply a holder for widgets that draw themseleves. I made my CellWidgets draw a border by over-riding the paintEvent function like so:
QPainter Painter(this);
Painter.setPen(QPen(QBrush(Qt::white), 2));
Painter.setBrush(Qt::black);
Painter.drawRect(0, 0, width(), height());
The QGridLayout spacing is set to 0, however, when it is drawn the grid border has a single width around the edges and double that width between cells, as the border of the cell is effectively being displayed twice.
Any clean way to solve/avoid this problem?

I think you are heading in the wrong direction.
Instead of painting your widget you should try to change the background color of parent widget to get the effect that you want.
Check out this link for an example.
I hope this helps.

Related

Qt how to set the shadow around the window

I need to show shadow around my mainWindow, and I cannot set my mainWindow WA_TranslucentBackground as I need to show video,any ideas to set the QMainWindow shadow without transparent?
You need to
Create top level QWidget
Make it translucent and frameless
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground);
Insert your MainWindow into created widget. Left some margins for shadow (about 5-15 px)
Add QGraphicsDropShadowEffect to MainWindow:
QGraphicsDropShadowEffect *wndShadow = new QGraphicsDropShadowEffect;
wndShadow->setBlurRadius(9.0);
wndShadow->setColor(QColor(0, 0, 0, 160));
wndShadow->setOffset(4.0);
mainWindow->setGraphicsEffect(wndShadow);
Look like:

Strange behavior of margins for Qt controls

I have just started using Qt (5.3) and encountered the fact that some controls appears with margins which I cannot control.
First, I tried to put QLabel and QPushButton right inside QMainWindow
window = new QMainWindow;
label = new QLabel( title, window );
In this case label appears with a margin of 12 pixels at the top (see picture).
QPushButton appears with 1 pixel top & left margins.
But if I insert QFrame with a border, it appears without any margin.
So the margins seem to be attributes of QLabel and QPushButton.
BUT:
When I tried to add extra QFrame between windows and controls:
window = new QMainWindow;
frame = new QFrame(window );
label = new QLabel( title, frame);
I had got different picture:
QLabels top margin had shortened to 1 pixel
QPushButton 1 pixel margins remained intact, but the height of the button had changed
I have tried:
setStyleSheet( "padding:0px" )
and
setContentsMargins( 0, 0, 0, 0 )
for all elements, but without any success.
Any help would be greatly appreciated
The QMainWindow class isn't designed to have widgets added to it directly. Whatever results you see are due to this fact.
The "margins" that you see are not really margins. Since a QLabel is a QFrame, you can enable its frame to see that it has no margin - merely the text is offset from the edge, and that's by design. You can similarly overlay a same-size translucent rectangle on a QPushButton to see that there is also no margin, merely the styling adds its own platform-specific margin. Do not mistake the platform styling mechanism for the style sheets: they are two separate mechanisms and mostly exclusive, with the use of the latter disabling the effects of the former, with few exceptions. For example, the stylesheet spacing/margins/padding is additive to whatever the platform style mandates.
See this answer for an example of how to show overlays on any widget without subclassing.

Drawing inside a QFrame: coordinate system

I would like to draw inside a Qt QFrame, however the QFrame will have a border. As far as I understand, the paintEvent receives a QPainter which is associated to the whole frameRect, so I will have to offset my paint operations of the border. Is this correct? Is there a way of getting a QPainter already associated to the inner part of the widget, without the (variable in size) border?
you have to consider the contentsRect contentsRect()-> Returns the area inside the widget's margins.using the return value rect of contensRect() you can restrict to draw anything inside the rect.
One way to do this would be to embed a QWidget inside the QFrame, place it in a simple QVBoxLayout layout or QStackedLayout layout with no margins and paint the QWidget instead. You'll probably get better performance if you simply offset your painting, though.

QT : Masking an image - Suggestions?

I dont know if I am using the correct term here. However this is what I am trying to achieve and I would like some suggestions on how I could achieve that. I want to have a circle with border visible. Now here is the hard part and something I dont even know how to start with. I want to manipulate the circle in such a way that the borders of the circle are visible and its center is not (i.e Pretty much that it has a hole in it and would show what ever is placed under it)I would then like to have another image placed under the circle such that only the part of the image that is under the transparent part of the circle is shown the parts outside the transparent boundary of the circle become invisible. Any suggestions on how I could achieve this. It seems that googling isnt helping me.
I would suggest the alternative way for unmasking a circular area of an image. You can specify the clip region - the area where you need to perform painting. For example:
[..]
QPainter painter(this);
// Sample circular area.
QRegion r(QRect(100, 100, 200, 200), QRegion::Ellipse);
painter.setClipRegion(r);
[..]
painter.drawImage(0, 0, image);
[..]
This will draw only those parts of your image that are inside of the circle with radius 200. All the rest pixels will be hidden.
You can handle mouse move event to move this "circle" over the image like a loupe.
UPDATE
Below is the sample code that generates an image with circular mask and insert it into the label:
QPixmap target(500, 500); // the size may vary
QPixmap source("image.png");
QPainter painter(&target);
QRegion r(QRect(100, 100, 200, 200), QRegion::Ellipse);
painter.setClipRegion(r);
painter.drawPixmap(0, 0, source);
QLabel l;
l.setPixmap(target);
l.show();
You might want to have a look at the Composition Example.
In short you could draw the first image and then use one of the Composition Modes to draw the second image on top (or the other way around). Make sure to convert the images to ARGB32 before using them.
To make the inner Part of the Circle transparent you can adjust the Alpha Channel accordingly.
Here is a small Example using Composition mode:
QPainter p(&imageCircle);
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
p.drawImage(image);
p.end()
Here you can find the Qt Documentation of QPainter.

Qt opacity color brush?

Particular in my case, I want to paint a line to a QGraphicsScene using adLine(). Befor that I have paint something on the scene and I want the last big line on the top of all of these but i still can see what I already paint.
In general, can I paint an Item and fill it with that kind of color which I can see what under the Item?
I have read some thing about BGMode here: http://doc.qt.io/qt-5/qt.html#BGMode-enum but I not sure how it work.
When you call addLine, you pass in a QPen. If you want that pen to draw with a semi-transparent color (so that things "beneath" still show), initialize that QPen with a color with an alpha-channel value below 255. (See QColor.)
QPen transRed(QColor(0xFF, 0, 0, 0x80));
scene.addLine(x1,y1, x2,y2, transRed);

Resources