I try to use ItemGrabResult {} element. But I got error
"QQmlApplicationEngine failed to load component"
"ItemGrabResult is not a type"
import QtQuick 2.15
Item {
id: root
ItemGrabResult {
}
Rectangle {
id: rect
color: "red"
anchors.fill: parent
}
ItemGrabResult is inactive
In documentation https://doc.qt.io/qt-5/qml-qtquick-itemgrabresult.html#details
I can not find any information how to import this element in CMake (or qmake) file
As iam_peter indicated, the ItemGrabResult comes from a call to Item.grabToImage().
In the following example, you need to click on the red Rectangle and it will initiate a grabToImage() call. The callback will have an instance of the ItemGrabResult which has properties and methods for accessing the grabbed image:
import QtQuick
import QtQuick.Controls
Page {
Item {
id: frame
width: 200
height: 200
Rectangle {
id: rect
color: "red"
anchors.fill: parent
}
MouseArea {
anchors.fill: parent
onClicked: {
frame.grabToImage( function (itemGrabResult) {
// itemGrabResult: QQuickItemGrabResult(0x254f9a0)
// itemGrabResult.image: QVariant(QImage, QImage(QSize(200, 200),format=QImage::Format_RGBA8888_Premultiplied,depth=32,devicePixelRatio=1,bytesPerLine=800,sizeInBytes=160000))
// itemGrabResult.saveToFile: function() { [native code] }
dbg.text = `
itemGrabResult: ${itemGrabResult.toString()}
itemGrabResult.image: ${itemGrabResult.image.toString()}
itemGrabResult.saveToFile: ${itemGrabResult.saveToFile.toString()}
`
} );
}
}
}
footer: TextEdit { id: dbg; wrapMode: Text.WordWrap }
}
You can Try it Online!
https://doc.qt.io/qt-6/qml-qtquick-item.html#grabToImage-method
Related
For my Custom window, shown in the answer, I've created a Component named PathButton
import QtQuick 2.0
import QtQuick.Shapes 1.12
Item {
property alias pathData: svg.path
width: 24
height: 24
Shape {
ShapePath {
fillColor: "black"
PathSvg {
id: svg
path: pathData
}
}
}
}
and used it to minimize, maximize and close the window like this:
RowLayout{
Layout.preferredWidth: 100
anchors.right: title.right
PathButton{
pathData: ViewModel.minimizeIcon
MouseArea{
anchors.fill: parent
onClicked: mainWindow.showMinimized()
}
}
PathButton{
pathData: ViewModel.maximizeIcon
MouseArea{
anchors.fill: parent
//this doesn't restore the window to its Normal state, showMaximized() is called always
onClicked: mainWindow.Maximized? mainWindow.showNormal() : mainWindow.showMaximized()
}
}
PathButton{
pathData: ViewModel.closeIcon
MouseArea{
anchors.fill: parent
onClicked: mainWindow.close()
}
}
}
in all those I've a MouseArea. What I want is to have that MouseArea in my Custom Component and declare a property of type eventhandler/signal/slot and assign that handler for onClicked like this:
import QtQuick 2.0
import QtQuick.Shapes 1.12
Item {
property alias pathData: svg.path
property alias handler: mouse.onClicked
width: 24
height: 24
Shape {
ShapePath {
fillColor: "black"
PathSvg {
id: svg
path: pathData
}
}
}
MouseArea{
id: mouse
anchors.fill: parent
onClicked: handler
}
}
and in its usage I want to assign the relevant function like this:
PathButton{
pathData: ViewModel.minimizeIcon
handler: mainWindow.showMinimized()
}
EDIT
Here's what I've in PathButton.qml:
import QtQuick 2.0
import QtQuick.Shapes 1.12
Item {
id: root
property alias pathData: svg.path
signal onClicked()
width: 24
height: 24
Shape {
ShapePath {
fillColor: "black"
PathSvg {
id: svg
path: pathData
}
}
}
MouseArea{
anchors.fill: parent
onClicked: root.onClicked()
}
}
and in main.qml I get that error and when I hit run with that error, in Application Output I get another error:
I think what you're looking for is simply a signal:
// PathButton.qml
Item {
id: root
signal clicked()
...
MouseArea {
onClicked: root.clicked()
}
}
Then you would use it like this:
PathButton {
onClicked: mainWindow.showMinimized()
}
I have this main.qml:
import QtQuick 2.13
import QtQuick.Window 2.13
import QtQuick.Controls 2.5
ApplicationWindow {
...
Item {
// This Item is to provide needed properties for functionality in the original app that was elided out in this example.
// It was left in in case it's relevant to the problem.
...
Column {
...
Text {
text: qsTr("Masked text")
SlidingMask {
id: testMask
anchors.fill: parent
...
}
}
Row {
Button {
id: btnRevealText
text: qsTr("Reveal")
...
}
Button {
id: btnHideText
text: qsTr("Hide")
...
}
}
}
}
Connections {
target: btnRevealText
onPressed: testMask.reveal()
}
Connections {
target: btnHideText
onPressed: testMask.hide()
}
}
And this SlidingMask.qml that's registered in the qml.qrc:
import QtQuick 2.0
Rectangle {
...
function hide() {
...
}
function reveal() {
...
}
}
When I run the app and try to press the buttons, I get the following errors:
TypeError: Property 'hide' of object SlidingMask_QMLTYPE_7(0x19991132c50) is not a function
TypeError: Property 'reveal' of object SlidingMask_QMLTYPE_7(0x19991132c50) is not a function
However, if I try changing the Connections to alter a property of the SlidingMask instead of calling a function, it works fine.
I've also tested this component previously and didn't run into any problems then, although I wasn't using Connections in that test.
I've searched here and on Google for an answer, but nothing I've found seems relevant to my situation. How would I fix this?
Here is a simple example which works properly:
//main.qml
ApplicationWindow {
id: window
width: 640
height: 480
visible: true
Column{
ItemWithFunction{
id: sc
width: 100
height: 100
}
Button{
id: btn1
text: 'Test Connection'
}
}
Connections{
target: btn1
onPressed: sc.testFunction();
}
}
//ItemWithFunction.qml
Rectangle{
color: 'red'
function testFunction(){
console.log("SOMETHING HAPPENED")
}
}
It seems that you are not putting your functions in SlidingMask root but in one of its child components.
I'm trying to open a "About" dialog from the menubar.
I have a MainMenuBar.qml that looks like this:
import QtQuick 2.12
import './dialogs'
Labs.MenuBar {
// Various menus omitted
AboutDialog {
id: about_dialog
}
Labs.Menu {
title: qsTr('&Help')
Labs.MenuItem {
text: qsTr('&About')
onTriggered: about_dialog.open()
}
}
}
And my AboutDialog.qml:
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
Dialog {
title: qsTr('id_about')
width: 500
height: 350
standardButtons: Dialog.Ok
Page {
anchors.fill: parent
header: RowLayout {
Image {
Layout.margins: 16
source: "../ic_home.png"
}
}
Label {
anchors.fill: parent
anchors.margins: 32
wrapMode: Text.WordWrap
text: qsTr("Hello world")
}
}
}
When clicking "About" I get:
/src/MainMenuBar.qml: QML Dialog: cannot find any window to open popup in.
I suppose that happens because I am opening it from the menubar and not from a window - is that possible? What should I do?
Nevermind, I figured it out.
AboutDialog.qml shouldn't be declared in MainMenuBar.qml, should be declared in main.qml instead.
MainMenuBar.qml
import QtQuick 2.12
import './dialogs'
Labs.MenuBar {
// Various menus omitted
Labs.Menu {
title: qsTr('&Help')
Labs.MenuItem {
text: qsTr('&About')
onTriggered: about_dialog.open()
}
}
}
main.qml
Item {
MainMenuBar { }
AboutDialog {
id: about_dialog
}
}
In my MyHeader.qml cannot load the MyChild2.qml. How to load child qml page on to mmain.qml page calling from another child qml page as shown below.
TestProject Folder
qml Folder
Main.qml
MyChild1.qml
mainui Folder
MyHeader.qml
MyChild2.qml
import QtQuick 2.10
import QtQuick.Controls 2.2
import "."
// Main.qml
ApplicationWindow {
id: rootApp
Loader {
id: loaderPage
anchors.fill: parent
}
MyChild1 {
}
}
// MyChild1.qml
import QtQuick 2.10
import QtQuick.Controls 2.2
import "."
Page {
id: myItem1
anchors.fill: parent
MyHeader {
anchors.top: parent.top
}
}
// MyChild2.qml
import QtQuick 2.10
import QtQuick.Controls 2.2
import "."
Page {
id: myItem2
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: "#000000"
}
}
// MyHeader.qml
import QtQuick 2.10
import QtQuick.Controls 2.2
import "."
Rectangle {
id: myHeader
width: parent.width
height: dp(30)
color: "lightblue"
Text {
id: loadQML
text: "Load QML"
color: "#000000"
font.pixelSize: dp(20)
MouseArea {
anchors.fill: parent
onClicked: {
myItem1.visible = false
loaderPage.source = "MyChild2.qml"
loaderPage.Top
}
}
}
}
Using the Loader and Connection I am getting Cannot assign to non-existent property "onPageChanged"
import QtQuick 2.10
import "mainui"
ApplicationWindow {
id: rootApp
signal pageChanged(int page);
Loader {
id:rootLoader
anchors.fill: parent
source: "mainui/Page1.qml"
Connections {
target: rootLoader.item
onPageChanged: {
switch(page)
{
case 1: rootLoader.source = "mainui/Page1.qml"; break;
case 2: rootLoader.source = "mainui/Page2.qml"; break;
}
}
}
}
} // APP
Due to scope limitation of Loader you cannot access items outside it. But you can notify the Loader to do some action. In the example below there are 2 components define a signal. The Loader connects this signal to a handler:
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
id: win
width: 400
height: 400
title: "Test"
visible: true
Component {
id: page1
Rectangle {
signal pageChanged(int page);
anchors.fill: parent
color: "orange"
Text {
anchors.centerIn: parent
text: "PAGE 1\nClick to change"
horizontalAlignment: Text.AlignHCenter
}
MouseArea {
anchors.fill: parent
onClicked: {
pageChanged(2);
}
}
}
}
Component {
id: page2
Rectangle {
signal pageChanged(int page);
anchors.fill: parent
color: "lightblue"
Text {
anchors.centerIn: parent
text: "PAGE 2\nClick to change"
horizontalAlignment: Text.AlignHCenter
}
MouseArea {
anchors.fill: parent
onClicked: {
pageChanged(1);
}
}
}
}
Loader {
id: loader
anchors.fill: parent
sourceComponent: page1
Connections {
target: loader.item
onPageChanged: {
switch(page)
{
case 1: loader.sourceComponent = page1; break;
case 2: loader.sourceComponent = page2; break;
}
}
}
}
}
Is it possible to do something like this:
import QtQuick 2.7
import QtQuick.Window 2.2
Window{
id: root_
visible: true
width: 300
height: 300
Component {
id:compouter
Column{
anchors.fill: parent
Component {
id: compinner
Rectangle {
width:parent.width
height:parent.height/2
}
}
}
}
Component.onCompleted: {
var c = compouter.createObject(this)
//var d = c.compinner.createObject(c, {"color": "green"})
//var e = c.compinner.createObject(c, {"color": "red"})
}
}
That is, I want to create multiple Objects inside the outer object (after the outer object was created). However this isn't possible, as I get the error:
TypeError: Cannot call method 'createObject' of undefined
Is there any workaround for this? Is it maybe only possible to instantiate all inner objects during the instantiation of the outer object?
The ids are out of the scope for your function call.
You can either add a function to your outer component, that creates your objects:
Component {
id:compouter
Column{
anchors.fill: parent
function createCompinner(arg) { compinner.createObject(this, arg) }
Component {
id: compinner
Rectangle {
width:parent.width
height:parent.height/2
}
}
}
}
or you expose the inner Component as a property:
Component {
id:compouter
Column{
property alias compinner: compinnerComponent
anchors.fill: parent
Component {
id: compinnerComponent
Rectangle {
width:parent.width
height:parent.height/2
}
}
}
}
and access it like that.
Ok, I found a workaround through sending a signal to the outter object:
import QtQuick 2.7
import QtQuick.Window 2.2
Window{
id: root_
visible: true
width: 300
height: 300
Component {
id:compouter
Column{
anchors.fill: parent
signal createRect(var color)
onCreateRect: {
compinner.createObject(this, {"color": color})
}
Component {
id: compinner
Rectangle {
width:parent.width
height:parent.height/2
}
}
}
}
Component.onCompleted: {
var c = compouter.createObject(this)
c.createRect("green")
c.createRect("red")
}
It's working, but maybe there is some more generic approach to this (see the accepted answer). As the poster suggested, calling a function would be semantically more clean than sending a signal