Is there a way to make the docks in imgui transparent? - imgui

When an imgui window is floating, I can make it transparent with ImGuiWindowFlags_NoBackground and render a translucent texture before the interface.
However when the window is docked, It shows a dark background which I do not want or need.
By window I do not mean the OS window. I mean the dockable child windows that imgui creates inside the OS window
How do I turn off the background for all the docks?

The following code can be used to change the color of the imgui background, it takes a vec4 meaning (R, G, B, A).
You want to change the A channel. 0.5
auto& style = ImGui::GetStyle();
ImVec4* colors = style.Colors;
// \/
const ImVec4 bgColor = ImVec4(0.1, 0.1, 0.1, 0.5);
colors[ImGuiCol_WindowBg] = bgColor;
colors[ImGuiCol_ChildBg] = bgColor;
colors[ImGuiCol_TitleBg] = bgColor;
You can use the following function if you just want to change the next imgui window and not all of them.
ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background

Related

Drawing a highlighting border around a region of the screen in Qt5 on Windows 10

I'm writing a desktop application on Windows 10 that does something similar to "share your screen/app window", and I've got the classic problem of trying to highlight the region of interest on the screen. So I need to draw a bright and thick rectangle, have the rectangle always be visible and 'on top', and have no interference with user input, mouse movement, etc. (i.e. all pass-through).
I can't make it work properly with Qt v5.7. I either get an opaque window (I can't see what's "below" it) with the right border, or a transparent window with only a black 1-pixel border.
I vaguely know that if I were to use Windows-specific APIs, I could create a window with WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOACTIVE style etc.
(using something like a "chrome window" - example in C# here), but besides the fact that I haven't tried yet (and need to do in C++ and not C#), I'd rather do it with Qt is possible.
Case A I'm still a novice with Qt, but I thought that using a QFrame was the way to go, so I wrote some code:
//
// A- Displays a completely transparent rectangle with a black 1-pixel border.
//
QFrame *frame = new QFrame();
frame->setFrameStyle(QFrame::Box | QFrame::Plain);
frame->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowTransparentForInput | Qt::WindowDoesNotAcceptFocus | Qt::WindowStaysOnTopHint);
frame->setAttribute(Qt::WA_TranslucentBackground, true);
frame->setGeometry(1000,500,600,300); // Just some fixed values to test
frame->show();
That gives me this, a rectangle with a black 1-pixel thick border:
It's great, in that the rectangle stays on top of everything else, is transparent, pass-through for mouse input etc., cannot get focus, be resized or moved, and doesn't show up on the task bar.
Case B I thought the only problem left was to draw a thick bright border, so I coded this just before the call to frame->show():
// Set a solid green thick border.
frame->setObjectName("testframe");
frame->setStyleSheet("#testframe {border: 5px solid green;}");
.. but that gave me exactly, er, nothing. The QFrame was not showing at all!
Case C So as a test, I removed the setting of Qt::WA_TranslucentBackground. Here's the code:
//
// C- Displays an opaque pass-through window with a green 5-pixel border.
//
QFrame *frame = new QFrame();
frame->setFrameStyle(QFrame::Box | QFrame::Plain);
frame->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowTransparentForInput | Qt::WindowDoesNotAcceptFocus | Qt::WindowStaysOnTopHint);
// Disabled Qt::WA_TranslucentBackground
//frame->setAttribute(Qt::WA_TranslucentBackground, true);
frame->setGeometry(1000,500,600,300); // Just some fixed values to test
// Set a solid green thick border.
frame->setObjectName("testframe");
frame->setStyleSheet("#testframe {border: 5px solid green;}");
frame->show();
That window is still completely pass-through, stay-on-top, etc. and has the right border, but of course it's opaque.
Now, the fact that:
with Qt::WA_TranslucentBackground set and without changing the style sheet, I get a black 1-pixel border/frame;
with Qt::WA_TranslucentBackground set and with changing the style sheet, I don't get a border/frame at all (the window becomes invisible);
without Qt::WA_TranslucentBackground set and with changing the style sheet, I get the expected border/frame;
.. seems to imply that there's some style set for getting the black 1-pixel outside border when the window is transparent. When I changed the border style myself, this stays fully inside the window frame, and thus disappears when the window is transparent (case B) - I think.
Does anybody know what the right style sheet settings should be so that I get the window fully transparent with its 5-pixel green border?
Also, I couldn't find any documentation that tells me exactly what styles could apply to what type of widget/window (and QFrame in particular, for my test case). Does that exist anywhere? It would be handy to know, as I'd also like to use gradient colours for the border, and possibly other effects.
Try replacing the QFrame in your code with something like...
class rubber_band: public QRubberBand {
using super = QRubberBand;
public:
template<typename... Types>
explicit rubber_band (const Types &... args)
: super(args...)
{
setAttribute(Qt::WA_TranslucentBackground, true);
}
protected:
virtual void paintEvent (QPaintEvent *event) override
{
QPainter painter(this);
QPen pen(Qt::green);
pen.setWidth(10);
painter.setPen(pen);
painter.drawLine(rect().topLeft(), rect().topRight());
painter.drawLine(rect().topRight(), rect().bottomRight());
painter.drawLine(rect().bottomRight(), rect().bottomLeft());
painter.drawLine(rect().bottomLeft(), rect().topLeft());
}
};
An instance of the above rubber_band class should display as a green border with completely transparent body. Use as...
rubber_band *frame = new rubber_band(QRubberBand::Rectangle);
frame->setGeometry(1000, 500, 600, 300);
frame->show();
(Note: On platforms using X11 the above will require that a composite manager such as xcompmgr be running. That's usually not an issue.)
I found a solution, which is to:
set a mask on the QFrame to exclude the inside of the frame - so that becomes completely transparent.
not set Qt::WA_TranslucentBackground (otherwise nothing is visible, as per case B in the question).
I've also set the opacity to 0.5 so that the border that gets rendered is partly transparent.
The final code is:
//
// D- Displays a completely transparent pass-through window with a green 5-pixel translucent border.
//
QFrame *frame = new QFrame();
frame->setFrameStyle(QFrame::Box | QFrame::Plain);
frame->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowTransparentForInput | Qt::WindowDoesNotAcceptFocus | Qt::WindowStaysOnTopHint);
frame->setGeometry(1000,500,600,300); // Just some fixed values to test
// Set a solid green thick border.
frame->setObjectName("testframe");
frame->setStyleSheet("#testframe {border: 5px solid green;}");
// IMPORTANT: A QRegion's coordinates are relative to the widget it's used in. This is not documented.
QRegion wholeFrameRegion(0,0,600,300);
QRegion innerFrameRegion = wholeFrameRegion.subtracted(QRegion(5,5,590,290));
frame->setMask(innerFrameRegion);
frame->setWindowOpacity(0.5);
frame->show();
What we end up with is this:
I worried somewhat that all this masking would lead to a not very optimal solution, but I realised afterwards that the C# example using Windows APIs actually does something very similar (a rectangle within a rectangle to exclude the region to stay transparent).. so maybe this is the right way to go.

Set dialog window's border color

The root question here is this: How do I set the color for the border around a window (more specifically, a dialog window)?
I have a dialog window which pops up with an alert. Due to the critical safety nature of the alert, there is a requirement that some parts of the window be red, including the dialog's window-border. When I got this requirement in, I thought it was a good idea. Seems reasonable and simple enough.
The application uses X/motif for its graphics. I started by making other requested parts red, such as the acknowledgement button. Getting everything else done was simple enough by changing graphics contexts and color resources.
The dialog's border, however, has been a pain. There is an XmNborderColor resource, so I tried changing that. It didn't seem to work. Eventually, after trying to set it for different widgets (frame and it's ancestors), I did the following out of desparation:
Widget w = button;
for(int i = 0; i <= 20; i += 1)
{
printf("i = %d, w = %d\n", i, w);
if(w <= 0) break;
XtVaSetValues( w, XmNborderColor, border, NULL);
w = XtParent(w);
}
I did that to just set it on everything from the button to the root and everything between.
After doing some more research, I realized that I might need to be changing the window attributes instead, such as via XChangeWindowAttributes(display, window, mask, values). The structure for the values includes a border_pixel, which I'm assuming is the border color but can't find confirmation on that - documentation just says it's for setting "the border pixel." Fortunately, there is a convenience function for setting just the border pixel so that you do not need to pass an entire values structure; the convenience function that changes only the border pixel is XSetWindowBorder(display, window, border_pixel).
So I wanted to try that. I now have:
// control_area is the widget containing the other
XSetWindowBorder(XtDisplay(shell), window, border);
shell is set elsewhere with the following function:
Widget myClass :: createShell( Widget parent, string title )
{
while( !XtIsApplicationShell(parent) )
{
parent = XtParent( parent );
}
shell = XtVaCreatePopupShell( name, xmDialogShellWidgetClass, parent,
XtNvisual, visual, // visual, colormap, depth are class member variables
XtNcolormap, colormap,
XtNdepth, depth,
NULL );
XtVaSetValues( shell,
XmNmwmDecorations, MWM_DECOR_BORDER,
XtNtitle, const_cast<char*> (title.c_str()),
XmNmwmFunctions, NO_FUNCTIONS,
XmNresizePolicy, XmRESIZE_NONE,
NULL );
return shell;
}
From another place in the code, it looks like window might be a reference to the root window - maybe that's the problem?
I am surprised by the lack of information about this and by how difficult it has been to find a direct answer.
How do I set the border color? If I should be using XSetWindowBorder(), what am I doing wrong? If it's because my window variable might not be referencing the correct window, how do I get the a reference to the correct window knowing the shell and contained widgets (maybe I should make a separate question out of this one if this question doesn't get traction)?
The colour of the border is most likely controlled by your window manager unless you are running without a window manager. You need to override the default colour for that specific window in your ~/.Xdefaults file. Something like:
[title]*bordercolor: red
Where [title] is the same as the string you pass to createShell().

Get QPushButton Pressed Background Color

How can I get the pressed background color of a QPushButton?
if (isDown())
_BGColor = <pressed background color>; // how to get this???
else
_BGColor = palette().color(QPalette::Background); // this is to get the idle backcolor
Thanks in advance!!!
It's very difficult (if not impossible) to find a way to get the backgound color of a button when it's pressed, because it depends on the style, and it's not guaranteed that the style respects the palette.
However I suggest two different approaches:
You can set you own background color using style sheets (simpler) or implement the painting of the button yourself, using styles or reimplementing paintEvent(). See Customizing QPushButton
To paint over the button with the inverse color, you can set a composition mode to the painter in order to get the inverse color.
For example:
painter.setPen(QColor(255, 255, 255));
painter.setCompositionMode(QPainter::RasterOp_SourceAndNotDestination);
(note that using this example, the inverse color of middle grey (128, 128, 128) is exactly the same color)
See QPainter::CompositionMode

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).

Clear Transparent Background for QWidget

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.