Archief - Flex + Sqlite data

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

ZackWhite

Legacy Member
Hallo

Ben bezig aan een klein project in Flex om mijn trainingen van het zwemmen in op te slaan. Dus Datum, soort van training, aantal kilometer,...

Nu zit ik zover dat ik al mijn data kan opslaan in een database (sqlite) en deze kan weergeven in een datagrid. De volgende stap zou zijn dat als ik op 1 van de trainingen in het datagrid klik, ik de details zie van wat er op die training nu juist gedaan is. Alsook zou ik een aantal statistieken willen tonen die gewoon totalen vormen van de gehele database.

Maar daar loopt het een beetje vast. Om het even simpel te houden zodat ik erna op mijn eigen verder kan:

Hoe kan ik in een 'label' het totaal aantal kilometer weergeven van al mijn trainingen samen.

Sql statement is normaal dit:
Code:
sqls.text = "SELECT SUM(totaal) FROM trainingenTable"

maar hoe kan ik het resultaat nu weergeven in dat label?

mvg

Zero Grav

Legacy Member
Voer die query gewoon uit? Ik zie niet bepaald waar ge vastzit aangezien ge nog niets geprobeerd hebt. Doe een execute op uw sql statement en bekijk dan uw SQLResult object voor de data die ge nodig hebt.

ZackWhite

Legacy Member
Ok, ik heb momenteel dit (uitgezonderd de code voor de database aan te maken want die werkt volledig):

Code:
private var selectData:SQLStatement = new SQLStatement;
private function test():void{
	selectData.sqlConnection = sqlc;
	selectData.text = "SELECT totaal FROM trainingenTable WHERE id=3";
	selectData.addEventListener(SQLEvent.RESULT, resultHandler); 
	selectData.execute();
}
private function resultHandler(event:SQLEvent):void 
{
	var result:SQLResult = selectData.getResult();
	trace(result);
}

Als resultaat van de trace krijg ik [Object SQLResult], terwijl het in dit geval '1.1' zou moeten zijn. Errors krijg ik niet.

het type van de kolom totaal = DECIMAL indien het er iets mee zou te maken hebben.

ZackWhite

Legacy Member
daar raak ik niet echt aan uit. als ik het volgende doe in mijn trace:
Code:
trace(ObjectUtil.toString(result));


krijg ik:
(flash.data::SQLResult)#0
complete = true
data = (Array)#1
[0] (Object)#2
totaal = 1.1
lastInsertRowID = 0
rowsAffected = 0

Dus dan zit de waarde er toch in veronderstel ik. Maar hoe krijg ik die nu weergegeven in een textfield of een label? (Sorry maar ik heb in flex nog nooit met databases gewerkt)

Zero Grav

Legacy Member
Het databasegedeelte daar zijt ge al vanaf feitelijk, nu zit ge maar gewoon met objecten in Flash te werken. Soit, zal u wat op het spoor zetten.

Zoals te lezen in de documentatie bevat het SQLResult object bij een succesvolle SELECT een array met alle opgehaalde rijen. Waarvan elke rij een object is met als properties de kolommen van uw tabel.

Dus result is een object met daarin een Array variabele (data) waarin elk item een object is met uw geselecteerde waardes uit de database die ge kunt aanspreken via de naam van de kolom. Daarna is het maar textField.text = data[0].kolomNaam;

ZackWhite

Legacy Member
thx, zit al een stap verder!

dit geeft het gewenste resultaat:
Code:
var row:Object = result.data[0];
tester.text = row.totaal;

Nu wou ik dezelfde code behouden, alleen gebruik ik als SQLstatement:
Code:
SELECT SUM(totaal) FROM trainingenTable
Dus gewoon de som van alle rijen in mijn database uit de kolom 'totaal'. Maar dit wilt hij dan weer niet tonen (textfield wordt gewoon leeggemaakt), terwijl ik via de trace wel het resultaat te zien krijg. Moet hiervoor nog iets speciaal gebeuren?

EDIT: Heb het gevonden, moest de 'SUM kolom' een naam geven en deze aanspreken door row.naam.

Danku voor de hulp! :)

ZackWhite

Legacy Member
Toch nog 1 klein vraagje, hoe zorg ik ervoor dat die functie bij het opstarten direct start? Alle, niet direct, nadat de database is geopend eigenlijk als ik mij niet vergis. Maar als ik ze daarachter zet dan krijg ik een error.

Momenteel is de enigste oplossing dat ik gevonden heb om ze uit te voeren met een button maar dat is niet echt de bedoeling :s

Dit is de eerste functie die uitgevoerd wordt bij het opstarten:
Code:
private function start():void
{
	var db:File = File.applicationStorageDirectory.resolvePath("test.db");
	sqlc.openAsync(db);
	sqlc.addEventListener(SQLEvent.OPEN, db_opened);
	sqlc.addEventListener(SQLErrorEvent.ERROR, error);
	sqls.addEventListener(SQLErrorEvent.ERROR, error);
	sqls.addEventListener(SQLEvent.RESULT, result);	
}

als ik hier een eventListener aan toevoeg, namelijk:
Code:
sqls.addEventListener(SQLEvent.RESULT, fillStatistics);
die verwijst naar dit:
Code:
private var selectData:SQLStatement = new SQLStatement;
private function fillStatistics(e:SQLEvent):void
{
	selectData.sqlConnection = sqlc;
	selectData.text = "SELECT SUM(totaal) as test FROM trainingenTable";
	selectData.addEventListener(SQLEvent.RESULT, resultHandler); 
	selectData.execute();
	trace(selectData);
}

private function resultHandler(event:SQLEvent):void 
{
	var result:SQLResult = selectData.getResult();
	trace(ObjectUtil.toString(result));
	var row:Object = result.data[0];
	tester.text = row.test;
	refresh();
}
krijg ik een error:
Error #1009: Cannot access a property or method of a null object reference.

:help:

Zero Grav

Legacy Member
Een null object reference betekent dat ge verwijst naar een object dat nog niet geïnitialiseerd is, waarvan de waarde nog null is dus.

Ge kunt het creationComplete event gebruiken van uw component om die start functie automatisch uit te laten voeren.

In die code zie ik nu niet onmiddellijk een null reference, of het zou sqlc moeten zijn. Feitelijk kunt ge dan best breakpoints zetten en kijken welk object null is terwijl het ingevuld zou moeten zijn.

't Kan ook zijn dat uw tester tekstveld nog niet bestaat als ge die functie te vroeg laat uitvoeren natuurlijk. Maar op het creationComplete event zou dat geen probleem moeten zijn als ge met mxml werkt.

ZackWhite

Legacy Member
k, ik heb het probleem gevonden denk ik. Ik werk met zo een accordeon en mijn textfield staat in de 2de 'viewstate'. Blijkbaar wordt die nog niet aangemaakt op het moment dat de code uitgevoerd wordt?

Nu heb ik mijn textfield naar de eerste viewstate verplaatst en werkt het wel. Is ook de bedoeling dat hij daar staat dus het is niet echt een probleem meer hoewel ik wel graag zou willen weten waarom die op de 2de viewstate niet werkt. :s

Zero Grav

Legacy Member
Ja, als ge werkt met includeIn dan gaat em dat tekstveld alleen maar aanmaken van het moment dat die state actief wordt. Dus als ge het probeert aan te spreken als een andere state actief is gaat ge inderdaad een null reference krijgen.

Ge kunt in plaats van includeIn werken met visible.stateName = false|true; afhankelijk van de groep waarin ge het wilt zien en verbergen.
Ge kunt ook aan dat textvak de property itemCreationPolicy toevoegen met als waarde immediate. Dan wordt het tekstvak aangemaakt bij het creëren van de applicatie, ongeacht de state.

Of ge kunt bij het switchen van de state kijken in welke state ge zit, kijken of die startfunctie al is uitgevoerd door middel van een Boolean of gewoon kijken of de nodige vars al zijn ingevuld en aan de hand daarvan die start functie uitvoeren.

ZackWhite

Legacy Member
Toch nog een klein vraagje, ik zit met mijn volgende code met een infinite loop. Het gedeelte waar men trace('test') staat blijft constant doorgaan, maar ik vind echt niet hoe ik die kan laten stoppen.

return; heb ik geprobeerd maar zonder succes.

De functie start() is degene die aangeroepen wordt wanneer het programma opstart.

Code:
private var sqlc:SQLConnection = new SQLConnection();
private var sqls:SQLStatement = new SQLStatement();
[Bindable]
private var dp:ArrayCollection = new ArrayCollection();

private function start():void
{	
	var db:File = File.applicationStorageDirectory.resolvePath("test.db");
	sqlc.openAsync(db);
	sqlc.addEventListener(SQLEvent.OPEN, db_opened);
	sqlc.addEventListener(SQLErrorEvent.ERROR, error);
	sqls.addEventListener(SQLErrorEvent.ERROR, error);
	sqls.addEventListener(SQLEvent.RESULT, result);		
}

private function db_opened(e:SQLEvent):void
{
	
	sqls.addEventListener(SQLEvent.RESULT, fillTotKm);
	sqls.sqlConnection = sqlc;
	sqls.text = "CREATE TABLE IF NOT EXISTS trainingenTable ( id INTEGER PRIMARY KEY AUTOINCREMENT, datum VARCHAR, type TEXT, totaalGed DECIMAL, totaalTeDoen DECIMAL, rec_km DECIMAL, reg_km DECIMAL, wc_km DECIMAL, wv_km DECIMAL, uc_km DECIMAL, uv_km DECIMAL, benen_km DECIMAL);";
	sqls.execute();
	refresh();
}

private var selectTotKm:SQLStatement = new SQLStatement;
private function fillTotKm(e:SQLEvent):void
{
	selectTotKm.sqlConnection = sqlc;
	selectTotKm.parameters["@datum1"] = datumBegin.text;
	selectTotKm.parameters["@datum2"] = datumEind.text;
	selectTotKm.text = "SELECT SUM(totaalTeDoen) as totKm FROM trainingenTable WHERE datum BETWEEN @datum1 AND @datum2";
	selectTotKm.addEventListener(SQLEvent.RESULT, berekenTotKm); 
	trace("test");
	selectTotKm.execute();
}

private function berekenTotKm(event:SQLEvent):void 
{
	var result:SQLResult = selectTotKm.getResult();
	var row:Object = result.data[0];
	aantalKilometer_Tel.text = row.totKm + " km";
	trace("test2");
}

private function refresh(e:TimerEvent = null):void
{
	var timer:Timer = new Timer(10,1);
	timer.addEventListener(TimerEvent.TIMER, refresh);
	
	if ( !sqls.executing )
	{
		sqls.text = "SELECT * FROM trainingenTable"
		sqls.execute();
	}
	else
	{
		timer.start();
	}
}

Zero Grav

Legacy Member
De fout zit wellicht in uw refresh functie, maar kan het niet met zekerheid zeggen omdat ge ook nergens uw eventListeners verwijdert.

in uw fillTotKm functie zou ik dus al beginnen met die eventListener te clearen van uw SQLEvent.RESULT, dan gaat em die sowieso niet meer opvangen. Maar het gaat al fout bij het feit dat em em meer dan eens afvuurt, en daarvoor zou ik dus eens kijken naar uw refresh functie.

Wat wellicht zal helpen is als ge uw timer globaal zet en em dan in uw if clause van refresh gaat stoppen, de eventListener ervan verwijdert en op null zet. In uw else clause kunt ge dan kijken of timer null is of niet, indien null maakt ge em aan en anders doet ge niets.

ZackWhite

Legacy Member
Uw hulp is ten zeerste geapprecieerd! Heb het gevonden dankzij je info.

Volgende stap is alle data in een grafiek gooien maar dat probeer ik zelf wel eerst natuurlijk! :)
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan