im using QQmlApplicationEngine with QQuickWindow for an application and i can't
transparent main window. i want to set a splash before application pops up and i use Window component for it and it should be transparent but it's not, my main.cpp is
int main(int argc, char *argv[])
{
Application app(argc, argv);
QShookaClient shooka_client;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("shooka", &shooka_client);
engine.load(QUrl("qrc:///shooka/shooka.qml"));
QObject *topLevel = engine.rootObjects().value(0);
QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
window->show();
window->setFlags(Qt::FramelessWindowHint);
window->setColor(Qt::transparent);
return app.exec();
}
but setColor doesn't work in win7. i know there is way for QDeclarativeView or even i found solution for QQuickview and it kinda should work for QQuickWindow but no, can anyone help me please..
One has to realize that a Window QtQuick type maps to QQuickWindow C++ class, and derives from QWindow. The window flags, per Cameron's answer, can be set. But you also need to set the opacity to, say, 0.75 to make it translucent. All of this can be done in QML, no need for setting flags from C++.
import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Window 2.0
ApplicationWindow {
title: qsTr("Hello World")
width: 640
height: 480
flags: Qt.SubWindow | Qt.Tool | Qt.FramelessWindowHint | Qt.WindowSystemMenuHint | Qt.WindowStaysOnTopHint
opacity: 0.75
visible: true
menuBar: MenuBar {
Menu {
title: qsTr("File")
MenuItem {
text: qsTr("Exit")
onTriggered: Qt.quit();
}
}
}
Button {
text: "Hello World"
anchors.centerIn: parent
}
}
I know this is an old question, but as it is not marked as solved, here is my approach:
import QtQuick 2.4
import QtQuick.Controls 1.3
ApplicationWindow {
title: qsTr("Hello World")
width: 640
height: 480
flags: Qt.FramelessWindowHint
color: "transparent"
visible: true
Rectangle
{
color:"red"
width: parent.width/2
height: parent.height/2;anchors.centerIn: parent
}
}
As result, you will get a transparent background with a red rectangle in the middle. You could easily change that rectangle for an image.
Hope helped someone.
You might consider using the following code for achieving a frameless transparent window effect:
setWindowFlags(
#ifdef Q_OS_MAC
Qt::SubWindow |
#else
Qt::Tool |
#endif
Qt::FramelessWindowHint |
Qt::WindowSystemMenuHint |
Qt::WindowStaysOnTopHint
);
setAttribute(Qt::WA_NoSystemBackground, true);
// set the parent widget's background to translucent
setAttribute(Qt::WA_TranslucentBackground, true);
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
// create a display widget for displaying child widgets
QWidget* displayWidget = new QWidget;
displayWidget->setStyleSheet(".QWidget { background-color: rgba(0, 0, 0, 75%); border-width: 1px; border-style: solid; border-radius: 10px; border-color: #555555; } .QWidget:hover { background-color: rgba(68, 68, 68, 75%); border-width: 2px; border-style: solid; border-radius: 10px; border-color: #ffffff; }");
The idea is that your parent window or containing window has no frame and has a translucent background. Then you nest a child QWidget inside the parent QWidget and apply styles using QSS for transparency.
Related
I have created a custom tooltip style using this guide: https://doc.qt.io/qt-6/qtquickcontrols2-customize.html#creating-a-custom-style
here is ToolTip.qml within my style:
import QtQuick.Templates 2.0 as T
import QtQuick
T.ToolTip {
id: ctrl
contentItem: Text{
color: "red"
text: ctrl.text
}
background: Rectangle {
color: "blue"
border.color: "yellow"
}
}
And here is how I use it:
import QtQuick.Controls 2.15
import QtQml 2.15
import QtQuick.Layouts 2.15
import QtQuick
ApplicationWindow {
id: mainWindow
visible: true
width: 800
height: 600
visibility: Window.Maximized
Button {
anchors.centerIn: parent
id: button
text: "Click me"
onClicked: {
console.log("Clicked")
}
ToolTip.visible: hovered
ToolTip.text: "hello world"
}
}
The text colour works, but the background doesn't.
Why does it not show the blue background rectangle?
I am using Qt6 with PySide6.
*edit:
I have tried using TextMetrics to give the background a width and height. Is this the idiomatic way to do it? It feels like I shouldn't need text metrics. This also leaves the Label uncentered in the background, which looks bad.
import QtQuick.Templates 2.0 as T
import QtQuick
import QtQuick.Controls
T.ToolTip {
id: ctrl
contentItem: Label {
color: "red"
text: ctrl.text
}
background: Rectangle {
id: bg
color: "yellow"
width: tmet.width + 5
height: tmet.height + 5
}
TextMetrics {
id: tmet
font: ctrl.font
text: ctrl.text
}
}
Everytime I need to create custom controls I'll look into the QtQuick Basic style. On my machine I can find it here Qt/6.4.0/gcc_64/qml/QtQuick/Controls/Basic/ToolTip.qml
Templates are non-visual implementations of controls' logic and
behavior.
You need to set a size on the ToolTip. Look how they are setting the implicitWidth and implicitHeight of the ToolTip.
import QtQuick
import QtQuick.Controls.impl
import QtQuick.Templates as T
T.ToolTip {
id: control
x: parent ? (parent.width - implicitWidth) / 2 : 0
y: -implicitHeight - 3
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
contentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
contentHeight + topPadding + bottomPadding)
margins: 6
padding: 6
closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent | T.Popup.CloseOnReleaseOutsideParent
contentItem: Text {
text: control.text
font: control.font
wrapMode: Text.Wrap
color: control.palette.toolTipText
}
background: Rectangle {
border.color: control.palette.dark
color: control.palette.toolTipBase
}
}
To set the toolTip text color, it is not necessary to define a custom contentItem Label component. You can change the tooltip color by setting palette.toolTipText.
I can see your use case is to try to apply a custom ToolTip style so that all your components will inherit.
[EDIT: Change the direction of my answer to a custom Button instead of changing the default ToolTip style]
Alternatively, consider implementing custom components that have a custom ToolTip style. e.g. instead of Button, consider having MyButton. This way, we leave the default Button with the default style.
import QtQuick
import QtQuick.Controls
Page {
MyButton {
anchors.centerIn: parent
id: button
text: "Click me"
onClicked: {
console.log("Clicked")
}
ToolTip.visible: hovered
ToolTip.text: "hello world"
}
}
// MyButton.qml
import QtQuick
import QtQuick.Controls
Button {
ToolTip {
visible: parent.hovered
text: parent.ToolTip.text
palette.toolTipText: "red"
background: Rectangle {
color: "lightsteelblue"
border.color: "yellow"
}
}
}
You can Try it Online!
I'm being tasked with creating a customized title bar for our application. It needs to have rounded corners and a settings button, amongst other things. It will run exclusively on windows.
Our application uses Qt and QML for the front end.
So the only way I could find how to do this is by making the application window frameless and creating the title bar from scratch.
This is my test code:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.0
ApplicationWindow {
id: mainWindow
visible: true
visibility: Window.Maximized
title: qsTr("Hello World")
flags: Qt.FramelessWindowHint | Qt.Window | Qt.WA_TranslucentBackground
//flags: Qt.Window | Qt.WA_TranslucentBackground
color: "#00000000"
TitleBar {
id: mainTitleBar
width: mainWindow.width;
height: mainWindow.height*0.018
color: "#aaaaaa"
onCloseApplication: {
Qt.quit();
}
onMinimizeApplication: {
mainWindow.visibility = Window.Minimized
}
}
Component.onCompleted: {
console.log("Size: " + mainWindow.width + "x" + mainWindow.height)
mainTitleBar.width = mainWindow.width
mainTitleBar.height = mainWindow.height*0.023;
}
Rectangle {
id: content
width: mainWindow.width
height: mainWindow.height - mainTitleBar.height
anchors.top: mainTitleBar.bottom
anchors.left: mainTitleBar.left
color: "#00ff00"
}
}
And
Here is the title bar code (TitleBar.js file):
import QtQuick 2.0
import QtQuick.Controls 2.0
Rectangle {
/*
* Requires setting up of
* -> width
* -> height
* -> title text
* -> icon path.
* -> Background color.
*/
id: vmWindowTitleBar
border.width: 0
x: 0
y: 0
radius: 20
signal closeApplication();
signal minimizeApplication();
// The purpose of this rectangle is to erase the bottom rounded corners
Rectangle {
width: parent.width
height: parent.height/2;
anchors.bottom: parent.bottom
anchors.left: parent.left
border.width: 0
color: parent.color
}
Text {
id: titleBarText
text: "This is The Title Bar"
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: parent.width*0.018
}
Button {
id: minimizeButton
width: height
height: vmWindowTitleBar.height*0.8
anchors.right: closeButton.right
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: parent.width*0.018
background: Rectangle {
id: btnMinimizeRect
color: vmWindowTitleBar.color
anchors.fill: parent
}
onPressed:{
minimizeApplication()
}
scale: pressed? 0.8:1;
contentItem: Canvas {
id: btnMinimizeCanvas
contextType: "2d"
anchors.fill: parent
onPaint: {
var ctx = btnMinimizeCanvas.getContext("2d");
var h = minimizeButton.height;
var w = minimizeButton.width;
ctx.reset();
ctx.strokeStyle = minimizeButton.pressed? "#58595b": "#757575";
ctx.lineWidth = 6;
ctx.lineCap = "round"
ctx.moveTo(0,h);
ctx.lineTo(w,h);
ctx.closePath();
ctx.stroke();
}
}
}
Button {
id: closeButton
//hoverEnabled: false
width: height
height: vmWindowTitleBar.height*0.8
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: parent.width*0.018
background: Rectangle {
id: btnCloseRect
color: vmWindowTitleBar.color
anchors.fill: parent
}
onPressed:{
closeApplication()
}
scale: pressed? 0.8:1;
Behavior on scale{
NumberAnimation {
duration: 10
}
}
contentItem: Canvas {
id: btnCloseCanvas
contextType: "2d"
anchors.fill: parent
onPaint: {
var ctx = btnCloseCanvas.getContext("2d");
var h = closeButton.height;
var w = closeButton.width;
ctx.reset();
ctx.strokeStyle = closeButton.pressed? "#58595b": "#757575";
ctx.lineWidth = 2;
ctx.lineCap = "round"
ctx.moveTo(0,0);
ctx.lineTo(w,h);
ctx.moveTo(w,0);
ctx.lineTo(0,h);
ctx.closePath();
ctx.stroke();
}
}
}
}
Now the problem comes with minimizing the application. The first thing I realize is that when using the Qt.FramelessWindowHint flag, the icon does not appear in the Windows Taskbar. Furthermore if I minimize it this happens:
And If I click on it, it doesn't restore.
So my question is, is there a way to reproduce regular minimize behavior when pressing the minimize button?
Or alternatively, is there a way I can completely customize the title bar of the application so that I can achieve the look and feel set by our UI designer?
NOTE: The current look is just a quick test. I have not set the gradient, font, or the aforementioned settings button.
As for me, playing with frameless windows and transparent background is kind of workaround. As I know, the only way to apply a custom shape to the window is QWindow::setMask. Sinse Window is derived from QWindow you can do that in this way.
For example, in the main.cpp:
QWindow *wnd = qobject_cast<QWindow *>(engine.rootObjects().at(0));
auto f = [wnd]() {
QPainterPath path;
path.addRoundedRect(QRectF(0, 0, wnd->geometry().width(), wnd->geometry().height()), 30, 30);
QRegion region(path.toFillPolygon().toPolygon());
wnd->setMask(region);
};
QObject::connect(wnd, &QWindow::widthChanged, f);
QObject::connect(wnd, &QWindow::heightChanged, f);
f();
Since you 'cut' the shape from the window itself, excluding title bar and frames you can leave the window flags as is.
Look at this way, I try to create something that you do but change completely your code.
the problem that makes change in your window size after you minimize the window is that you didn't set the initial width and height for the window so when you minimize the app it shows in the minimum width and height.
so you need to add just this in main.qml and set the initial width and height to the maximum.
width: maximumWidth
height:maximumHeight
but In the code below I change something else too.
For example, you didn't need to emit signals and then catch them in main.qml
you have access to mainWindow in TitleBar.qml.
in TitleBar.qml :
import QtQuick 2.0
import QtQuick.Controls 2.0
Rectangle {
anchors.fill: parent
height: 30
Row {
id: row
anchors.fill: parent
Label {
id: label
text: qsTr("Title ")
}
Button {
id: button
x: parent.width -80
text: qsTr("close")
onClicked:
{
mainWindow.close()
}
}
Button {
id: button1
x: parent.width -160
width: 90
text: qsTr("Minimized")
onClicked:
{
mainWindow.showMinimized()
}
}
}
}
and in main.qml :
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.0
import "."
Window {
id: mainWindow
visible: true
visibility: Window.FullScreen
title: qsTr("Hello World")
flags: Qt.FramelessWindowHint | Qt.Window | Qt.WA_TranslucentBackground
width: maximumWidth
height:maximumHeight
Rectangle {
id: content
anchors.fill: parent
x: 0
y: 20
width: mainWindow.width
height: mainWindow.height - mainTitleBar.height
anchors.top: mainTitleBar.bottom
anchors.left: mainTitleBar.left
color: "#00ff00"
}
TitleBar {
id: mainTitleBar
color: "#aaaaaa"
anchors.bottomMargin: parent.height -40
anchors.fill: parent
}
}
I have a simple qml ApplicationWindow program with "Maximized" visibility. The application fits properly on my screen when the PC setting is below:
Resolution : 1920x1080 (Recommended)
Scale : 100%
screenshot : Resolution_1920x1080_scale_100_screenshot.JPG
But,when I configured the laptop’s setting “Scale and Layout” to 100% and laptop display at the highest resolution (1366 x 768), the right side of my application is being cut.
screenshot (which has issue): Resolution_1355x768_scale_100_screenshot.JPG
Any suggestions to solve it??
Qml:
import QtQuick 2.14
import QtQuick.Controls 2.14
ApplicationWindow {
id:root
visible: true
visibility: Window.Maximized//"Maximized"
title: qsTr("Hello World")
Rectangle {id:red; width: 900; height: 350; color: "red" }
Rectangle {id:yellow; width: 900; height: 350; color: "yellow"; anchors.left: red.right }
}
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
Below is the screenshot of application with resolution 1920x1080 setting. Both Red and Yellow rectangles are of same size.
Above one is the screenshot of application with resolution 1366x768 setting. Both Red and Yellow rectangles are of same size. But, yellow half part is not visible with these setting.
in your code you used fixed size Rectangles. So changing the display resolution won't change the size of the items. Use relative position and size for this to work:
import QtQuick 2.14
import QtQuick.Controls 2.14
ApplicationWindow {
id:root
visible: true
visibility: Window.Maximized//"Maximized"
title: qsTr("Hello World")
Rectangle {id:red; width: root.width/2; height: parent.height; color: "red" }
Rectangle {id:yellow; width: root.width/2; height: parent.height; color: "yellow"; anchors.left: red.right }
}
I use Drawer from QtQuick.Controls 2.2
Drawer {
id: drawer
width: parent.width/2
height: parent.height
modal: true
...
}
With style:
[Controls]
Style=Material
[Material]
Theme=Dark
Accent=Red
Primary=#c64949
I want to change a color of the Drawer shadow. Style Material uses a white color for the shadow (that to the right of the open Drawer).
-- Edit by Bounty Sponsor --
I have discovered the shadow is defined, ie. here: http://code.qt.io/cgit/qt/qtquickcontrols2.git/tree/src/imports/controls/Drawer.qml
as:
T.Overlay.modal: Rectangle {
color: Color.transparent(control.palette.shadow, 0.5)
}
T.Overlay.modeless: Rectangle {
color: Color.transparent(control.palette.shadow, 0.12)
}
Without defining an entirely new Style, how can one modify them as one-off?
I presumably can redefine an entirely custom control.. but there ought to be a compatible version?
What you are looking for is Overlay.modal property, as #Blabdouze mentioned. Simple working example:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
Window {
visible: true
width: 640
height: 480
title: qsTr("test")
Drawer {
height: parent.height
width: parent.width/2
Rectangle {
anchors.fill: parent
color: "green"
}
Overlay.modal: Rectangle {
color: "red"
}
}
}
Default edge is left, so drag it from there.
Links:
Documentation
Drawer source code
I want to set my demo layout is Right to Left, and I set this in main function, like this:
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
app.setLayoutDirection(Qt::RightToLeft)
return app.exec();
}
Here is my qml file:
import QtQuick 2.6
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
id:root
Row {
spacing: 20
Repeater {
model: 5
Rectangle {
color: "red"
opacity: (5 - index) / 5
width: 70; height: 30
Text {
text: index + 1+" hello"
width:parent.width
}
}
}
}
}
However the layout result still is left to right:
How can I get the real RTL layout, all components are right to left, include the text, just like this:
Right-to-left User Interfaces says that you should use the LayoutMirroring attached properties. Taking the example from that page:
import QtQuick 2.0
Rectangle {
LayoutMirroring.enabled: true
LayoutMirroring.childrenInherit: true
width: 300; height: 50
color: "yellow"
border.width: 1
Row {
anchors { left: parent.left; margins: 5 }
y: 5; spacing: 5
Repeater {
model: 5
Rectangle {
color: "red"
opacity: (5 - index) / 5
width: 40; height: 40
Text {
text: index + 1
anchors.centerIn: parent
}
}
}
}
}