QML Image not updating after source change - c++

I am using Qt Quick 2 and would like a QML image to be updated when the source is change via clicked on the image. But can't get that to happen.
There have been a few similiar questions but those solutions have not brought any joy in my case. Both images are added to the solution and I can set the image to either. Just can't update the image after changing the source.
Thanks in advance
Image {
id : two_player_button
x: 24
y: 105
cache : false
fillMode: Image.PreserveAspectCrop
z: 1
sourceSize.height: 0
sourceSize.width: 0
source: "resources/base/players_2.png"
MouseArea {
anchors.fill: parent
onClicked: {
source: "resources/base/players_2_hl.png"
//two_player_button.update()
}
}
}
I have also tried updating it via the parent.

Found my own mistake finally:
needed to be
two_player_button.source = "resources/base/players_2_hl.png"
Just saying
source = "resources/base/players_2_hl.png"
would also not have worked and sets the parent source.

Related

How to make QFileSystemModel work with a ListView

I am unable to make the QFileSystemModel go along with the ListView. All the examples and documentation that I found would use QFileSystemModel with the TreeView (which works fine), but this is not what I need.
I do not want to use FolderListModel QML type either because I want to add extra roles to my model later and edit/delete files and folders from the application.
I used DelegateModel to be able to set an other root index. For some reason, my files are correctly displayed for a fraction of a second and then the view jumps to the root of my filesystem. I'm not sure what happens, maybe the indexes are invalidated somehow.
Below is a sample of my code:
main.cpp
QFileSystemModel *fsm = new QFileSystemModel(&engine);
fsm->setRootPath(QDir::homePath());
fsm->setResolveSymlinks(true);
engine.rootContext()->setContextProperty("displayFileSystemModel", fsm);
engine.rootContext()->setContextProperty("rootPathIndex", fsm->index(fsm->rootPath()));
fsview.qml
ListView {
width: 300
height: 400
model: DelegateModel {
model: displayFileSystemModel
rootIndex: rootPathIndex
delegate: Rectangle {
width: 200; height: 25
Text {
text: model.filePath
Component.onCompleted: {
console.log(text)
}
}
}
}
}
What am I doing wrong?
UPDATE
So, apparently QFileSystemModel uses a separate thread to populate itself and shoots a directoryLoaded signal once the the thread has finished to load the path.
I tried connecting my view to only set the root index once the path has been properly loaded by adding the following code to my listview
Connections {
target: displayFileSystemModel
function onDirectoryLoaded(path) { delegatemodel.rootIndex = rootPathIndex }
}
However, this does not solve the problem. A dirty workaround was to set a timer to try set the rootIndex after a period of time.
Timer {
interval: 100
running: true
onTriggered: delegatemodel.rootIndex = examPathIndex
}
And this "solves" the problem but of course is far from a satisfactory solution. Any idea?
UPDATE 2
Turns out every time the model is updated (and the directoryLoaded signal is triggered), the view resets. Even trying to reassign the rootIndex every time new data is loaded doesn't work.

QML TableView Model Silently Failing?

edit: added some clarification
Using QML 5.14
It seems the model attribute of TableView does not want to display a QList<int>, or any variation of int, be it qint8, qint32, etc. I can make it work with unsigned QList<uint>, however I need to keep the negative range of values in my application.
I've found that the information is making it to the qml layer, because when i call:
console.log("cfs.amounts is " + cfs.amounts)
console.log("model is " + model)
console.log("modellength is " + model.length)
I actually am getting the expected console output of:
qml: cfs.amounts is 11,12
qml: model is 11,12
qml: modellength is 2
I've ensured the TableView is functional by directly passing it data, i.e. model: [11, 22] and it displays correctly, i.e. it displays the indexes 0, 1. However I can't get it to display anything at all when I pass it the cfs.amounts, which is a QList<int> in c++. So according to the console.log, the model data is there, it is correct, it's getting passed from c++ to qml without issues, and the length is good -- the TableView is just failing to display it.
The only thing I can think of, is that the TableView is silently failing to display arrays of signed integers. However I may also be completely wrong, because I can't get a Repeater item to recognize it in its model, neither. I've searched but I can't find any bug reports on this subject. Does anyone have any suggestion on how to get the qml model to recognize the passed QList<int> ? This is all in QML 5.14.
cashflowschedule.h
#ifndef CASHFLOWSCHEDULE_H
#define CASHFLOWSCHEDULE_H
#include "QObject"
#include "QList"
class CashFlowSchedule : public QObject
{
Q_OBJECT
Q_PROPERTY(QList<int> amounts READ amounts)
public:
CashFlowSchedule() {};
QList<int> amounts() { return {11,12}; }
};
#endif // CASHFLOWSCHEDULE_H
main.qml
import QtQuick 2.14
import QtQuick.Window 2.14
import cpps 1.0
Window {
visible: true
width: 640
height: 480
CashFlowSchedule { id: cfs }
TableView {
anchors.fill: parent
model: cfs.amounts
delegate: Text { text: index }
Component.onCompleted: {
console.log("cfs.amounts is " + cfs.amounts)
console.log("model is " + model)
}
}
}
included in the main.cpp
#include "cashflowschedule.h"
...
qmlRegisterType<CashFlowSchedule>("cpps", 1, 0, "CashFlowSchedule");
...
QList<int> is not one of the official supported C++ types used for models (see the list here). A bug report exists to clarify the documentation on that point. A QVariantList is a good alternative to use.

How add wavefront file(.obj) to surface3d qml?

I wanna add a obj file(wavefront format) as a point(by a position) in surface3d in qml
but i dont know how i do it!
i found some solutions but they have some problems, for example i just want use qml , but they use c++ and QCustomItem .
i tried to use it in sactter3d with new mesh (just training with that) but it couldnt work:
mesh:Abstract3DSeries.MeshUserDefined
userDefinedMesh:Mesh{
source: "wfObj.obj"
}
it was just a training , my main queston is adding waveFront to surface3d qml.
thx for helping .
finally i added my CustomItem in qml.
at first i created a Custom3DItem :
Custom3DItem
{
id:c3i
meshFile: qsTr(":/Items/oilrig.obj")
position: Qt.vector3d(35,150,35)
textureFile: qsTr(":/Items/redPng.png")
visible: true
scaling: Qt.vector3d( 0.25 , 0.25 , 0.25 )
}
then i wanted add it to my Surface3d(id:mySurface) , for doing it i needed add it by a method ,so i used an Item and component.onCompleted:
Component.onCompleted: mySurface.addCustomItem(c3i);

displaying image in a toolbar in swift 3

i am trying to create a toolbar with buttons. and the button i want to have is an image rather title. The current non working code is:
let imageName = "yourImage.png"
self.myUIBarButtonBack = UIBarButtonItem(image: UIImage(named: imageName), style:.plain, target: self, action: #selector(onClickBarButton))
I have 2 questions:
1. where should i place the yourImage.png in my application
2. is this code sufficient to render image or i need to do things like putting it into imageView component and make it visible etc. ?
The best approach is to add images in xcassets. This is the best way you can organize images. The concept of App slicing applies here.
You don't need to put the image in image view in the case of bar button item.
Try changing the rendring option as Original Image instead of Default.
One way is create custom button and assign to toolbar like navigationbar
self.navigationItem.hidesBackButton = true
let button = UIButton.init(type: .custom)
button.setImage(UIImage.init(named: "back_icon"), for: UIControlState.normal)
button.addTarget(self, action:#selector(onClickBackBarItem), for: UIControlEvents.touchUpInside)
button.frame = CGRect.init(x: 0, y: 0, width: 25, height: 25)
let barButton = UIBarButtonItem.init(customView: button)
self.navigationItem.leftBarButtonItem = barButton

QML text scroll

I am using C++ and QML to create a nice interface.
I would like to have a "console view", where plenty to text is printed through time.
However, when the text of a text item or webview content grows, the view does not "scroll down".
How can I make the text on the bottom of the text/webview item always stay visible ?
I have tried playing with flickable and the_webview.evaluateJavaScript + window.scrollTo , but I could not get them to do what I want.
This seems a fairly simple piece of UI, but I am having serious troubles to do it with QML.
Thanks for you answer.
Yeah I'd use a Flickable containing a Text object. Whenever you add text to the Text, check its paintedHeight, and adjust the Flickable's contentY if it's got any bigger.
Maybe you should consider using a ListView and have the messages as items in the view. Then you could use ListView::positionViewAtEnd.
funkybro answers inspired my final solution:
function scroll_to_bottom() {
flickabe_item.contentY =
Math.max(0, webview_item.height - flickabe_item.height);
return;
}
Thanks !
My solution to this was to vertically flip both the content and Flickable. This way the text ends the right way up and is naturally anchored to the bottom of the flickable area.
It might be more efficient too since the transform is handled by OpenGL behind the scenes.
Flickable {
id: flick
anchors.fill: parent
contentHeight: text.height
Text {
id: text
width: parent.width
transform: Scale { yScale: -1; origin.y: text.height/2 }
}
transform: Scale { yScale: -1; origin.y: flick.height/2 }
}