I have a Qml App that has a Win32 window as a child window. Now, I simply want to show a popup on the click of a button(or Image in my case) on top of Win32 window but Popup is not coming on top.
Working code is as below:-
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QWindow>
#include "qt_windows.h"
#include "Windows.h"
#pragma comment(lib, "user32.lib")
/*
* Input Window proc
*/
LRESULT CALLBACK uiInputWindowProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
/*
* Create window that receives and forwards input
*/
void uiCreateInputWindow(
HWND parentWindow,
int x,
int y,
int width,
int height)
{
#define UI_INPUT_WINDOW_CLASS L"uiNativeInputWindowClass"
/*
* Register Window Class
*/
WNDCLASSEX wcex;
wcex.cbSize = sizeof wcex;
wcex.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)uiInputWindowProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(void*);
wcex.hInstance = NULL;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_BACKGROUND+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = UI_INPUT_WINDOW_CLASS;
wcex.hIconSm = NULL;
if (RegisterClassEx(&wcex) == 0 && GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
{
return;
}
DWORD style = WS_CHILD;
DWORD exstyle = 0;
/*
* Create Window
*/
HWND hwnd = CreateWindowEx(
exstyle, // dwExStyle
UI_INPUT_WINDOW_CLASS, // lpClassName
L"uiNativeInputWindow", // lpWindowName
style, // dwStyle
x, // x
y, // y
width, // nWidth
height, // nHeight
parentWindow, // hWndParent
NULL, // hMenu
0, // hInstance
0); // lpParam
if (hwnd != NULL)
{
ShowWindow(hwnd, SW_SHOW);
SetFocus(hwnd);
}
}
/*
* Initialize ui
*/
int main(int argc, char* argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine* engine = new QQmlApplicationEngine;
engine->load(QUrl(QStringLiteral("qrc:/main.qml")));
QObject* qmlRoot = engine->rootObjects().first();
QWindow* mainWindow = qobject_cast<QWindow*>(qmlRoot);
int fbWidth = 1920, fbHeight = 1080;
uiCreateInputWindow((HWND)mainWindow->winId(), 0, 70, fbWidth, fbHeight);
app.exec();
}
main.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import QtQuick.Window 2.12
ApplicationWindow {
id: root
x: 10
y: 10
width: 1920
height: 1150
visible: true
flags: Qt.Window | Qt.FramelessWindowHint
RowLayout {
anchors.fill: parent
spacing: 0
ColumnLayout {
spacing: 0
Rectangle {
id: topbar
color: "#232642"
Layout.fillWidth: true
Layout.preferredHeight: 70
MouseArea {
anchors.fill: parent
property point lastMouse
onPressed: {
lastMouse = mapToGlobal(mouseX, mouseY)
}
onPositionChanged: {
var newMouse = mapToGlobal(mouseX, mouseY)
root.x += newMouse.x - lastMouse.x
root.y += newMouse.y - lastMouse.y
lastMouse = newMouse
}
onDoubleClicked: {
root.visibility == ApplicationWindow.Windowed ?
root.showMaximized() :
root.showNormal()
}
}
RowLayout {
anchors.fill: parent
spacing: 0
Text {
text: "Test Window"
color: "#F8F8EE"
font.family: "Segoe UI"
font.pointSize: 11
font.weight: Font.DemiBold
Layout.fillHeight: true
Layout.topMargin: 10
Layout.leftMargin: 10
}
Item {
Layout.fillWidth: true
}
/*
Show Popup on click of this image
*/
Image {
id: cfgBtn
source: "Assets/cfgmenu.png"
Layout.fillHeight: true
Layout.preferredWidth: height
MouseArea {
anchors.fill: parent
onClicked: optionsPopup.open()
}
}
Image {
source: "Assets/closewindow.png"
Layout.fillHeight: true
Layout.preferredWidth: height
MouseArea {
anchors.fill: parent
onClicked: root.close()
}
}
}
}
Rectangle {
id: containerLv1
Layout.fillWidth: true
Layout.fillHeight: true
color: "black"
Rectangle {
id: containerLv2
width: Math.round(Math.min(containerLv1.width,
containerLv1.height * 16 / 9))
height: Math.round(Math.min(containerLv1.height,
containerLv1.width * 9 / 16))
anchors.centerIn: parent
visible: true
color: "grey"
}
}
}
}
/*
Desired popup to show
*/
Popup {
id: optionsPopup
x: cfgBtn.x - 160
y: topbar.y + topbar.height + 5
width: 200
height: 120
focus: true
dim: false
modal: true
padding: 0
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
contentItem: Rectangle {
id: rect
anchors.centerIn: parent
color: "#FF232642"
ColumnLayout {
spacing: 0
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
Rectangle {
Layout.preferredWidth: 200
Layout.preferredHeight: 40
color: "transparent"
Text {
anchors.fill: parent
text: "Option1"
color: "white"
font.pointSize: 14
}
}
Rectangle {
Layout.preferredWidth: 200
Layout.preferredHeight: 40
color: "transparent"
Text {
anchors.fill: parent
text: "Option2"
color: "white"
font.pointSize: 14
}
}
Rectangle {
Layout.preferredWidth: 200
Layout.preferredHeight: 40
color: "transparent"
Text {
anchors.fill: parent
text: "Option3"
color: "white"
font.pointSize: 14
}
}
}
}
}
}
The native window is part of our application and is used for receiving mouse and keyboard inputs. Any suggestion is most welcomed.
I did a hack to solve this. Basically, the problem is everything that is drawn as part of Qml window gets hidden below the native window and there is no good way(that I can find online) to do this except by adding another layer of a modal window.
So, before opening the popup, just create a transparent modal window over which your popup can be shown and close this window when the popup closes.
I am still looking for a better way to do this.
Related
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
}
}
We want to implement an embedded code editor in our QtQuick based application. For highlighting we use a QSyntaxHighlighter based on KSyntaxHighlighting. We found no way to determine the line height and line spacing that would allow us to display line numbers next to the code. Supporting dynamic line-wrap would also be a great addition.
Flickable {
id: flickable
flickableDirection: Flickable.VerticalFlick
Layout.preferredWidth: parent.width
Layout.maximumWidth: parent.width
Layout.minimumHeight: 200
Layout.fillHeight: true
Layout.fillWidth: true
boundsBehavior: Flickable.StopAtBounds
clip: true
ScrollBar.vertical: ScrollBar {
width: 15
active: true
policy: ScrollBar.AlwaysOn
}
property int rowHeight: textArea.font.pixelSize+3
property int marginsTop: 10
property int marginsLeft: 4
property int lineCountWidth: 40
Column {
id: lineNumbers
anchors.left: parent.left
anchors.leftMargin: flickable.marginsLeft
anchors.topMargin: flickable.marginsTop
y: flickable.marginsTop
width: flickable.lineCountWidth
function range(start, end) {
var rangeArray = new Array(end-start);
for(var i = 0; i < rangeArray.length; i++){
rangeArray[i] = start+i;
}
return rangeArray;
}
Repeater {
model: textArea.lineCount
delegate:
Label {
color: (!visualization.urdfPreviewIsOK && (index+1) === visualization.urdfPreviewErrorLine) ? "white" : "#666"
font: textArea.font
width: parent.width
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
height: flickable.rowHeight
renderType: Text.NativeRendering
text: index+1
background: Rectangle {
color: (!visualization.urdfPreviewIsOK && (index+1) === visualization.urdfPreviewErrorLine) ? "red" : "white"
}
}
}
}
Rectangle {
y: 4
height: parent.height
anchors.left: parent.left
anchors.leftMargin: flickable.lineCountWidth + flickable.marginsLeft
width: 1
color: "#ddd"
}
TextArea.flickable: TextArea {
id: textArea
property bool differentFromSavedState: fileManager.textDifferentFromSaved
text: fileManager.textTmpState
textFormat: Qt.PlainText
//dont wrap to allow for easy line annotation wrapMode: TextArea.Wrap
focus: false
selectByMouse: true
leftPadding: flickable.marginsLeft+flickable.lineCountWidth
rightPadding: flickable.marginsLeft
topPadding: flickable.marginsTop
bottomPadding: flickable.marginsTop
background: Rectangle {
color: "white"
border.color: "green"
border.width: 1.5
}
Component.onCompleted: {
fileManager.textEdit = textArea.textDocument
}
onTextChanged: {
fileManager.textTmpState = text
}
function update()
{
text = fileManager.textTmpState
}
}
}
As you can see we use property int rowHeight: textArea.font.pixelSize+3 to guess the line height and line spacing but that of course breaks as soon as DPI or other properties of the system change.
The TextArea type has two properties contentWidth and contentHeight which contains the size of the text content.
So, if you divide the height by the number of lines (which you can get with the property lineCount), you will get the height of a line:
property int rowHeight: textArea.contentHeight / textArea.lineCount
But, if you plan to have multiple line spacing in the same document, you will have to handle each line by manipulating the QTextDocument:
class LineManager: public QObject
{
Q_OBJECT
Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged)
public:
LineManager(): QObject(), document(nullptr)
{}
Q_INVOKABLE void setDocument(QQuickTextDocument* qdoc)
{
document = qdoc->textDocument();
connect(document, &QTextDocument::blockCountChanged, this, &LineManager::lineCountChanged);
}
Q_INVOKABLE int lineCount() const
{
if (!document)
return 0;
return document->blockCount();
}
Q_INVOKABLE int height(int lineNumber) const
{
return int(document->documentLayout()->blockBoundingRect(document->findBlockByNumber(lineNumber)).height());
}
signals:
void lineCountChanged();
private:
QTextDocument* document;
};
LineManager* mgr = new LineManager();
QQuickView *view = new QQuickView;
view->rootContext()->setContextProperty("lineCounter", mgr);
view->setSource(QUrl("qrc:/main.qml"));
view->show();
Repeater {
model: lineCounter.lineCount
delegate:
Label {
color: "#666"
font: textArea.font
width: parent.width
height: lineCounter.height(index)
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
renderType: Text.NativeRendering
text: index+1
background: Rectangle {
border.color: "black"
}
}
}
I found a QML only solution:
Use TextEdit instead of TextArea to avoid alignment issues between line numbers and text
Use a 'ListView' to generate the line numbers for the text edit:
Here is an initial solution:
RowLayout {
anchors.fill: parent
ListView {
Layout.preferredWidth: 30
Layout.fillHeight: true
model: textEdit.text.split(/\n/g)
delegate: Text { text: index + 1 }
}
TextEdit {
id: textEdit
Layout.fillWidth: true
Layout.fillHeight: true
}
}
The ListView has a complete copy of each row of text. We can use this copy to compute the line height (taking into account of word wrap). We do this by creating an invisible Text. We can improve the answer further by adding a Flickable to the TextEdit and synchronize the scroll between the ListView and the TextEdit:
Here is a more complete solution:
// NumberedTextEdit.qml
import QtQuick 2.12
import QtQuick.Controls 2.5
Item {
property alias lineNumberFont: lineNumbers.textMetrics.font
property color lineNumberBackground: "#e0e0e0"
property color lineNumberColor: "black"
property alias font: textEdit.font
property alias text: textEdit.text
property color textBackground: "white"
property color textColor: "black"
Rectangle {
anchors.fill: parent
color: textBackground
ListView {
id: lineNumbers
property TextMetrics textMetrics: TextMetrics { text: "99999"; font: textEdit.font }
model: textEdit.text.split(/\n/g)
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.margins: 10
width: textMetrics.boundingRect.width
clip: true
delegate: Rectangle {
width: lineNumbers.width
height: lineText.height
color: lineNumberBackground
Text {
id: lineNumber
anchors.horizontalCenter: parent.horizontalCenter
text: index + 1
color: lineNumberColor
font: textMetrics.font
}
Text {
id: lineText
width: flickable.width
text: modelData
font: textEdit.font
visible: false
wrapMode: Text.WordWrap
}
}
onContentYChanged: {
if (!moving) return
flickable.contentY = contentY
}
}
Item {
anchors.left: lineNumbers.right
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.margins: 10
Flickable {
id: flickable
anchors.fill: parent
clip: true
contentWidth: textEdit.width
contentHeight: textEdit.height
TextEdit {
id: textEdit
width: flickable.width
color: textColor
wrapMode: Text.WordWrap
}
onContentYChanged: {
if (lineNumbers.moving) return
lineNumbers.contentY = contentY
}
}
}
}
}
I've found that you can query the line height using FontMetrics and then getting the true height by Math.ceil(fontMetrics.lineSpacing) for example:
TextEdit {
id: textArea
FontMetrics {
id: fontMetricsId
font: textArea.font
}
Component.onCompleted: {
console.log("Line spacing:" + Math.ceil(fontMetricsId.lineSpacing)
}
}
I would like to create a slideshow showing 3 items with a picture and a label for each, the item in the middle being highlighted (picture is bigger and a description text appears below the label).
When a corresponding arrow is clicked, I would like the items to "slide" instead of just appearing where they should. Unfortunately, the Behavior on x {
NumberAnimation{...}} code in the delegate does not do this.
Here is my code:
import QtQuick 2.7
import QtQuick.Window 2.0
Window {
id: display
width: 500
height: 300
visible: true
Item {
id: conteneur
anchors.leftMargin: 50
height: display.height / 1.2
width: display.width / 1.2
anchors.horizontalCenter: parent.horizontalCenter
Rectangle {
id: boutonAvant
height: conteneur.height
anchors.verticalCenter: parent.verticalCenter
width: 68
x: -50
color: "transparent"
z: 1
Text {
id: pictureAv
anchors.centerIn: parent
text: "<"
font.pixelSize: 90
}
MouseArea {
id: buttonAvMouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: listview.decrementCurrentIndex()
}
}
ListView {
id: listview
clip: true
orientation: ListView.Horizontal
width: conteneur.width
height: conteneur.height / 1.2
anchors.centerIn: conteneur
model: myListModel
delegate: myDelegate
maximumFlickVelocity: 700
snapMode: ListView.SnapToItem
highlightFollowsCurrentItem: true
highlightRangeMode: ListView.StrictlyEnforceRange
preferredHighlightBegin: conteneur.width * 0.3
preferredHighlightEnd: conteneur.width * 0.3 + conteneur.width * 0.4
onCurrentIndexChanged: {
positionViewAtIndex(currentIndex, ListView.SnapPosition)
}
Component.onCompleted: {
currentIndex = 1
}
}
Rectangle {
id: boutonApres
height: conteneur.height
anchors.verticalCenter: parent.verticalCenter
x: conteneur.width - 10
width: 68
color: "transparent"
Text {
id: pictureAp
anchors.centerIn: parent
text: ">"
font.pixelSize: 90
}
MouseArea {
id: buttonApMouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: listview.incrementCurrentIndex()
}
}
}
ListModel {
id: myListModel
ListElement {
name: "rectangle 0"
desc: "blabla"
mycolor: "green"
}
ListElement {
name: "rectangle 1"
desc: "blabla"
mycolor: "blue"
}
ListElement {
name: "rectangle 2"
desc: "blabla"
mycolor: "lightblue"
}
ListElement {
name: "rectangle 3"
desc: "blabla, \n with several lines for test \n and more lines \n and more lines"
mycolor: "gold"
}
}
Component {
id: myDelegate
Rectangle {
id: cadre
opacity: listview.currentIndex === index ? 1 : 0.5
anchors.top: parent.top
anchors.topMargin: listview.currentIndex === index ? 0 : 35
width: listview.currentIndex === index ? listview.width * 0.4 : listview.width * 0.3
height: conteneur.height
border.color: mycolor
color: "transparent"
Behavior on x {
NumberAnimation {
duration: 800
}
}
}
}
}
ListView inherits Flickable which uses contentX and contentY to govern what's visible. The model Rectangles don't actually move.
I would try a Behavior on ListView's contentX. Note that the documentation for positionViewAtIndex says not manipulate those directly because the math on them is not predictable – but a behavior on them may work.
I finally had some result using this :
//In bouton Avant :
MouseArea{
id: boutonAvant
anchors.fill: parent
hoverEnabled: true
onClicked: {
pictureAp.visible = true;
var oldPos = listview.contentX;
listview.decrementCurrentIndex();
var newPos = oldPos - listview.width*0.3; // listview.width*0.3 is the width of one item that is not the current one
if(listview.currentIndex == 0){
pictureAv.visible = false;
}
anim.running = false
anim.from = oldPos;
anim.to = newPos;
anim.running = true;
}
}
}
The ListView becomes :
ListView{
id: listview
clip: true
orientation: ListView.Horizontal
width: conteneur.width
height: conteneur.height/1.2
anchors.centerIn: conteneur
model: myListModel
delegate: myDelegate
Component.onCompleted: {
currentIndex = 1;
}
}
NumberAnimation { id: anim; target: listview; property: "contentX"; duration: 800 }
And boutonApres is similar to boutonAvant with :
MouseArea{
id: buttonApMouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: {
pictureAv.visible = true;
var oldPos = listview.contentX;
listview.incrementCurrentIndex();
var newPos = oldPos + listview.width*0.3;
if(listview.currentIndex == listview.count-1){
pictureAp.visible = false;
}
anim.running = false
anim.from = oldPos;
anim.to = newPos;
anim.running = true;
}
}
It works fines when items being 'slided' are in the middle of the listview but when I get to the first item (on the last click on the left arrow), or to the last item (on the last click on the right arrow), I get a disturbing 'flick' as if the listview was trying to move at two places at the same time, following 2 different orders. But I can't see where this could come from...
I have Rectangle filled with MouseArea which on onPressAndHold() handler reveals second Rectangle and transfers drag action to that Rectangle. The problem is that when I move that second Rectangle over DropArea it doesn't notify about any actions (onEntered, onExited, onDropped). I tried to do this in many combinations but it has never worked. Here is an example, am I missing something?
import QtQuick 2.0
import QtQuick.Window 2.0
Window {
id: appDrawerRoot
visible: true
width: 360; height: 360
property bool isRectVisible: false
Rectangle{
id:rect
color: "blue"
x:50; y:50
width: 50; height: 50
MouseArea{
anchors.fill: parent
onPressed: {
cloneRect.x = rect.x
cloneRect.y = rect.y
}
onPressAndHold: {
isRectVisible = true
drag.target = cloneRect
}
onReleased: {
drag.target = undefined
isRectVisible = false
cloneRect.x = rect.x
cloneRect.y = rect.y +100
}
}
}
Item{
id: cloneRect
width: 50; height:50
visible: isRectVisible
MouseArea{
id: mouseArea
width:50; height:50
anchors.centerIn: parent
Rectangle{
id:tile
width: 50; height:50
color:"black"
opacity: 0.5
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
Drag.hotSpot.x: 25
Drag.hotSpot.y: 25
}
}
}
DropArea {
id:dropArea
x:153
y:158
z:-1
width:100; height: 100
Rectangle{
anchors.fill: parent
color: "Green"
}
onEntered: {
drag.source.opacity = 1
console.log("ENTERED")
}
onExited: {
drag.source.opacity = 0.5
console.log("EXITED")
}
onDropped:
{
console.log("DROPPED")
}
}
}
The main problem with your code is that you don't set the active property of the drag. Modify you code like this:
//..........................
Item{
id: cloneRect
width: 50; height:50
visible: isRectVisible
Drag.active: visible // Add this line of code
//.....................
For more information please refer to Qt examples. At Qt Creator's "Welcome" screen hit "Examples" button and search for "drag and drop qml".
The problem is simple: window doesn't rendering and refresh, until the program is finished. It just doesn't show anything.
And I want to see the window even if the long cycle is not finished yet.
I will be very grateful for any help!
#include <QtGui>
#include <QtQml>
int main(int _nArgCount, char * _pArgValues[]) {
QApplication app(_nArgCount, _pArgValues);
//QMLblock
QString strQmlPath = "../main.qml";
QQmlApplicationEngine engine;
QQmlComponent pComponent(&engine, strQmlPath);
if( pComponent.status()==QQmlComponent::Error )
{ qDebug()<<"Error:"<<pComponent.errorString();
return app.exec();
}
QObject * pQmlObject = pComponent.create();
QObject * pWindow = pQmlObject->findChild<QObject*>("initStateGui");
QObject * pWindowNext = pQmlObject->findChild<QObject*>("searchRemovableGui");
pWindow->setProperty("visible","false");
pWindowNext->setProperty("visible","true");
QObject * pList = pQmlObject->findChild<QObject*>("devicesList");
QStringList s;
QString str;
s.append("3");
pList->setProperty("model",s);
for (int i=0; i<5; i++){
s.append(str.number(i));
pList->setProperty("model",s);
}
return app.exec();
}
And my QML (I don't think it's needed, but anyway):
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Window 2.2
QtObject {
property real defaultSpacing: 10
property SystemPalette palette: SystemPalette { }
property var controlWindow: Window {
width: 500
height: 500
color: palette.window
title: "Updater"
visible: true
//init state
Column {
id: initStateGui
objectName: "initStateGui"
anchors.fill: parent
anchors.margins: defaultSpacing
spacing: defaultSpacing
property real cellWidth: initStateGui.width / 3 - spacing
visible: true
Text { text: "Init state" }
Grid {
id: grid
columns: 3
spacing: defaultSpacing
width: parent.width
Button {
id: showButton
width: initStateGui.cellWidth
text: "Cancel"
onClicked: Qt.quit()
}
Button {
id: initStateContinue
objectName: "initStateContinue"
width: initStateGui.cellWidth
text: "Continue"
signal sigInitStateContinue()
onClicked: initStateContinue.sigInitStateContinue()
}
}
Text {
id: textLabel
text: "Welcome to the updater!"
}
Rectangle {
id: horizontalRule
color: "black"
width: parent.width
height: 1
}
}
//updater update state
Column {
id: updaterUpdateGui
objectName: "updaterUpdateGui"
anchors.fill: parent
anchors.margins: defaultSpacing
spacing: defaultSpacing
visible: false
property real cellWidth: initStateGui.width / 3 - spacing
Text { text: "UpdaterUpdate State" }
Grid {
id: grid1
columns: 3
spacing: defaultSpacing
width: parent.width
Button {
id: showButton1
width: initStateGui.cellWidth
text: "Cancel"
onClicked: Qt.quit()
}
Button {
id: updaterUpdateContinue
objectName: "updaterUpdateContinue"
width: initStateGui.cellWidth
text: "Continue"
signal sigUpdaterUpdateContinue()
onClicked: updaterUpdateContinue.sigUpdaterUpdateContinue()
}
}
Text {
text: "Update is started!"
}
Rectangle {
id: horizontalRule1
color: "black"
width: parent.width
height: 1
}
}
//removable Search gui
Column {
id:searchRemovableGui
objectName: "searchRemovableGui"
anchors.fill: parent
anchors.margins: defaultSpacing
spacing: defaultSpacing
visible: false
property real cellWidth: initStateGui.width / 3 - spacing
Text { text: "Removable search State" }
Grid {
id: grid2
columns: 3
spacing: defaultSpacing
width: parent.width
Button {
id: showButton2
width: initStateGui.cellWidth
text: "Cancel"
onClicked: Qt.quit()
}
}
Text {
text: "Searching for removable, please wait...!"
}
ListView {
id:devicesList
objectName:"devicesList"
width: 100; height: 500
model: myModel
delegate: Rectangle {
height: 15
width: 100
Text { text: modelData }
}
}
}
}
}
Addition: i don't need threads, i need to see the freezed window with the caption.
I see it if i add the button, and begin cycle after the button is pressed.
Without the button the window doesn't rendering, and i can't find how to do it.
It's impossible to realize in one thread.
Only moving long process to another thread allows to render GUI.