I'm building a flutter app for windows. I've made a screen where a list of programmaticly generated Radio Widgets (about 40 radiogroups with 2 or 3 radio widgets in each group) is shown. Everything works when clicked. The value is updated, yet the radiobuttons do not change it's appearance (it does not show it's selected), this is until I scroll the radiogroup out of sight and scroll it back into sight (probably because it is rebuilt at that moment).
Any hints?
---update
Sorry for not posting any code at first, the problem I've described did not seem the kind of problem that would need so.
There are many issues and solutions on here that go on about refreshing
So far this is the one that makes it work.
setState(() {
FutureToBeRefreshed = functionToGetData;
}
There's only one drawback. After setState, the whole screen gets refreshed and starts at the first position, which is annoying when you changed the value of a radiobutton which is offscreen at the beginning.
I'm not that experienced (let's say I've just started with flutter) and any solutions involving scrollControllers and .jumpTo the scrollposition I could not get to work.
For now, I've came up with a solution that involves paging so that there are no elements outside the visible Viewport. Yet if there's a different solution other than paging, please let me know.
#override
initState() {
super.initState();
Size size = WidgetsBinding.instance.window.physicalSize;
screenWidth = size.width;
screenHeight = size.height;
pageIndex = 0;
headerHeight = 330;
lineHeight = 70;
if (screenHeight == null || screenHeight < (headerHeight + 2*lineHeight) ) {
screenHeight = (headerHeight + 2*lineHeight);
}
double tmpCalc = (screenHeight - headerHeight ) / lineHeight ;
maxLines = tmpCalc.toInt();
datafields = getDataFields();
}
There is no need for paging if you use a ListView instead of a Viewport.
About the refresh, you should definitely use setState to at least store the selected Radio buttons.
Check this screen recording below of a prototype and the live demo on DartPad. Is this what you're expecting?
Here's the prototype code:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
final groups = [
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2],
[1, 2, 3],
[1, 2, 3],
[1, 2],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2],
[1, 2],
[1, 2],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2],
[1, 2],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2],
[1, 2],
[1, 2],
[1, 2],
[1, 2],
[1, 2],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2],
[1, 2],
[1, 2],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2],
].asMap();
class _MyHomePageState extends State<MyHomePage> {
final selectedRadiosByGroup = <int, int>{};
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Expanded(
child: ListView.separated(
itemCount: groups.length,
separatorBuilder: (context, _) => const Divider(
height: 2,
),
itemBuilder: ((context, groupIndex) {
final group = groups[groupIndex]!;
return Row(
children: [
for (final entry in group)
Row(
children: [
Radio(
value: entry,
groupValue: selectedRadiosByGroup[groupIndex],
onChanged: (value) => setState(
() => selectedRadiosByGroup[groupIndex] = entry),
),
Text('$groupIndex:$entry'),
],
)
],
);
}),
),
),
),
);
}
}
Related
I'm building a particle system in which particles have directions they are pointing at and I want to reflect that in an instance mesh I use to present them, but something is not quite working... It seems that the center of rotation and/or the up axis are not quite right, and despite me console logging stuff I could not find the problem. Here's the code:
const Particles = (particleSystem: TparticleSystem) => {
const mesh = useRef<THREE.InstancedMesh>(null);
const light = useRef<THREE.PointLight>(null);
const dummy = useMemo(() => new THREE.Object3D(), []);
const pyramid = useMemo(() => {
return {
vertices: [1, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, -1, 0, 2, 0],
indices: [0, 1, 2, 2, 3, 0, 0, 4, 1, 1, 4, 2, 2, 4, 3, 3, 4, 0],
};
}, []);
useFrame(() => {
if (particleSystem !== undefined) {
particleSystem.update();
particleSystem.move();
particleSystem.particles.forEach((particle: Tparticle, index: number) => {
dummy.position.set(particle.pos.x, particle.pos.y, particle.pos.z);
dummy.lookAt(vec().copy(particle.pos).add(particle.dir)); // rotating weird
dummy.scale.set(1, 2, 1);
dummy.updateMatrix();
// And apply the matrix to the instanced item
if (mesh.current) mesh.current.setMatrixAt(index, dummy.matrix);
});
if (mesh.current) mesh.current.instanceMatrix.needsUpdate = true;
}
});
return (
<>
<pointLight ref={light} distance={40} intensity={3} color="lightblue" />
{particleSystem !== undefined && (
<instancedMesh ref={mesh} args={[, , particleSystem.num]}>
<polyhedronBufferGeometry
args={[pyramid.vertices, pyramid.indices, 1, 0]}
/>
<meshBasicMaterial
color="#2596be"
wireframe={Math.random() > 0.5 ? true : false}
/>
</instancedMesh>
)}
</>
);
};
I feel like maybe this is something to do with local and world coordinates, but I don't quite understand it.
Oh! and this vec stuff is just
const vec = function (x = 0, y = 0, z = 0) {
return new THREE.Vector3(x, y, z);
};
I am racking my brain trying to get this code working, I am just starting out on SwiftUI and haven't found a solution. I have a math equation that adds the variables and accepts the answer input from the user. My issue is once the answer is correct, how can i get the variables numbers1 & numbers2 to refresh and grab new numbers and give another math problem?
import SwiftUI
import Foundation
struct ContentView: View {
#State private var answer = ""
#State private var number1 = ""
#State private var number2 = ""
#State private var messageText = ""
#State private var keyboardHeight: CGFloat = 0.0
var numbers1 : Int = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].randomElement()!
var numbers2 : Int = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].randomElement()!
var questionNumber = 0
var value = 0.00
var body: some View {
VStack {
ForEach((1...10).reversed(), id: \.self) {_ in
Text(self.number2)
}
Text("\(numbers1)")
.font(.largeTitle)
.padding()
Text("\(numbers2)")
.font(.largeTitle)
.padding()
TextField("answer", text: self.$answer)
.padding(/*#START_MENU_TOKEN#*/.all/*#END_MENU_TOKEN#*/)
.font(/*#START_MENU_TOKEN#*/.largeTitle/*#END_MENU_TOKEN#*/)
//.keyboardType(.numberPad)
Button(action: {
var addition: Int {
let addition = self.numbers1 + self.numbers2
return addition
}
print("submit button pressed")
print(addition)
if (self.answer == String(addition)) {
print("Answer is Correct!")
}
else {
print("Answer is Incorrect")
}
self.answer = ""
}) {
Text("Submit")
.font(.largeTitle)
.padding()
.background(Color.red)
.foregroundColor(.white)
.cornerRadius(40)
}
// .padding()
.actionSheet(isPresented: /*#START_MENU_TOKEN#*/ /*#PLACEHOLDER=Is Presented#*/.constant(false)/*#END_MENU_TOKEN#*/) {
ActionSheet(title: Text(/*#START_MENU_TOKEN#*/ /*#PLACEHOLDER=Title#*/"Action Sheet"/*#END_MENU_TOKEN#*/))
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
```
enter code here
what you can do is this:
declare
#State var numbers1 : Int = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].randomElement()!
#State var numbers2 : Int = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].randomElement()!
and
if (self.answer == String(addition)) {
print("Answer is Correct!")
self.numbers1 = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].randomElement()!
self.numbers2 = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].randomElement()!
}
or some variation of this, like storing the array in a var.
I'm using Plotly.js to draw a 3-D scatter plot . On zoom , I want to check which points are visible . Can this be done on svg level ? or any plotly expert ?
Snippet:
var myPlot = document.getElementById("myDiv");
var trace = {
x: [1, 7, 2, 4,1],
y: [12, 9, 15, 12,2],
z: [1, 2, 4, 8,4],
// x: [1,2],
//y: [12,15],
//z: [1, 4],
mode: 'markers' ,
type: 'scatter3d' ,
marker: {size:5 }
}
var data = [trace];
var layout = {
margin: {
l: 0,
r: 0,
b: 0,
t: 0} ,
//title: {text: 'ReOptim8 Scatter Plot'},
scene: {
yaxis:{title: 'X-axis'},
xaxis:{title: 'y-axis'},
zaxis:{title: 'z-axis'},
camera: {eye: {x:1.25, y:1.25, z:1.25}}
}
};
var config = {
displayModebar : true,
displaylogo: false,
responsive: true
};
Plotly.plot( myPlot, data, layout, config );
Code pen link below :
https://codepen.io/aniwar/pen/wLOzZv
I have a handontable demo.
document.addEventListener("DOMContentLoaded", function() {
var
example = document.getElementById('example1'),
hot1;
hot1 = new Handsontable(example, {
data: [
['', '', '', ''],
[1, 2, 3, '=SUM(A2:C2)'],
[1, 2, 3],
],
width: 584,
height: 320,
rowHeaders: true,
formulas: true,
colHeaders: true,
columns: [1, 2, 3, 4],
columnSummary: function () {
var summary = [];
for (var i = 0; i < 4; i++) {
summary.push({
ranges: [[1, 2]],
destinationRow: 0,
destinationColumn: i,
type: 'sum',
forceNumeric: true,
sourceColumn: i
});
}
return summary;
}
});
});
It caclulates:
Sum of column and puts a result in the first raw.
Sum of rows (except first one) and puts it in the column "D"
I need to calculate correct total of the totals, which is the cell D1.
After loading and changing any cell calculation of D1 has to work properly.
Thank you for any ideas.
The option columnSummary should not be applied on the 4th column (the column of SUM results). Try to apply you code of columnSummary option only for the first three columns :
for (var i = 0; i < 3; i++) //Instead of i < 4
And use in the row one what you use to calculate the sum on your other rows :
data: [
['', '', '', '=SUM(A1:C1)'],
[1, 2, 3, '=SUM(A2:C2)'],
[1, 2, 3, '=SUM(A3:C3)'],
],
You will see that it works like a charm : JSFiddle.
example:
var s1 = Observable.of([1, 2, 3]);
var s2 = Observable.of([4, 5, 6]);
s1.merge(s2).subscribe(val => {
console.log(val);
})
I want to get
[1,2,3,4,5,6]
instead of
[1,2,3]
[4,5,6]
forkJoin works wells, you just need to flatten the array of arrays :
const { Observable } = Rx;
const s1$ = Observable.of([1, 2, 3]);
const s2$ = Observable.of([4, 5, 6]);
Observable
.forkJoin(s1$, s2$)
.map(([s1, s2]) => [...s1, ...s2])
.do(console.log)
.subscribe();
Output : [1, 2, 3, 4, 5, 6]
Plunkr to demo : https://plnkr.co/edit/zah5XgErUmFAlMZZEu0k?p=preview
My take is zip and map with Array.prototype.concat():
https://stackblitz.com/edit/rxjs-pkt9wv?embed=1&file=index.ts
import { zip, of } from 'rxjs';
import { map } from 'rxjs/operators';
const s1$ = of([1, 2, 3]);
const s2$ = of([4, 5, 6]);
const s3$ = of([7, 8, 9]);
...
zip(s1$, s2$, s3$, ...)
.pipe(
map(res => [].concat(...res)),
map(res => res.sort())
)
.subscribe(res => console.log(res));
Just instead of Observable.of use Observable.from that takes as argument an array and reemits all its values:
var s1 = Observable.from([1, 2, 3]);
var s2 = Observable.from([4, 5, 6]);
s1.merge(s2).subscribe(val => {
console.log(val);
});
Maybe instead of merge you might want to prefer concat but in this situation with plain arrays it'll give same results.
This will give you:
1
2
3
4
5
6
If you want this as a single array you could append also toArray() operator. Btw, you could achieve the same with Observable.of but you'd have to call it with Observable.of.call(...) which is probably unnecessary complicated and it's easier to use just Observable.from().
Maybe you could do this with List instead of Array:
var s1 = Rx.Observable.of(1, 2, 3);
var s2 = Rx.Observable.of(4, 5, 6);
and then
Rx.Observable.merge(s1,s2).toArray().map(arr=>arr.sort()).suscribe(x=>console.log(x))
The accepted answer from #maxime1992 will now cause deprecation warnings with the current version of RXJS. Here's an updated version:
import { forkJoin, of } from 'rxjs';
import { map } from 'rxjs/operators';
const s1$ = of([1, 2, 3]);
const s2$ = of([4, 5, 6]);
Observable
.forkJoin([s1$, s2$])
.pipe(
.map(([s1, s2]) => [...s1, ...s2])
)
.do(console.log)
.subscribe();