Clear Transparent Background for QWidget - c++

I have a widget as on overlay for another widget. The transparency works fine, as long as I don't clear the background of the overlay.
But I have to clear the widget to acutalize the displayed "effects". I tried to solve the inital problem (the background getting the default color) like described in 20848594, but except changing the color to black it had no effect...
Has anyone an idea why the widget which should be transparent does not display the underlaying widget(s)?
Here the code:
SudokuMarkerOverlayWidget::SudokuMarkerOverlayWidget(QWidget* parent, uint const fieldSize) : QWidget(parent)
{
// Translucent should be the correct one
setAttribute(Qt::WA_TranslucentBackground);
//setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_TransparentForMouseEvents);
...
}
void SudokuMarkerOverlayWidget::paintEvent(QPaintEvent*)
{
QPainter painter(this);
painter.setRenderHint( QPainter::Antialiasing );
// Tried this too, no difference
// painter.setCompositionMode(QPainter::CompositionMode_Source);
// painter.fillRect( this->rect(), Qt::transparent );
painter.setCompositionMode(QPainter::CompositionMode_Clear);
painter.eraseRect( this->rect() );
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
...
}
EDIT:
Just noticed, using CompositionMode Source instead of SourceOver for my semi-transparent painting (gradient seen in first image) also causes them to be a red-to-black-gradient instead of red-to-transparent.
That means every transparency except the inital by WA_TranslucentBackground or WA_NoSystemBackground isn't working.

Widgets in Qt can be either a 'native' or 'alien' type. In one case they're a separate operating system window. In some operating systems a transparent window isn't supported.
You might want to consider using QML if you're after fancy visual effects. That's what it was designed for.

Related

Gtkmm-3.0 and Cairomm, transparent window not working

I've been trying for the last hour to make this work.
The idea es Dock is a class whose base is Gtk::Window, and upon the signal_draw() being emited, the given context should be painted by CairoMM to be transparent.. Instead I see a black window.
Here goes the code:
Dock::Dock() : Gtk::Window()
{
set_decorated(false);
set_default_size(200,200);
set_app_paintable(true);
signal_draw().connect(sigc::mem_fun(*this,&Dock::dibujar));
}
bool Dock::dibujar(const Cairo::RefPtr<Cairo::Context>& contexto)
{
contexto->set_source_rgba(1.0,1.0,1.0,0.0);
contexto->set_operator(Cairo::OPERATOR_SOURCE);
contexto->paint();
return false;
}
Shouldn't it be enough to make the window transparent?
Your draw handler doesn't have access to the information about what else should be painted on the window, so your paint() call paints a transparent layer above what is, I guess by default, a black background.
Luckily there is a method to achieve what you want: Gtk::Widget::set_opacity()

Drawing with wxWidgets

I'm creating an application for capturing the screen or a part of it, and for that I need to select the part of the screen I want to capture.
The idea is to create a fullscreen semi-transparent window and draw thing on it so the user can see what he is doing. I have a working implementation where the selected area is dislayed as a wxPanel, but I want to rewrite it to paint everything to the main wxPanel manually.
frame = new wxFrame(NULL, -1, "", wxPoint(0,0), wxSize(0,0), wxSTAY_ON_TOP|wxFRAME_NO_TASKBAR|wxFRAME_SHAPED);
panel = new wxPanel(frame, -1);
SetTopWindow( frame );
panel->Bind(wxEVT_KEY_DOWN, &wxMiniApp::OnKeyDown, this);
panel->Bind(wxEVT_KEY_UP, &wxMiniApp::OnKeyUp, this);
panel->Bind(wxEVT_LEFT_DOWN, &wxMiniApp::OnMouseStart, this);
panel->Bind(wxEVT_LEFT_UP, &wxMiniApp::OnMouseEnd, this);
panel->Bind(wxEVT_MOTION, &wxMiniApp::OnMouseMove, this);
panel->Bind(wxEVT_PAINT, &wxMiniApp::OnPaintPanel, this);
panel->SetFocus();
panel->SetBackgroundColour(wxColor(0,0,0,100));
panel->SetBackgroundStyle(wxBG_STYLE_PAINT);
frame->SetBackgroundColour(wxColor(0,0,0,0));
frame->Show();
frame->ShowFullScreen(true);
I use panel to capture the mouse/keyboard events and I want to do the painting there too, but I don't know how to do this.
I want to have semi-transparent black background and the selected area should be transparent white or even fully transparent (without the black background).
The result of every attempt was that either it draw a solid color background or I got the famous WinXP lag effect.
Can you give me a basic OnPaintPanel(wxPaintEvent &event) implementation using x, y, with, height of the selected area (can be in wxPython too, if you're more comfortable with it) ?
You need to use SetTransparent(), wxDC doesn't support using alpha transparency anyhow (wxGraphicsContext does but it wouldn't help here).

Qt - avoid white background when resizing (set immediately a background color)

The question is in bold at the end so please read this as a whole.
I have a QAbstractScrollArea widget that I manually and completely render in the OnPaint() event.
In its constructor I set
setAttribute( Qt::WA_OpaquePaintEvent, true );
setAttribute( Qt::WA_NoSystemBackground, true );
setStyleSheet( "QWidget { background-color: rgb(0,0,77); }" );
and the paint event looks like this:
void MyArea::paintEvent (QPaintEvent *event) {
QPainter view(viewport());
view.fillRect(rect(), backgroundBrush);
renderedPixmap = heavyAndSlowRenderingOnAPixmap();
view.drawPixmap(viewRect, renderedPixmap, pixmapRect);
}
as you can see there's a "slow" function involved to render stuff into a pixmap.
The problem is: when I resize the window, I can see for a moment a white flickering in the area not yet redrawn
I know I can't avoid the white region until the viewport has been redrawn, but I'd like to draw that white region with the background color immediately.
So here's the question: can I display a background color immediately before the heavy-pixmap rendering?
I can't seem to find a way to achieve this.. it seems all graphics operations are buffered and then immediately bit-blitted to the screen together. I'm using Windows 8.1 x64 and Qt5. Any way to immediately draw the background color and then proceed with the rest of the rendering?
The best solution would be to move the expensive rendering out of the paintEvent(), potentially into another thread. You'll want to cache the rendered pixmap anyway. Update that pixmap when really needed and then call update() to trigger a repaint.

Qt: issue with QGraphicscene to show an imge

I am trying to develop very simple image viewer using QT. I am using the following code to show the image on QGraphicsScene widget:
QImage image(fileName);
firstPicture = new QGraphicsScene();
firstPicture->addPixmap(QPixmap::fromImage(image));
ui->graphicsView->setScene(firstPicture);
ui->graphicsView->fitInView(firstPicture->sceneRect() ,Qt::KeepAspectRatio);
I am getting the following output:
How can I fit the image into the GraphicsScene?
This approach works only when view showed your scene. In your case you did not call show(). Solution:
Use your approach when scene already shown.
You can reimplement showEvent and use your approach here.
You can scale image by yourself and set this scaled image to scene.
Also you can try to use: Qt::IgnoreAspectRatio instead of Qt::KeepAspectRatio.
You can make your custom class which inherits from QGraphicsView. You should reimplement resizeEvent( QResizeEvent *event ) in your custom QGraphicsView like:
void MyView::resizeEvent(QResizeEvent *event)
{
fitInView(firstPicture->sceneRect(), Qt::KeepAspectRatio);
QGraphicsView::resizeEvent(event);
}
This way the view will always display the whole scene. I.e. if the window size is changed and the graphicsView is resized, The scene gets scaled and you can see everything appropriately.

Drawing a scalable QIcon using QPainter

I want to design a new QIcon and want it to look like a fixed text with a rounded rectangle around it
.-----.
| Phy |
`-----ยด
The icon is supposed to scale without the "pixel-blocks" effect when painting on a QPainter that eventually has a scale transformation applied (for example when I paint into a widget that is part of a QGraphicsView with a scale applied on its scene).
Therefor, I have difficulties knowing how I should paint my QIcon. If I do it in the following way, I will paint a QPixmap that always has a fixed amount of pixels, thus introducing the pixel-blocks effect inevitably when the scale is large enough
void MyWidget::drawIcon(QPainter *painter, QPoint pos) {
QPixmap pixmap = icon.pixmap(QSize(22, 22),
isEnabled() ? QIcon::Normal
: QIcon::Disabled,
isChecked() ? QIcon::On
: QIcon::Off);
painter->drawPixmap(pos, pixmap);
}
What I am looking for is a way similar to how QFont with drawText works. Regardless on how large my scale is, when I draw fonts it always looks sharp and I cannot detect individual pixels.
I imagine that I could tell QPainter to paint my icon into a given pixel rectangle, and QPainter transforms the rectangle itself before letting my QIconEngine::paint render the item into a possibly larger rectangle or pixmap. But I see no way how I could do something like this.
Am I just being stupid and not seeing the obvious solution?
I was indeed completely dump. I can just use QIcon::paint and pass it the rectangle. It will correctly delegate the request to the icon engine.
I do this by creating my icons/images as SVG files, and using QSvgRenderer to paint them onto a QPainter. The required classes are in the SVG module.