Qt adding drop shadow effect for QLabel using QGraphicsDropShadow - c++

I have to apply drop shadow for multiple QLabel in my Application. I used QGraphicsDropShadowEffect and it is working fine, if i am adding it for one QLabel. I tried applying the same Graphics effect for two QLabels.
QGraphicsDropShadowEffect* effect = new QGraphicsDropShadowEffect();
effect->setColor(Qt::white);
effect->setBlurRadius(0);
effect->setXOffset(1);
effect->setYOffset(0);
QLabel* label = new QLabel();
label->setText("QLabel1");
label->setGraphicsEffect(effect);
QLabel* label2 = new QLabel();
label2->setText("QLabel2");
label2->setGraphicsEffect(effect);
In this case,the shadow effect is applied only to label2.
I tried creating two different QGraphicsDropShadowEffect objects and setting the QLabels with that.
QGraphicsDropShadowEffect* effect = new QGraphicsDropShadowEffect();
effect->setColor(Qt::white);
QLabel* label = new QLabel();
label->setText("QLabel1");
label->setGraphicsEffect(effect);
QGraphicsDropShadowEffect* effect1 = new QGraphicsDropShadowEffect();
effect1->setColor(Qt::white);
QLabel* label2 = new QLabel();
label2->setText("QLabel2");
label2->setGraphicsEffect(effect1);
In this case, Application is crashing in QRasterPaintEngine::transformChanged() call.
Any idea on how to fix this issue?
I am using qt 5.3.

Was just trying to solve this myself. As much as this solution pains me it's the best I came up with quickly. Use QList to help yourself out here:
// List instances containing labels and drop shadows
QList<QLabel*> label_list_;
QList<QGraphicsDropShadowEffect*> shadow_list_;
// Get all UI labels and apply shadows
label_list_ = this->findChildren<QLabel*>();
foreach(QLabel *lbl, label_list_) {
shadow_list_.append(new QGraphicsDropShadowEffect);
shadow_list_.back()->setBlurRadius(10);
shadow_list_.back()->setOffset(3, 3);
lbl->setGraphicsEffect(shadow_list_.back());
}
If don't want all UI labels in your list you can add manually with append

Related

Why does scene not being displayed when widget is set as central

I have a problem displaying two labels, the label "label" is displayed with no problem ( it has some buttons adjusted Horizontally ) and the second label "label1" is not being displayed ( it contains a scene which has a view , in the scene i have a title and a picture ). This is the code i am trying to use.
widget1 = new QWidget;
setCentralWidget(widget1);
label1 = new QLabel(widget1);
scene = new QGraphicsScene(label1);
vue = new QGraphicsView(scene);
label1->move(100,100);
label = new QLabel(widget1);
layout = new QHBoxLayout(label);
label->resize(500,100);
It's my first time using QGraphicsScene/View and it is confusing me a little bit.
Thanks for the answers
You're definitly not using all those widgets the right way.
you don't need a label to display a QGraphcisView, neither the QGraphicsScene to be the child of the label.
If you want to display, let's say, a label and a view in the center widget you could write this :
//==== Central widget part
QWidget* widget = new QWidget(this);
setCentralWidget(widget);
//==== Graphics part
QGraphicsScene* scene = new QGraphcisScene(this);
QGraphicsView* view = new QGraphicsView(widget);
view->setScene(scene);
//==== Label part
QLabel* label = new QLabel(widget);
//==== Layout part
QHBoxLayout* layout = new QHBoxLayout(widget);
layout.addWidget(label);
layout.addWidget(view);
widget.setLatout(layout);
This should show a label and a graphics view in row.
If you allow me a piece of advice : you should understand the parenting system before trying to use the QGraphics module. It's one of the cornerstones of Qt and that what you did wrong here. Starts here for the parenting system : https://doc.qt.io/qt-5/objecttrees.html
and here for the graphics : https://doc.qt.io/qt-5/graphicsview.html
Hope that helps you.

How to create custom layout for widget

I'm trying to create a custom widget in QT that looks something like this:
The red squares will be displaying an image/icon.
How can I achieve this layout through coding the widget? I will need to create many of those widgets with the same layout but different values in their labels. Ideally, I will display those widgets as a list with a scrollbar in my mainwindow. But right now I'm struggling to just create the layout for those widgets through code. Any help is much appreciated.
You need to split you design on to separate segments. Each segment can be either a separate sub layout or a widget. In you example, I see the following segments:
Large red icon,
Two labels: TextLabel and 06-November-2014...
Two labels make a vertical box layout,
Vertical box layout and large red icon make a horizontal box layout,
Small red rectangle makes a separate layout,
All layouts make a main layout.
Now lets code this composition:
QLabel *largeRed = new QLabel(this); // Should set an image for this label
QLabel *lbl1 = new QLabel("06-November-2014...", this);
QLabel *lbl2 = new QLabel("TextLabel", this);
QVBoxLayout *vLayout = new QVBoxLayout;
vLayout->addWidget(lbl1);
vLayout->addWidget(lbl2);
vLayout->addStretch();
QHBoxLayout *hLayout = new QHBoxLayout;
hLayout->addWidget(largeRed);
hLayout->addLayout(vLayout);
QLabel *smallRed = new QLabel(this); // Should set an image for this label
QHBoxLayout *hLayout2 = new QHBoxLayout;
hLayout2->addWidget(smallRed, 0, Qt::AlignRight);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addLayout(hLayout);
mainLayout->addLayout(hLayout2);
[..]
Use this.
QPixmap big(75,65);
big.fill(Qt::red);
QPixmap small(25,15);
QVBoxLayout *box = new QVBoxLayout;
QWidget *window = new QWidget;
QLabel *bigLab = new QLabel;
QLabel *smallLab = new QLabel;
QLabel *textLab = new QLabel("Two");
bigLab->setPixmap(big);
smallLab->setPixmap(small);
QHBoxLayout *hLay = new QHBoxLayout;
hLay->addWidget(bigLab);
hLay->addWidget(textLab);
QHBoxLayout *vLay = new QHBoxLayout;
vLay->addWidget(smallLab,0,Qt::AlignRight);
box->addLayout(hLay);
box->addLayout(vLay);
window->setLayout(box);
window->show();
Result:
What I normally do is:
Design the layout with Qt Designer/Creator using rich features of layouting.
Set its instances (from code) as the item widget of a list or table widget.
Be careful, If the item count of the list is too large, it will perform very slowly.
P.S. If you really need the layout coded, just use the code generated by Qt designer.

Qt: How to add two widgets (say QPushButton) to the status bar, one to the left and other to the right side?

I would like to add two widgets (say QPushButton) to the status bar, one to the left and other to the right side.
I am thinking of adding horizontal spacer in between the two widgets, but don't know how to add.
PS: I tried using addWidget() to add to the left and addPermanentWidget() to add to the right but it doesn't look neat and also it doesn't feel right.
You can add two buttons to a layout in a widget and add the widget to the status bar using QStatusBar::addWidget :
QWidget * widget = new QWidget();
QPushButton * leftBut = new QPushButton("Left");
QPushButton * rightBut = new QPushButton("Right");
QGridLayout * layout = new QGridLayout(widget);
layout->addWidget(leftBut,0,0,1,1,Qt::AlignVCenter | Qt::AlignLeft);
layout->addWidget(rightBut,0,1,1,1,Qt::AlignVCenter | Qt::AlignRight);
ui->statusBar->addWidget(widget,1);
I am thinking of adding horizontal spacer in between the two widgets, but don't know how to add.
Here is a way to use a "fake" spacer.
QPushButton *leftButton = new QPushButton("Left");
QPushButton *rightButton = new QPushButton("Right");
QLabel *spacer = new QLabel(); // fake spacer
ui->statusBar->addPermanentWidget(leftButton);
ui->statusBar->addPermanentWidget(spacer, 1);
ui->statusBar->addPermanentWidget(rightButton);
The second parameter in addPermanentWidget is "used to compute a suitable size for the given widget as the status bar grows and shrinks".
Demo:
I think the simplest way is using a QGridLayout (honestly I never tried to modify a status bar anyway) supposing that the status bar is or descends from widget you can do this:
QGridLayout *myGridLayout = new QGridLayout();
statusbar->setLayout(myGridLayout)
QPushButton *button1 = new QPushButton(this);
myGridLayout->addWidget(button1,0,0,1,1);
QPushButton *button2 = new QPushButton(this);
myGridLayout->addWidget(button2,X,0,1,1);
The biggest is X the more space you want to leave in between, I would suggest to start with 3 and then make few tests to see how it looks.

drop shadow effect on QPushButton text

How do I set a drop-shadow effect on a QPushButton text?
I could set shadow on the entire QPushButton using QGraphicsDropShadowEffect, I however, am not able to find a way to directly set the effect of text inside the QButton.
Edit:
I tried the following, not sure if the syntax is correct
in the .qss file:
MyButton::text
{
shadow: palette(dark);
}
I set the button's drop shadow effect by:
QGraphicsDropShadowEffect* effect = new QGraphicsDropShadowEffect( );
effect->setBlurRadius( 5 );
mStartButton->setGraphicsEffect( effect );
Try this:
Set a QLabel iside QPushButton rather than simple text. Then apply shadow effect to the label.
You may need to add extra code for centering the label inside the pushbutton.
mStartButton->setText("");
QLabel *label = new QLabel(mStartButton);
label->setText("<b>Button</b>");
QGraphicsDropShadowEffect* effect = new QGraphicsDropShadowEffect( );
effect->setBlurRadius( 5 );
label ->setGraphicsEffect( effect );

Setting the form lines like iTunes info dialog on Mac with Qt

I'm just a beginner and I wonder if it would be possible to create a form widget on Mac like the info dialog in iTunes.
I tried using:
QGroupBox: I cannot find a way to get rid of the frames.
Creating my own widget: I cannot find a way to fix the spacing between the label and the QLineEdit widget using the QVBoxLayout (actually I'm not sure I understand well the differences between margin/spacing).
QFormLayout: I cannot find a way to reduce the size of the QLabel after using setrowWrapPolicy::WrapAllRows
Also I am not (yet) very comfortable with QtDesigner, so i'd like to avoir using it (for now)
Thanks in advance
Edit: Some precisions on the programs. I use QtCreator 2.6.1 with Qt 4.8.1 and 5.0 on Mac OS X Mountain Lion.
Edit 2: Here is the code.
Subclass of QWidget:
MCLineEdit::MCLineEdit(const QString &header)
{
m_lineEdit = new QLineEdit;
m_lineTitle = new QLabel(header);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(m_lineTitle);
layout->addWidget(m_lineEdit);
layout->setSpacing(0);
setLayout(layout);
}
To display the widget
myView::myView(QWidget *parent) :
QWidget(parent)
{
setFixedSize(600, 500);
MCLineEdit *lineEdit1 = new MCLineEdit("Test 1");
MCLineEdit *lineEdit2 = new MCLineEdit("Test 2");
MCLineEdit *lineEdit3 = new MCLineEdit("Test 3");
MCLineEdit *lineEdit4 = new MCLineEdit("Test 4");
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(lineEdit1);
mainLayout->addWidget(lineEdit2);
mainLayout->addWidget(lineEdit3);
mainLayout->addWidget(lineEdit4);
mainLayout->setSpacing(0);
setLayout(mainLayout);
}
This can be accomplished a ton of ways I am sure. Qt gives you all the possible layouts you could need to achieve this. You could do it with a QGridLayout, and add widgets with different amounts of "cell" spanning, and control the row and column sizes to suit. Or you can just do it with a bunch of nested vertical/horizontal layouts.
For example, you can group a label and a field together in a QVBoxLayout, by adding the widgets with a left alignment, and then setting the spacing to 0 between the items:
layout->setSpacing(0);
layout->addWidget(aLabel, Qt::AlignLeft);
layout->addWidget(aLineEdit, Qt::AlignLeft);
mainVerticalLayout->addLayout(layout);
For something like the track numbers, it is just more nested layouts:
vLayout->addWidget(aLabel);
hLayout->addWidget(aCheckbox);
hLayout->addWidget(aLabel);
hLayout->addWidget(aCheckbox);
vLayout.addLayout(hLayout);
And regarding your bullet points:
QGroupBox lets you remove the frame with setFlat(bool)
With layouts, the margin is the padding around the outside of the contained widgets. What you want is setSpacing(int) to control the amount of space between the items in the layout.
QFormLayout is probably not your best choice here. That is usually for having labels on one side and widgets on the other. Basically it is a 2 column layout. A QGridLayout would be more appropriate. And to reduce the size of the QLabel, you can give it a max or a fix size. Such as using setFixedWidth() or setMaximumWidth() on the label.
So I finally managed to get the expected result after playing a bit with QtCreator.
Here is the code for who might be interested:
myLineEdit:myLineEdit(const QString &header)
{
m_lineEdit = new QLineEdit;
m_groupBox = new QGroupBox;
QFont groupFont;
groupFont.setPixelSize(10);
groupFont.setBold(true);
m_groupBox->setTitle(header);
m_groupBox->setFlat(true);
m_groupBox->setFont(groupFont);
m_groupBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
QFont lineFont;
lineFont.setPixelSize(13);
lineFont.setBold(false);
m_lineEdit->setFont(lineFont);
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(m_lineEdit);
layout->setContentsMargins(0, 10, 0, 0);
layout->setSpacing(10);
layout->setSizeConstraint(QLayout::SetMinAndMaxSize);
m_groupBox->setLayout(layout);
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addWidget(m_groupBox);
setLayout(mainLayout);
}
One comment though: will only work on Qt 5 since on 4.8 the setFlat() method will display a separating line between the header and the QLineEdit.
Thanks to jdi for his help!