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);
Related
Currently I am writing a small application with Qt and OpenGl and I choosed QOpenGLWidget for rendering graphics.
That's how I declared my widget:
class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions{
// Methods, slots, e.t.c
}
And that's the constructor:
GLWidget::GLWidget(QWidget *parent) : QOpenGLWidget(parent)
{
/* Tried this, it didn't help.
QSurfaceFormat format;
format.setDepthBufferSize(24);
this->setFormat(format);
*/
}
In my init function I set GL_CULL_FACE and GL_DEPTH_TEST:
void GLWidget::initializeGL()
{
/* Some initialization stuff regarding the scene */
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
And I really don't know why the widget renders the black screen.
Here are some pictures.
First one: with disabled GL_CULL_FACE and disabled GL_DEPTH_TEST.
Second one: with enabled GL_CULL_FACE and disabled GL_DEPTH_TEST. Maybe it's not a good picture, but I can assure you, you can see some surfaces through the other.
Third one: with enabled GL_CULL_FACE and enabled GL_DEPTH_TEST. Actually, it doesn't matter if GL_CULL_FACE is enabled. Anyway it renders the black screen.
And here's the image without any shading just to show you that the model is fine.
I tried to set the format manually, but it didn't help. Still the black screen:
QSurfaceFormat format;
format.setDepthBufferSize(24);
this->setFormat(format);
Oh and yes, I set glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); at the beginning of my paintGL() function.
When I create a QPainter object in paintGL() function the rendered scene does not shown. Here is my code:
void D3Display::paintGL(){
makeCurrent();
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
// some adjustment stuff here...
glPushMatrix();
// some rendering stuff here...
glPopMatrix();
QPainter painter(this);
// some overpainting stuff here...
}
Now the problem is: when I create the QPainter object, screen suddenly turns into black and does not show anything (including render and overpaint stuff). As you can see, I want to overpaint something on a QGLWidget , I am trying some stuff but I couldn't work it out. This function has been written similarly with the QT Overlay example project.
I'm trying to create a chroma key for a qwebview in Qt5. This means I need to make a specific color be transparent (other widgets should be visible through webview's pixels with that color). I've found that it can be done using QPainter::CompositionMode operations, but can't make it work.
For example, I need to make all black pixels of a webview be transparent (the source color should be changed in runtime).
I've reimplemented QWebView::paintEvent in my class (get a part of a code from Qt sources), but don't know what to do next
WebView::paintEvent(QPaintEvent *event) {
if (!page()) return;
QWebFrame *frame = page()->mainFrame();
QPainter painter(this);
painter.setRenderHints(renderHints());
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
frame->render(&painter, event->region());
}
I found a way how to make any source color be white with the following code:
QWebFrame *frame = page()->mainFrame();
QImage source_image(size(), QImage::Format_ARGB32_Premultiplied);
QImage result_image(size(), QImage::Format_ARGB32_Premultiplied);
QPainter imagePainter(&source_image);
imagePainter.setRenderHints(renderHints());
frame->render(&imagePainter, event->region());
imagePainter.end();
QImage mask = source_image.createMaskFromColor(qRgb(0x00,0x00,0x00)); // Source color
QPainter resultPainter(&result_image);
resultPainter.drawImage(source_image.rect(), source_image);
resultPainter.setCompositionMode(QPainter::CompositionMode_Screen);
resultPainter.drawImage(source_image.rect(), mask);
QPainter painter(this);
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
painter.drawImage(0, 0, result_image);
But I don't know how to convert a white color to transparent.
I found a solution, but it consumes a lot of CPU.
First it's required to set
setStyleSheet("QWebView { background: transparent }");
setAttribute(Qt::WA_OpaquePaintEvent, true);
somewhere in WebView's constructor (I just forgot to mention that in the first message). Then reimplement paintEvent:
void WebView::paintEvent(QPaintEvent *event)
{
if (!page())
return;
QWebFrame *frame = page()->mainFrame();
QPainter painter(this);
QColor chroma_color(0, 0, 0); // A color that should be transparent
float opacity_level = 0.9; // WebView opacity
m_render_pixmap.fill(Qt::transparent);
QPainter pixmapPainter(&m_render_pixmap);
pixmapPainter.setRenderHints(renderHints());
frame->render(&pixmapPainter, event->region());
pixmapPainter.end();
m_render_pixmap.setMask(m_render_pixmap.createMaskFromColor(
chroma_color, Qt::MaskInColor));
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
painter.setOpacity(opacity_level);
painter.drawPixmap(QPoint(event->rect().left(), event->rect().top()), m_render_pixmap, event->rect());
painter.end();
}
m_render_pixmap is an instance of QPixmap. I don't want to recreate it every time paintEvent is called. I just recreate it on resizeEvent
void WebView::resizeEvent(QResizeEvent *event)
{
QWebView::resizeEvent(event);
m_render_pixmap = QPixmap(size());
}
The code above work great but in my case I want to render a video widget below a webview. So WebView::paintEvent calls about 25 times per second and each call takes about 20-25 ms in windowed mode on my PC. And it takes about 100% of one of CPU cores in a fullscreen mode.
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);
...
}
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.