Set background color only partially with stylesheets - qt

How can I set the background color for a part of the background like in the following image:
Of course, without border frames, I want to set only the cyan color.
I need to set the length of the left part (cyan) as the percentage of the widget length, e.g 30%.

With css I would hack qlineargradient a little bit. Note that edge of cyan may be a little blurry.
QFrame
{
background-color: qlineargradient(x1:0, x2: 1, stop: 0 cyan, stop: 0.29 cyan, stop: 0.2901 white, stop: 1 white);
}

If you want it hard-coded in the application, you can overload the paintEvent function in a widget. Something like this:
void MyWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
QPen pen(Qt::NoPen);
painter.setPen(pen);
painter.fillRect(0, 0, width(), height(), Qt::white);
painter.fillRect(0, 0, 0.3*width(), height(), Qt::cyan);
...
}

Related

How to change Qt ProgressBar color?

I would like to change color of my progress bar from default green to red. I have this code, but the view is "flat", I would like to achieve something like "3d effect" as on picture below:
Code for red PB:
QPalette pal = ui->pbExtractionWidget->palette();
pal.setColor(QPalette::Normal, QColor(Qt::red));
QString danger = "QProgressBar::chunk {background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0,stop: 0 #FF0350,stop: 0.4999 #FF0020,stop: 0.5 #FF0019,stop: 1 #FF0000 );border-bottom-right-radius: 5px;border-bottom-left-radius: 5px;border: .px solid black;}";
ui->pbExtractionWidget->setStyleSheet(danger);
This is how it looks:
This link provides a way to style the progressbar.
This link provides a way to change gradient color for widgets.
Essentially, you just need to change the stylesheet correctly. Each Chunk is a piece of the progressbar.
Or use QPalette which uses Base to color the background of a widget. Set its gradient correctly and then do the following.
palette.setBrush( QPalette::Base, gradientVariable);
ui->pbExtractionWidget->setPalette(palette);
// In main.cpp
qDebug() << QStyleFactory::keys();
// If keys contains e.g. 'Fusion' it would be possible to change color of QProgressBar.
// On windows default style is 'Windows' and color can only be change with style sheets.
auto style = QStyleFactory::create("Fusion");
if (style) {
app.setStyle(style);
}
class MyProgressBar final : public QProgressBar {
void paintEvent(QPaintEvent*) final {
QStyleOptionProgressBar option{};
initStyleOption(&option);
option.textAlignment = Qt::AlignHCenter;
option.palette.setColor(QPalette::Highlight, QColor("lightskyblue"));
option.palette.setColor(QPalette::HighlightedText, option.palette.color(QPalette::Text));
QPainter painter{this};
style()->drawControl(QStyle::CE_ProgressBar, &option, &painter, this);
}
};
You have to set the stylesheet correctly, use below stylesheet code
QString danger = "QProgressBar::chunk: horizontal {border-radius: 3px; background: QLinearGradient(X1:0, y1:0.966136, x2:0, y2:0, stop:0.609721 rgba(242, 53, 53, 255), stop:0.691923 rgba(240, 151, 141, 252));border: .px solid black;}";
ui->progressBar->setStyleSheet(danger);

Transparent Shader in QGLWidget leads to transparent background (see through)

I have a QGLWidget:
GlWidget::GlWidget(QWidget *parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
For antialiasing I resently implemented the Samplebuffer.
For some transparent meshes I used the GL_BLEND function:
void GlWidget::initializeGL()
{
...
glEnable(GL_MULTISAMPLE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
My widget also have a background painted in the painGL() function:
void GlWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
glColor4f(0.67,0.67,0.75,1);
glVertex2f(-1.0,-1.0);
glVertex2f(1.0,-1.0);
glColor4f(0.2,0.2,0.2,1);
glVertex2f(1.0, 1.0);
glVertex2f(-1.0, 1.0);
glEnd();
// other object drawing stuff
...
}
The problem I have is the windows get transparent where the transparent meshes are rendered.
I want the BLEND to be applied to the colored background I drew.
I tried to clear the widget with none transparent white before drawing things but this did not help.
See this picture for more explanation: http://i.stack.imgur.com/AZx3f.png
The problem did not appear before I implemented the SampleBuffers.
I searched for hours and the simple solution is:
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

Make a pixmap transparent for a QLabel

I have a MainWindow with a QLabel and a pixmap. I want to make it transparent (or less opaque)
I am using the following code below.
ui->label->setAttribute(Qt::WA_TranslucentBackground);
ui->label->repaint();
However it does not seem to work. The image looks the same without any changes. I also tried to use to the following statement:
ui->label->setStyleSheet("background-color: rgba(255, 255, 255, 10);");
Unfortunately, this does not seem to work either.
Anyone knows how can I make an image transparent or make it less opaque?
Thank you for your time.
If your image isn't transparent as it is and you want it to be, you can do something like this:
QLabel *l = new QLabel(this);
QImage image(":/img/myimage.png");
QPainter p;
p.begin(&image);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.fillRect(image.rect(), QColor(0, 0, 0, 50));
p.end();
l->setPixmap(QPixmap::fromImage(image));
You can apply QGraphicsOpacityEffect to a label to adjust it's opacity.
You can use method fill, example:
pixmap = QPixmap(width_size_in_pixels, height_size_in_pixels)
pixmap.fill(Qt.transparent)

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);
}
};

Wrong alpha blending when rendering on a QGLFramebufferObject

I write an OpenGL based vector graphics renderer for my application. It needs to render to a framebuffer object rather to the screen directly. Since I write the application in Qt, I use a QGLFramebufferObject which is a wrapper class for a OpenGL framebuffer object.
I created a minimal example which shows a wrong result I also get when rendering more complex stuff (for example using a fragment shader which sets colors with a non-one alpha value). I just render a red circle and a half-transparent green one on a black cleared screen, and then the same on the FBO:
void MainWidget::initializeGL()
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0, 0, 0, 0);
}
void MainWidget::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
}
void MainWidget::paintGL()
{
// DRAW ON THE SCREEN
{
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(100);
glEnable(GL_POINT_SMOOTH);
glBegin(GL_POINTS);
glColor4f(1, 0, 0, 1);
glVertex2f(-.2, 0);
glColor4f(0, 1, 0, .5);
glVertex2f( .2, 0);
glEnd();
}
QGLFramebufferObject fbo(width(), height());
fbo.bind();
// DRAW ON THE FBO USING THE SAME CODE AND THE SAME CONTEXT
{
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(100);
glEnable(GL_POINT_SMOOTH);
glBegin(GL_POINTS);
glColor4f(1, 0, 0, 1);
glVertex2f(-.2, 0);
glColor4f(0, 1, 0, .5);
glVertex2f( .2, 0);
glEnd();
}
fbo.release();
fbo.toImage().save("debug.png");
}
The result looks like this on the screen (scaled 400%):
The rendering to the QGLFramebufferObject looks like this (also scaled 400%):
Note that this image is not fully opaque, so here it is the same image with a checkerboard added behind it:
Even the area in which the two circles overlap isn't fully opaque. And the anti-aliasing looks pretty ugly.
How does this happen? And how can I fix this?
I already tried:
Different blend functions.
Explicitly disabling the depth buffer, stencil buffer and sampling on the QGLFramebufferObject. I'm not sure if the QGLFramebufferObject default format adds something I don't want.
Try the following:
QGLFramebufferObjectFormat fmt;
fmt.setSamples(1); // or 4 or disable this line
fmt.setInternalTextureFormat(GL_RGBA8);
QGLFramebufferObject fbo(width(), height(), fmt);
This forces a specific pixel format and also disables rendering to a texture by using multisampling (otherwise QT always renders to a texture). That might produce different results. You can also experiment with the format.
Also, what is your hardware? My maximal point size is only 64 pixels (GTX 260), you are trying to render 100 pixel points. That might be an issue. Are any OpenGL errors generated? Does the same happen on small points?
You might also try hinting (if it's possible in QT):
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
But i wouldn't expect this to change anything.

Resources