Can't remove CandlestickSet from CandlestickSeries - qtcharts

I continued playing with CandlestickSeries and today I was able to insert a CandlestickSet, but was unable to remove it. See "Insert" and "Delete" buttons in the code below:
ColumnLayout
{
spacing: 5
anchors.fill: parent
ChartView {
id: cv
title: "Candlestick series"
theme: ChartView.ChartThemeLight
legend.alignment: Qt.AlignBottom
antialiasing: true
Layout.fillWidth: true
Layout.fillHeight: true
CandlestickSeries {
id: series
name: "Acme Ltd."
increasingColor: "green"
decreasingColor: "red"
CandlestickSet { timestamp: 1435708800000; open: 6.90; high: 6.94; low: 5.99; close: 6.60 }
//CandlestickSet { timestamp: 1435795200000; open: 6.69; high: 6.69; low: 6.69; close: 6.69 }
CandlestickSet { timestamp: 1436140800000; open: 4.85; high: 6.23; low: 4.85; close: 6.00 }
CandlestickSet { timestamp: 1436227200000; open: 5.89; high: 6.15; low: 3.77; close: 5.69 }
//CandlestickSet { timestamp: 1436313600000; open: 4.64; high: 4.64; low: 2.54; close: 2.54 }
}
}
RowLayout
{
Layout.margins: 10
spacing: 5
Button
{
text: "Change 2"
onClicked: series.at(2).open = 3
}
Button
{
text: "Change 4"
onClicked: series.at(4).open = 3
}
Button
{
text: "Insert"
onClicked: {
var set = Qt.createQmlObject('import QtCharts 2.2; CandlestickSet {}', series, "dynamicSnippet1");
set.timestamp = 1435795200000
set.open = 5.69
set.high = 6.69
set.low = 3.54
set.close = 4.54
var ret = series.insert(1, set)
console.log("ret=", ret, set)
}
}
Button
{
text: "Add"
onClicked: {
var set = Qt.createQmlObject('import QtCharts 2.2; CandlestickSet {}', series, "dynamicSnippet1");
set.timestamp = 1436313600000 //1436413600000
set.open = 4.64
set.high = 4.64
set.low = 2.54
set.close = 2.54
var ret = series.append(set)
console.log("ret=", ret, set)
}
}
Button
{
text: "Delete"
onClicked: {
var set = series.at(1)
var ret = series.remove(set)
console.log("ret=", ret, set)
}
}
}
series.remove remove returned false and the chart did not change.
Also, as before, it is not clear how to append a candle.
My QT version is 6.2.

Related

Infinite draggable webgl slider

I'm new to webgl and I'm trying to imrpove this infinite draggable webgl slider:
https://codepen.io/ReGGae/pen/povjKxV
setup() {
const { ww } = store
const state = this.state
const { items, titles } = this.ui
const {
width: wrapWidth,
left: wrapDiff
} = this.el.getBoundingClientRect()
// Set bounding
state.max = -(items[items.length - 1].getBoundingClientRect().right - wrapWidth - wrapDiff)
state.min = 0
// Global timeline
this.tl = gsap.timeline({
paused: true,
defaults: {
duration: 1,
ease: 'linear'
}
})
.fromTo('.js-progress-line-2', {
scaleX: 1
}, {
scaleX: 0,
duration: 0.5,
ease: 'power3'
}, 0)
.fromTo('.js-titles', {
yPercent: 0
}, {
yPercent: -(100 - (100 / titles.length)),
}, 0)
.fromTo('.js-progress-line', {
scaleX: 0
}, {
scaleX: 1
}, 0)
// Cache stuff
for (let i = 0; i < items.length; i++) {
const el = items[i]
const { left, right, width } = el.getBoundingClientRect()
// Create webgl plane
const plane = new Plane()
plane.init(el)
// Timeline that plays when visible
const tl = gsap.timeline({ paused: true })
.fromTo(plane.mat.uniforms.uScale, {
value: 0.65
}, {
value: 1,
duration: 1,
ease: 'linear'
})
// Push to cache
this.items.push({
el, plane,
left, right, width,
min: left < ww ? (ww * 0.775) : -(ww * 0.225 - wrapWidth * 0.2),
max: left > ww ? state.max - (ww * 0.775) : state.max + (ww * 0.225 - wrapWidth * 0.2),
tl,
out: false
})
}
}
What I would like to be able to do is to perfectly loop the words with the slides. Now when dragging it fast the words don't match the pictures (currently there is one more word than the images as workaround).
Plus I would like to find a way to place links on the draggable images.
I would be very grateful for any advice.

'init(destination:isActive:label:)' was deprecated in iOS 16.0: use NavigationLink(value:label:) inside a NavigationStack or NavigationSplitView

I have tried different iterations of examples posted on this site but nothing is going right.
I have also tried following the examples listed here:
Navigation to new navigation types:
I am getting the warning in this posts' title for deprecation of NavigationLink(destination:isActive)
struct PhoneLogin: View {
#StateObject var phoneLoginData = PhoneLoginViewModel()
#State var isSmall = UIScreen.main.bounds.height < 750
var body: some View {
VStack {
VStack {
Text("Continue With Phone")
.font(.title2)
.fontWeight(.bold)
.foregroundColor(.black)
.padding()
Image("phone_logo")
.resizable()
.aspectRatio(contentMode: .fit)
.padding()
Text("You'll receive a 4-digit code \n to verify next")
.font(isSmall ? .none : .title2)
.foregroundColor(.gray)
.multilineTextAlignment(.center)
.padding()
// Mobile Number Field . . . . .
HStack {
VStack(alignment: .leading, spacing: 6) {
Text("Enter Your Number")
.font(.caption)
.foregroundColor(.gray)
Text("+ \(phoneLoginData.getCountryCode()) \(phoneLoginData.phNo)")
.font(.title2)
.fontWeight(.bold)
.foregroundColor(.black)
}
Spacer(minLength: 0)
NavigationLink(
destination: Verification(phoneLoginData: phoneLoginData), isActive: $phoneLoginData.goToVerify) {
Text("")
.hidden()
}
Button(action: phoneLoginData.sendCode, label: {
Text("Continue")
.foregroundColor(.black)
.padding(.vertical, 18)
.padding(.horizontal, 38)
.background(Color.yellow)
.cornerRadius(15)
})
.disabled(phoneLoginData.phNo == "" ? true : false)
}
.padding()
.background(Color.white)
.cornerRadius(20)
.shadow(color: Color.black.opacity(0.1), radius: 5, x: 0, y: -5)
}
.frame(height: UIScreen.main.bounds.height / 1.8)
.background(Color.white)
.cornerRadius(20)
// Custom Number Pad
CustomNumberPad(value: $phoneLoginData.phNo, isVerify: false)
}
.background(Color("bg").ignoresSafeArea(.all, edges: .bottom))
}
}
I finally figured it out:
REPLACED:
NavigationLink(
destination: Verification(phoneLoginData: phoneLoginData),
isActive: $phoneLoginData.goToVerify) {
Text("")
.hidden()
}
WITH:
Making sure the below code is placed anywhere inside a NavigationStack (ios 16):
.navigationDestination(
isPresented: $phoneLoginData.goToVerify) {
Verification(phoneLoginData: phoneLoginData)
Text("")
.hidden()
}

SwiftUI Images disappearing when in NavigationLink

I am trying out SwiftUI and I am building a holiday app in which you can see where have you been what was the weather like there and how long did you stay there.
The problem is that when I put my HolidayCard in NavigationLink all images disappear.
This is the code and the preview with navigation link
struct ContentView: View {
var body: some View {
NavigationView {
ScrollView {
ForEach(holidayData, id: \.id) { holiday in
NavigationLink(destination: HolidayDetails(holiday: holiday)) {
HolidayCard(holiday: holiday)
}
}
}
.navigationBarTitle(Text("My holidays"), displayMode: .large)
}
}
}
This is my HolidayCard and how should it look like
var body: some View {
HStack {
VStack(alignment: .leading, spacing: 12) {
Spacer()
holiday.weatherImage
.resizable()
.frame(width: 48, height: 48)
VStack(alignment: .leading, spacing: 0) {
Text("\(holiday.city),")
.font(.headline)
.fontWeight(.bold)
Text(holiday.country)
.font(.subheadline)
}
Text("\(holiday.season.rawValue) · \(holiday.duration) days")
.font(.headline)
.fontWeight(.light)
}
.foregroundColor(Color.white)
.padding()
.background(Color.black.opacity(0.5))
Spacer()
}
.frame(width: UIScreen.main.bounds.width - 20, height: 200)
.background(
holiday.cityImage
.resizable()
.aspectRatio(contentMode: .fill)
)
.cornerRadius(10)
.padding(10)
.padding(.top, 30)
.shadow(color: Color.gray, radius: 6, x: 3, y: 6)
}
HolidayDetails
struct HolidayDetails: View {
var holiday: Holiday
#State var moreDescription = false
var body: some View {
ScrollView {
VStack {
ZStack(alignment: .bottomLeading) {
holiday.cityImage
.resizable()
.frame(height: moreDescription ? UIScreen.main.bounds.height * 0.3 : UIScreen.main.bounds.height * 0.6)
.aspectRatio(contentMode: .fill)
.frame(width: UIScreen.main.bounds.width)
.animation(.easeInOut)
HStack {
VStack(alignment: .leading, spacing: 12) {
holiday.weatherImage
.resizable()
.frame(width: 64, height: 64)
VStack(alignment: .leading, spacing: 0) {
Text("\(holiday.city),")
.font(.largeTitle)
.fontWeight(.bold)
Text(holiday.country)
.font(.title)
}
Text("\(holiday.season.rawValue) · \(holiday.duration) days")
.font(.headline)
.fontWeight(.light)
}
.foregroundColor(Color.white)
.animation(.easeInOut)
.padding()
}
}
VStack(alignment: .center, spacing: 12) {
Text(holiday.description)
.font(moreDescription ? .subheadline : .caption)
.lineLimit(moreDescription ? 99 : 2)
.opacity(moreDescription ? 1 : 0.5)
.animation(.easeInOut)
.padding()
Button(action: {
withAnimation(.easeInOut(duration: 3)) {
self.moreDescription.toggle()
}
}) {
Text(moreDescription ? "Less.." : "More..")
.font(.caption)
.padding(.vertical, moreDescription ? 10 : 5)
.padding(.horizontal, moreDescription ? 30 : 15)
.background(Color.blue)
.foregroundColor(Color.white)
.animation(.easeInOut)
}
.cornerRadius(10)
}
Spacer()
}
}
}
}
Holiday model
import Foundation
import SwiftUI
struct Holiday: Hashable, Codable, Identifiable {
var id: Int
var city: String
var country: String
var description: String
var duration: Int
var weather: Weather
var season: Season
}
extension Holiday {
var weatherImage: Image {
Image("\(self.weather)")
}
var cityImage: Image {
Image(self.city
.replacingOccurrences(of: " ", with: "")
.lowercased())
}
}
enum Weather: String, CaseIterable, Hashable, Codable {
case cloudy = "cloudy"
case rainy = "rainy"
case snowy = "snowy"
case sunny = "sunny"
}
enum Season: String, CaseIterable, Hashable, Codable {
case summer = "Summer"
case winter = "Winter"
case spring = "Spring"
case autumn = "Autumn"
}
And this is how I get holiday populated
import Foundation
let holidayData: [Holiday] = load("holidayData.json")
func load<T: Decodable>(_ filename: String, as type: T.Type = T.self) -> T {
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \(filename) in main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}
Without the Navigation link the background image and the weather image are visible.
Try to put .renderingMode(.original) in your Image
Try to add this parameter to your NaviguationLink or Button
.buttonStyle(PlainButtonStyle())

How to animate tabbar items (on selection) in SwiftUI?

How can I animate Tabbar Items (of a TabView) on selection in SwiftUI?
for example give the selected item a .scaleEffect() with .spring() animation
or sth like below:
This is what I've tried so far:
struct MyTabbedView: View {
#State var enlargeIt1 = false
#State var enlargeIt2 = true
var body: some View {
TabView {
Text("Item 1")
.onAppear {
self.enlargeIt1.toggle()
self.enlargeIt2.toggle()
}
.tabItem{
VStack{
Image(systemName: "music.note")
.font(self.enlargeIt1 ? .system(size: 30) : .system(size: 15) )
.animation(.interpolatingSpring(mass: 0.7, stiffness: 200, damping: 10, initialVelocity: 4))
Text("Music")
}
}.tag(1)
Text("Item 2")
.onAppear {
self.enlargeIt1.toggle()
self.enlargeIt2.toggle()
}
.tabItem{
VStack{
Image(systemName: "music.mic")
.font(self.enlargeIt2 ? .system(size: 30) : .system(size: 15) )
.animation(.interpolatingSpring(mass: 0.7, stiffness: 200, damping: 10, initialVelocity: 4))
Text("Mic")
}
}.tag(2)
}
}
}
and the result is this:
I tried approximately the same code in a separate View called TestView :
struct TestView: View {
#State var enlargeIt1 : Bool = false
var body: some View {
VStack{
Image(systemName: "music.note")
.font(self.enlargeIt1 ? .system(size: 30) : .system(size: 15) )
.animation(.interpolatingSpring(mass: 0.7, stiffness: 200, damping: 10, initialVelocity: 4))
Text("Music")
}
.onTapGesture {
self.enlargeIt1.toggle()
}
}
}
and this is the result:
What's wrong with the TabView I've created that it's not giving the same result?
Here is possible approach for standard TabView (for provided code snapshot).
The idea is to use animatable modifier for font size over used SF images.
Tested with Xcode 11.4 / iOS 13.4
// Animating font size
struct AnimatableSFImage: AnimatableModifier {
var size: CGFloat
var animatableData: CGFloat {
get { size }
set { size = newValue }
}
func body(content: Self.Content) -> some View {
content
.font(.system(size: size))
}
}
// helper extension
extension Image {
func animatingSF(size: CGFloat) -> some View {
self.modifier(AnimatableSFImage(size: size))
}
}
// Modified test code snapshot
struct TestAnimatedTabBar: View {
#State var enlargeIt1 = false
#State var enlargeIt2 = true
var body: some View {
TabView {
Text("Item 1")
.onAppear {
self.enlargeIt1.toggle()
self.enlargeIt2.toggle()
}
.tabItem{
VStack{
Image(systemName: "music.note")
.animatingSF(size: self.enlargeIt1 ? 30 : 15 )
Text("Music")
}.animation(.interpolatingSpring(mass: 0.7,
stiffness: 200, damping: 10, initialVelocity: 4))
}.tag(1)
Text("Item 2")
.onAppear {
self.enlargeIt1.toggle()
self.enlargeIt2.toggle()
}
.tabItem{
VStack{
Image(systemName: "music.mic")
.animatingSF(size: self.enlargeIt2 ? 30 : 15 )
Text("Mic")
}.animation(.interpolatingSpring(mass: 0.7,
stiffness: 200, damping: 10, initialVelocity: 4))
}.tag(2)
}
}
}
Someone created a custom TabView that might be of help to you. I'm sure you could modify it to suit your needs.
BottomBar component for SwiftUI inspired by this concept
https://github.com/smartvipere75/bottombar-swiftui
import SwiftUI
import BottomBar_SwiftUI
let items: [BottomBarItem] = [
BottomBarItem(icon: "house.fill", title: "Home", color: .purple),
BottomBarItem(icon: "heart", title: "Likes", color: .pink),
BottomBarItem(icon: "magnifyingglass", title: "Search", color: .orange),
BottomBarItem(icon: "person.fill", title: "Profile", color: .blue)
]
struct BasicView: View {
let item: BottomBarItem
var detailText: String {
"\(item.title) Detail"
}
var followButton: some View {
Button(action: openTwitter) {
VStack {
Text("Developed by Bezhan Odinaev")
.font(.headline)
.color(item.color)
Text("#smartvipere75")
.font(.subheadline)
.foregroundColor(.gray)
}
}
}
var destination: some View {
Text(detailText)
.navigationBarTitle(Text(detailText))
}
var navigateButton: some View {
NavigationLink(destination: destination) {
ZStack {
Rectangle()
.fill(item.color)
.cornerRadius(8)
.frame(height: 52)
.padding(.horizontal)
Text("Navigate")
.font(.headline)
.foregroundColor(.white)
}
}
}
func openTwitter() {
guard let url = URL(string: "https://twitter.com/smartvipere75") else {
return
}
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
var body: some View {
VStack {
Spacer()
followButton
Spacer()
navigateButton
}
}
}
struct ContentView : View {
#State private var selectedIndex: Int = 0
var selectedItem: BottomBarItem {
items[selectedIndex]
}
var body: some View {
NavigationView {
VStack {
BasicView(item: selectedItem)
.navigationBarTitle(Text(selectedItem.title))
BottomBar(selectedIndex: $selectedIndex, items: items)
}
}
}
}

Creating draggable dynamic items

I have a menu with grouped components (qtreeview). I want to drag them into another treeview.
The treeview
TreeView {
id: menuView
Layout.minimumWidth: 50
Layout.fillHeight: true
rowDelegate: Item {
height: 30
}
height: parent.height
property int dragItemIndex: -1
itemDelegate: dndDelegate
model: myModel
onCurrentIndexChanged: console.log("current index", currentIndex)
TableViewColumn {
title: "Name"
resizable: false
}
}
/*Delegate for displaying treeview item*/
Component {
id: dndDelegate
Item {
DraggableArea{}
}
}
/*Draggable area*/
MouseArea {
id:mouseArea
onPressed: Code.startDrag(mouse);
onPositionChanged: Code.continueDrag(mouse);
onReleased: Code.endDrag(mouse)
anchors { left: parent.left; right: parent.right }
height: dragRect.height
width:dragRect.width
drag.target: dragRect
Rectangle {
id: dragRect
Image {
id: menuItemImage
anchors.leftMargin: 5
anchors.left:parent.left // set anchor to be able to set margin
anchors.verticalCenter:parent.verticalCenter
source:model ? model.CommandIcon:""
}
Text {
anchors.left:menuItemImage.right
anchors.verticalCenter:parent.verticalCenter
text:model ? model.CommandTitle:""
anchors.leftMargin: 5
font.pixelSize: 14
}
width: menuView.width - 50
color: "red"
border.color: "black"
border.width: 2
radius: 4
height: 27
}
}
and the javascript code to drag by copying the items
var itemComponent = null;
var draggedItem = null;
var startingMouse;
var posnInWindow;
function startDrag(mouse)
{
posnInWindow = dragRect.mapToItem(root, 0, 0);
console.debug("posnInWindow: "+ posnInWindow.x + " " + posnInWindow.y);
startingMouse = { x: mouse.x, y: mouse.y }
console.debug("startingMouse: "+ startingMouse.x + " " + startingMouse.y);
loadComponent();
}
//Creation is split into two functions due to an asynchronous wait while
//possible external files are loaded.
function loadComponent() {
if (itemComponent != null) { // component has been previously loaded
createItem();
return;
}
itemComponent = Qt.createComponent("../DraggableArea.qml");
if (itemComponent.status == Component.Loading) //Depending on the content, it can be ready or error immediately
component.statusChanged.connect(createItem);
else
createItem();
}
function createItem() {
if (itemComponent.status == Component.Ready && draggedItem == null) {
draggedItem = itemComponent.createObject(root, {"x": 40,
"y": posnInWindow.y});
draggedItem.anchors.left = undefined;
draggedItem.anchors.right = undefined;
console.debug("draggedItem created: "+ draggedItem.x + " " + draggedItem.y);
// make sure created item is above the ground layer
}
else if (itemComponent.status == Component.Error) {
draggedItem = null;
console.log("error creating component");
console.log(itemComponent.errorString());
}
}
function continueDrag(mouse)
{
if (draggedItem == null)
return;
draggedItem.x = mouse.x + posnInWindow.x - startingMouse.x;
draggedItem.y = mouse.y + posnInWindow.y - startingMouse.y;
//console.debug("mouse: "+ mouse.x + " " + mouse.y);
//console.debug("posnInWindow: "+ posnInWindow.x + " " + posnInWindow.y);
//console.debug("startingMouse: "+ startingMouse.x + " " + startingMouse.y);
//console.debug("draggedItem: "+ draggedItem.x + " " + draggedItem.y);
}
function endDrag(mouse)
{
draggedItem.destroy();
draggedItem = null;
}
The problem is that these dynamically created items aren't perceived as draggable (I just emulate dragging changing coordinates in JS). How to do it right, like it works in QTreeView approach? Setting drag.target for newly created object doesn't seem to work (get an exception)