javafx 1.3 listview - javafx

I want to display data from database. There is no TableView in javaFx 1.3 so I used ListView. But, when I put textbox in the listview, it does not perform well. I get problems in fetching data. Can anyone give me a code for listview with a textbox in it and it also fetches and updates data.

var lv_dept_nm:String = "";
var lv_dept_des:String = "";
var lv_dept_name:TextBox;
var lv_dept_desc:TextBox;
var lv_dept_upBtn: Button;
var lv_dept_flag:Boolean = false;
var lv_dept_ind: Integer;
var lv_dept_len: Integer = 0;
var lv_dept_size:Integer = 0;
function removeLastChar(str: String)
{
var string;
if(str != "")
{
string = str.substring(0, str.length()-1);
}
else
{
string = str;
}
return string;
}
var viewDepartmentListView: ListView = ListView
{
items: bind [dept_choicebox_item]
layoutInfo: LayoutInfo{height:bind lv_dept_size}
layoutX: 170
layoutY: 150
width: 500
cellFactory: function() {
var listCell: ListCell;
if(dept_choicebox_item.size() > 5)
{
lv_dept_size = 55 * 5;
}
else
{
lv_dept_size = 55 * dept_choicebox_item.size();
}
listCell = ListCell {
node : HBox {
width: 200
content: [
VBox {
spacing: 10
content: [
Label {
text: bind dept_choicebox_item[listCell.index]
visible: bind not listCell.empty and not lv_dept_flag or not listCell.selected or (lv_dept_ind != listCell.index)
}
lv_dept_name = TextBox
{
promptText: bind dept_choicebox_item[listCell.index]
onKeyPressed: function(ke: KeyEvent)
{
if(ke.code.toString() == "VK_BACK_SPACE")
{
lv_dept_len = lv_dept_nm.length();
lv_dept_nm = removeLastChar(lv_dept_nm);
}
}
onKeyTyped: function(e:KeyEvent)
{
if(lv_dept_len != 0)
{
lv_dept_len = 0;
}
else if(lv_dept_nm == "")
{
lv_dept_nm = e.char;
}
else
{
lv_dept_nm = '{lv_dept_nm}{e.char}';
}
}
columns: 12
visible:bind not listCell.empty and lv_dept_flag and listCell.selected and (lv_dept_ind == listCell.index)
}
]
}
VBox {
spacing: 10
content: [
Label {
text: bind description[listCell.index]
visible: bind not listCell.empty and not lv_dept_flag or not listCell.selected or (lv_dept_ind != listCell.index)
}
lv_dept_desc = TextBox
{
promptText: bind description[listCell.index]
onKeyPressed: function(ke: KeyEvent)
{
if(ke.code.toString() == "VK_BACK_SPACE")
{
lv_dept_len = lv_dept_des.length();
lv_dept_des = removeLastChar(lv_dept_des);
}
}
onKeyTyped : function(e: KeyEvent)
{
if(lv_dept_len != 0)
{
lv_dept_len = 0;
}
else if(lv_dept_des == "")
{
lv_dept_des = e.char;
}
else
{
lv_dept_des = '{lv_dept_des}{e.char}';
}
}
columns: 12
visible:bind not listCell.empty and lv_dept_flag and listCell.selected and (lv_dept_ind == listCell.index)
}
]
}
VBox{
spacing: 10
content: [
Button {
vpos: VPos.TOP;
text: "Edit"
visible: bind not listCell.empty and (not lv_dept_flag or not listCell.selected or (lv_dept_ind != listCell.index))
action: function() {
lv_dept_ind = listCell.index;
lv_dept_flag = true;
}
}
lv_dept_upBtn = Button {
vpos: VPos.TOP;
text: "Update"
visible: bind not listCell.empty and lv_dept_flag and listCell.selected and (lv_dept_ind == listCell.index)
action: function() {
cs = cn.prepareCall("call update_dept(?,?,?)");
cs.setString(1, '{dept_choicebox_item[listCell.index]}');
cs.setString(2, '{lv_dept_nm}');
cs.setString(3, '{lv_dept_des}');
cs.executeUpdate();
dept_choicebox_item[listCell.index] = lv_dept_nm;
description[listCell.index] = lv_dept_des;
lv_dept_flag = false;
lv_dept_nm = "";
lv_dept_des = "";
}
}
]
}
VBox{
spacing: 10
content: [
Button {
vpos: VPos.TOP;
text: "Delete"
visible: bind not listCell.empty and (not lv_dept_flag or not listCell.selected or (lv_dept_ind != listCell.index))
action: function() {
cs = cn.prepareCall("call delete_dept(?)");
cs.setString(1,'{dept_choicebox_item[listCell.index]}');
cs.executeUpdate();
delete dept_choicebox_item[listCell.index] from dept_choicebox_item;
delete description[listCell.index] from description;
lv_dept_size = 55 * dept_choicebox_item.size();
}
}
]
}
]
}
}
}
visible:true;
};

Related

QML: How to re-order repeater items with drag and drop? Somewhat working code inside

I'm trying to reorder Repeater items using drag & drop. I'm using a Repeater due to dynamically loaded data. Below is what I have so far using a simple sqlite database with sample data added. What I'm hoping for is to get the re-order set up so when the user releases the dragged object, the database is updated to reflect the new order. The "Change" button reorders the elements as I want, I just can't get it to work property with drag and drop.
The loadData() function simply creates the table and inserts sample data. The "Change" button won't be in the final code, I just wanted to use it to get the re-ordering code to work.
import QtQuick.Controls 2.2 as QC2
import QtQuick 2.10
import QtQuick.Window 2.10
import QtQuick.LocalStorage 2.0
Window {
id: root
width: 320
height: 480
property var db
property int rowHeight: 90
Component.onCompleted: {
db = LocalStorage.openDatabaseSync("test_db", "1.0", "Database", 100000)
loadData()
}
property var sql_data: []
function loadData() {
var sql, rs, len, i
db.transaction(function(tx) {
tx.executeSql("DROP TABLE IF EXISTS tbl")
tx.executeSql("CREATE TABLE IF NOT EXISTS tbl (
rowId INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL, listOrder INTEGER NOT NULL)")
len = 5
for (i = 0; i < len; i++)
tx.executeSql("INSERT INTO tbl (name, listOrder) VALUES ('Item " + i + "', " + i + ")")
rs = tx.executeSql("SELECT name, listOrder FROM tbl ORDER BY listOrder ASC")
})
len = rs.rows.length
sql_data = new Array(len)
for (i = 0; i < len; i++) {
sql_data[i] = {"name": "", "order": ""}
sql_data[i]["name"] = rs.rows.item(i).name
sql_data[i]["order"] = rs.rows.item(i).listOrder
}
repeater.model = sql_data
}
Flickable {
id: mainFlick
anchors.fill: parent
contentHeight: mainColumn.height
Column {
id: mainColumn
width: parent.width
QC2.Button {
text: "Change"
onClicked: {
var p1, p2
var d1 = new Date().getTime()
var movedEle = 3
var newPos = 1
var ele1 = repeater.itemAt(movedEle)
var ele2 = repeater.itemAt(newPos)
ele1.y = ele2.y
root.sql_data[movedEle]["order"] = root.sql_data[newPos]["order"]
if (newPos < movedEle) {
p1 = newPos
p2 = movedEle
} else {
p1 = movedEle
p2 = newPos
}
root.db.transaction(function(tx) {
var sql = "UPDATE tbl SET listOrder = " + root.sql_data[p1]["order"] + " "
sql += "WHERE listOrder = " + (root.sql_data[p2]["order"])
for (var i = p1; i < p2; i++) {
if (i !== movedEle) {
repeater.itemAt(i).y = repeater.itemAt(i).y + rowHeight
root.sql_data[i]["order"] += 1
sql = "UPDATE tbl SET listOrder = " + root.sql_data[i]["order"] + " "
sql += "WHERE listOrder = " + (root.sql_data[i]["order"] - 1)
tx.executeSql(sql)
}
}
})
sql_data = sql_data.sort(function(a,b) {
return a["order"] - b["order"]
})
repeater.model = sql_data
var d2 = new Date().getTime()
console.debug("Seconds: " + (d2 - d1) / 1000)
}
}
Repeater {
id: repeater
width: parent.width
model: []
delegate: Column {
id: repeaterItem
width: parent.width - 20
height: rowHeight
anchors.horizontalCenter: parent.horizontalCenter
property int pos: index
DropArea {
id: dragTarget
width: parent.width
height: 20
Rectangle {
id: dropRect
anchors.fill: parent
color: "green"
states: [
State {
when: dragTarget.containsDrag
PropertyChanges {
target: dropRect
color: "red"
}
}
]
}
}
Row {
id: contentRow
width: parent.width
height: parent.height
z: 1
Column {
id: itemColumn
width: parent.width - 70
Text {
text: "Name: " + modelData["name"]
}
Text {
text: "Order: " + modelData["order"]
}
Text {
text: "Repeater Index: " + index
}
} // itemColumn
MouseArea {
id: dragArea
width: 40
height: itemColumn.height
drag.axis: Drag.YAxis
drag.target: dragRect
onReleased: parent = ((dragRect.Drag.target !== null) ? dragRect.Drag.target : root)
Rectangle {
Component.onCompleted: console.debug(dragRect.Drag.target)
id: dragRect
width: 40
height: itemColumn.height
color: "grey"
Drag.active: dragArea.drag.active
Drag.source: dragArea
Drag.hotSpot.x: width / 2
Drag.hotSpot.y: height / 2
states : State {
when: dragArea.drag.active
ParentChange { target: dragRect; parent: root }
AnchorChanges {
target: dragRect
anchors.verticalCenter: undefined
anchors.horizontalCenter: undefined
}
}
}
}
} // contentRow
Behavior on y {
PropertyAnimation {
duration: 200
easing.type: Easing.Linear
}
}
} // repeaterItem
} // repeater
} // mainColumn
} // mainFlick
} // id
Much of the drag and drop code came from the Qt Examples site.
Here's what my problems are:
The MouseArea used for dragging the rectangles doesn't seem to change locations. Once a rectangle is actually moved, it stays in its new location but if I want to move it again, I have to click and drag where it was originally when the app loads.
If I switch the target of the Drag Area from the child rectangle to the entire row (repeaterItem), everything moves properly but will no longer interact with the Drop areas.
I think I can get the index of the new location after a row has been dragged simply by getting the y-value of the Drop Area. Would there be a better way to do this?
Since the "Change" button already re-orders the row elements, I only need help getting the rows to properly interact with the Drop Areas and then get the y-position of the Drop Area when the dragged item is released.
It may not be the most efficient out there but it's a good start for anybody looking to do something similar.
import QtQuick.Controls 2.2 as QC2
import QtQuick 2.10
import QtQuick.Window 2.10
import QtQuick.LocalStorage 2.0
Window {
id: root
width: 320
height: 580
property var db
property int rowHeight: 90
property int len
Component.onCompleted: {
db = LocalStorage.openDatabaseSync("test_db", "1.0", "Database", 100000)
loadData()
}
property var sql_data: []
function loadData() {
var sql, rs, i
db.transaction(function(tx) {
tx.executeSql("DROP TABLE IF EXISTS tbl")
tx.executeSql("CREATE TABLE IF NOT EXISTS tbl (
rowId INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL, listOrder INTEGER NOT NULL)")
len = 15
for (i = 0; i < len; i++)
tx.executeSql("INSERT INTO tbl (name, listOrder) VALUES ('Item " + i + "', " + i + ")")
rs = tx.executeSql("SELECT name, listOrder FROM tbl ORDER BY listOrder ASC")
})
len = rs.rows.length
sql_data = new Array(len)
for (i = 0; i < len; i++) {
sql_data[i] = {"name": "", "order": ""}
sql_data[i]["name"] = rs.rows.item(i).name
sql_data[i]["order"] = rs.rows.item(i).listOrder
}
repeater.model = sql_data
}
Flickable {
id: mainFlick
anchors.fill: parent
contentHeight: mainColumn.height
rebound: Transition {
NumberAnimation {
properties: "y"
duration: 500
easing.type: Easing.OutCirc
}
}
Column {
id: mainColumn
width: parent.width
function moveEle(start, end, f) {
if (f === false) {
var p1, p2, ele1, ele2
var c = false
var d1 = new Date().getTime()
ele1 = repeater.itemAt(start)
console.debug(f)
ele2 = repeater.itemAt(end)
root.sql_data[start]["order"] = root.sql_data[end]["order"]
if (end < start) {
p1 = end
p2 = start
} else {
p1 = start
p2 = end
c = true
}
root.db.transaction(function(tx) {
var sql = "UPDATE tbl SET listOrder = " + root.sql_data[p1]["order"] + " "
sql += "WHERE listOrder = " + (root.sql_data[p2]["order"])
for (var i = p1; i < p2; i++) {
if (c === false) {
if (i !== start) {
root.sql_data[i]["order"]++
sql = "UPDATE tbl SET listOrder = " + root.sql_data[i]["order"] + " "
sql += "WHERE listOrder = " + (root.sql_data[i]["order"] - 1)
tx.executeSql(sql)
}
} else {
root.sql_data[i]["order"]--
sql = "UPDATE tbl SET listOrder = " + root.sql_data[i]["order"] + " "
sql += "WHERE listOrder = " + (root.sql_data[i]["order"] - 1)
tx.executeSql(sql)
}
}
})
} else if (f === true) {
c = false
d1 = new Date().getTime()
ele1 = repeater.itemAt(start)
console.debug(f)
end--
ele2 = repeater.itemAt(end)
root.sql_data[start]["order"] = root.sql_data[end]["order"]
p1 = start
p2 = end
c = true
root.db.transaction(function(tx) {
var sql = "UPDATE tbl SET listOrder = " + root.sql_data[p1]["order"] + " "
sql += "WHERE listOrder = " + (root.sql_data[p2]["order"])
tx.executeSql(sql)
for (var i = p1; i <= p2; i++) {
if (i !== start) {
root.sql_data[i]["order"]--
sql = "UPDATE tbl SET listOrder = " + root.sql_data[i]["order"] + " "
sql += "WHERE listOrder = " + (root.sql_data[i]["order"] - 1)
tx.executeSql(sql)
}
}
})
}
sql_data = sql_data.sort(function(a,b) {
return a["order"] - b["order"]
})
repeater.model = sql_data
var d2 = new Date().getTime()
console.debug("Seconds: " + (d2 - d1) / 1000)
}
Repeater {
id: repeater
width: parent.width
model: []
delegate: Column {
id: repeaterItem
width: parent.width
height: rowHeight
anchors.horizontalCenter: parent.horizontalCenter
z: dragArea.drag.active ? 2 : 1
property int pos: index
DropArea {
id: dragTarget
width: parent.width
height: 15
property int ind: index
onEntered: {
drag.source.ind = index
drag.source.f = false
if (drag.source.ind !== drag.source.oldInd && drag.source.ind !== drag.source.oldInd + 1)
drag.source.caught = true
}
onExited: drag.source.caught = false
Rectangle {
id: dropRect
anchors.fill: parent
z: 0
states: [
State {
when: dragTarget.containsDrag
PropertyChanges {
target: dropRect
color: "grey"
}
PropertyChanges {
target: dropRectLine
visible: false
}
}
]
Rectangle {
id: dropRectLine
width: parent.width
height: 1
anchors.verticalCenter: parent.verticalCenter
color: "black"
}
}
}
Row {
id: contentRow
width: parent.width
height: parent.height
Drag.active: dragArea.drag.active
Drag.source: dragArea
Drag.hotSpot.x: width / 2
Drag.hotSpot.y: height / 2
Column {
id: itemColumn
width: parent.width - 70
Text {
text: "Name: " + modelData["name"]
}
Text {
text: "Order: " + modelData["order"]
}
Text {
text: "Repeater Index: " + index
}
} // itemColumn
MouseArea {
id: dragArea
width: 40 //repeater.width
height: itemColumn.height
drag.axis: Drag.YAxis
drag.target: contentRow
property point beginDrag
property point dropTarget
property bool caught: false
property int ind
property int oldInd: index
property bool f
onPressed: {
dragArea.beginDrag = Qt.point(contentRow.x, contentRow.y);
}
onReleased: {
if (dragArea.caught) {
dropRectFinal.color = "white"
dropRectLineFinal.visible = true
mainColumn.moveEle(index,dragArea.ind, dragArea.f)
} else {
backAnimY.from = contentRow.y;
backAnimY.to = beginDrag.y;
backAnim.start()
}
}
Rectangle {
id: dragRect
width: 40
height: itemColumn.height
color: "grey"
}
} // contentRow
} // dragArea
ParallelAnimation {
id: backAnim
SpringAnimation { id: backAnimY; target: contentRow; property: "y"; duration: 300; spring: 2; damping: 0.2 }
}
} // repeaterItem
} // repeater
DropArea {
id: dragTargetFinal
width: parent.width
height: 15
property int ind: root.len
onEntered: {
drag.source.ind = ind
drag.source.f = true
if (drag.source.ind !== drag.source.oldInd && drag.source.ind !== drag.source.oldInd + 1)
drag.source.caught = true
}
onExited: drag.source.caught = false
Rectangle {
id: dropRectFinal
anchors.fill: parent
states: [
State {
when: dragTargetFinal.containsDrag
PropertyChanges {
target: dropRectFinal
color: "grey"
}
PropertyChanges {
target: dropRectLineFinal
visible: false
}
}
]
Rectangle {
id: dropRectLineFinal
width: parent.width
height: 1
anchors.verticalCenter: parent.verticalCenter
color: "black"
}
}
}
} // mainColumn
QC2.ScrollBar.vertical: QC2.ScrollBar { active: scrollAnim.running ? true : false }
} // mainFlick
DropArea {
id: scrollUp
width: parent.width
height: 50
anchors.top: parent.top
visible: {
var visible = false
if (mainFlick.contentY > 0)
visible = true
visible
}
onEntered: {
scrollAnim.from = mainFlick.contentY
scrollAnim.to = 0
scrollAnim.start()
}
onExited: scrollAnim.stop()
}
DropArea {
id: scrollDown
width: parent.width
height: 50
anchors.bottom: parent.bottom
visible: {
var visible = false
if (mainFlick.contentY < mainColumn.height - Window.height)
visible = true
visible
}
onEntered: {
scrollAnim.from = mainFlick.contentY
scrollAnim.to = mainColumn.height - Window.height
scrollAnim.start()
}
onExited: scrollAnim.stop()
}
SmoothedAnimation {
id: scrollAnim
target: mainFlick
property: "contentY"
velocity: 400
loops: 1
maximumEasingTime: 10
}
} // root

SignalR with paging using Groups

I am new to SignalR and in the learning process, I am trying to make Stock ticker. I have over 1000 stocks list and want to show paging and update on real-time changes that's why I am using Groups with SignalR. Problem is that when I open page 1 then everything works fine until I open page 2, then page 1 stop getting signals and page 2 start getting signals. What am I missing here in SignalR groups? Please help me, Thanks.
Hub
[HubName("stockTicker")]
public class StockTickerHub : Hub
{
private StockTicker _stockTicker;
public StockTickerHub()
: this(StockTicker.Instance)
{
}
public StockTickerHub(StockTicker stockTicker)
{
_stockTicker = stockTicker;
}
public void OpenMarket()
{
var page = this.Context.QueryString["page_no"];
int pageno = Convert.ToInt32(page);
_stockTicker.OpenMarket(pageno);
tryAddGroup(page);
}
public Task tryAddGroup(string page)
{
return Groups.Add(Context.ConnectionId, page);
}
}
StockTicker.cs
public class StockTicker
{
MainModel _model = new MainModel();
private static Lazy<StockTicker> _instance = new Lazy<StockTicker>(() => new StockTicker(GlobalHost.ConnectionManager.GetHubContext<StockTickerHub>().Clients));
private TimeSpan _updateInterval = TimeSpan.FromMilliseconds(3000);
private Timer _timer;
public volatile int pageno;
private StockTicker(IHubConnectionContext<dynamic> clients)
{
Clients = clients;
}
public static StockTicker Instance
{
get
{
return _instance.Value;
}
}
private IHubConnectionContext<dynamic> Clients
{
get;
set;
}
public void OpenMarket(int page_no)
{
pageno = page_no;
_timer = new Timer(UpdateStockPrices, pageno, _updateInterval, _updateInterval);
}
private void UpdateStockPrices(object state)
{
var latest_stocks = new List<StockViewModel>();
latest_stocks = _model.Get100Stocks(pageno);
foreach (var stock in latest_stocks)
{
BroadcastStockPrice(stock, pageno);
}
}
private void BroadcastStockPrice(StockViewModel stock, int pageno)
{
Clients.Group(pageno.ToString()).updateStockPrice(stock);
//Clients.All.updateStockPrice(stock);
}
}
(Updated Question)
StockTicker.js
if (!String.prototype.supplant) {
String.prototype.supplant = function (o) {
return this.replace(/{([^{}]*)}/g,
function (a, b) {
var r = o[b];
return typeof r === 'string' || typeof r === 'number' ? r : a;
}
);
};
}
jQuery.fn.flash = function (color, duration) {
var current = this.css('backgroundColor');
this.animate({ backgroundColor: 'rgb(' + color + ')' }, duration / 2)
.animate({ backgroundColor: current }, duration / 2);
};
$(function () {
var ticker = $.connection.stockTicker;
var $stockTable = $('#stockTable');
var $stockTableBody = $stockTable.find('tbody');
tdPrice = '<td data-rank-price="{currency_query}" data-sort="{currency_price_usd}"><div data-price-spn="{currency_query}">${currency_price_usd}</div></td>';
tdPercentage = '<td data-rank-perc="{currency_query}" data-sort="{currency_change_24h_usd}"><div data-change-spn="{currency_query}"><span class="{DirectionClass}">{currency_change_24h_usd}</span></div></td>';
tdVolume = '<td data-rank-volume="{currency_query}" data-sort="{currency_24h_volume_usd}"><div data-24-volume-spn="{currency_query}>${currency_24h_volume_usd}</div></td>';
tdMarketcap = '<td data-rank-cap="{currency_query}" data-sort="{currency_market_cap_usd}"><div data-mcap-spn="{currency_query}">${currency_market_cap_usd}</div></td>';
function formatStock(stock) {
return $.extend(stock, {
currency_price_usd: formatprices(stock.currency_price_usd),
currency_change_24h_usd: stock.currency_change_24h_usd == null ? '0.00%' : (stock.currency_change_24h_usd).toFixed(2) + '%',
currency_24h_volume_usd: stock.currency_24h_volume_usd == null ? '0' : nFormatter(stock.currency_24h_volume_usd, 2),
currency_market_cap_usd: stock.currency_market_cap_usd == null ? '0' : nFormatter(stock.currency_market_cap_usd, 2),
DirectionClass: stock.currency_change_24h_usd === 0 ? 'nochange' : stock.currency_change_24h_usd >= 0 ? 'green' : 'red'
});
}
function nFormatter(num, digits) {
var si = [
{ value: 1, symbol: "" },
{ value: 1E3, symbol: "K" },
{ value: 1E6, symbol: "M" },
{ value: 1E9, symbol: "B" },
{ value: 1E12, symbol: "T" },
{ value: 1E15, symbol: "P" },
{ value: 1E18, symbol: "E" }
];
var rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
var i;
for (i = si.length - 1; i > 0; i--) {
if (num >= si[i].value) {
break;
}
}
return (num / si[i].value).toFixed(digits).replace(rx, "$1") + si[i].symbol;
}
function formatprices(n, curr) {
var sep = sep || ".";
var decimals;
if (n > 0.99999999) {
decimals = decimals || 2;
}
else {
decimals = decimals || 6;
}
return n.toLocaleString().split(sep)[0]
+ sep
+ n.toFixed(decimals).split(sep)[1];
}
$.extend(ticker.client, {
updateStockPrice: function (stock) {
var displayStock = formatStock(stock),
$tdprice = $(tdPrice.supplant(displayStock)),
$tdpercentage = $(tdPercentage.supplant(displayStock)),
$tdvolume = $(tdVolume.supplant(displayStock)),
$tdcap = $(tdMarketcap.supplant(displayStock));
if (stock.LastChange != 0.0) {
bgprice = stock.LastChange < 0.0
? '255,148,148'
: '154,240,117';
$stockTableBody.find('td[data-rank-price=' + stock.currency_query + ']').replaceWith($tdprice);
$tdpricespn = $stockTableBody.find('div[data-price-spn=' + stock.currency_query + ']');
$tdpricespn.flash(bgprice, 1500);
}
if (stock.LastChangePercentage != 0.0) {
bgper = stock.LastChangePercentage < 0.0
? '255,148,148'
: '154,240,117';
$stockTableBody.find('td[data-rank-perc=' + stock.currency_query + ']').replaceWith($tdpercentage);
$tdpercentagespn = $stockTableBody.find('div[data-change-spn=' + stock.currency_query + ']');
$tdpercentagespn.flash(bgper, 1500);
}
if (stock.LastChangeVolume != 0.0) {
bgvol = stock.LastChangeVolume < 0.0
? '255,148,148'
: '154,240,117';
$stockTableBody.find('td[data-rank-volume=' + stock.currency_query + ']').replaceWith($tdvolume);
$tdvolumespn = $stockTableBody.find('div[data-24-volume-spn=' + stock.currency_query + ']');
$tdvolumespn.flash(bgvol, 1500);
}
if (stock.LastChangeCap != 0.0) {
bgcap = stock.LastChangeCap < 0.0
? '255,148,148'
: '154,240,117';
$stockTableBody.find('td[data-rank-cap=' + stock.currency_query + ']').replaceWith($tdcap);
$tdcapspn = $stockTableBody.find('div[data-mcap-spn=' + stock.currency_query + ']');
$tdcapspn.flash(bgcap, 1500);
}
}
});
$.connection.hub.url = 'http://localhost:13429/signalr';
$.connection.hub.qs = { 'page_no': $("#page").val() };
$.connection.hub.start().done(function () {
console.log("connected");
}).then(function () {
return ticker.server.openMarket();
});
});
Looking at your code, your global variable pageno is always the last page that was requested:
public void OpenMarket(int page_no)
{
pageno = page_no;
_timer = new Timer(UpdateStockPrices, pageno, _updateInterval, _updateInterval);
}
You need another variable that tracks the max page.
public volatile int pageMax;
public void OpenMarket(int page_no)
{
pageno = page_no;
pageMax = pageno > pageMax
: pageno
? pageMax;
_timer = new Timer(UpdateStockPrices, pageno, _updateInterval, _updateInterval);
}
Then make sure to broadcast the correct stocks to the pages.

Qt Quick Controls 2 on-screen Number pad on spinbox

In a touchpanel application, is it possible to edit the integer value of a qml SpinBox, from QtQuickControls 2.0, in such a way that a numeric keypad appears on-screen and one can enter the exact value?
Or do you have any idea on how to embed this predefined number pad in a customized spinbox, that should pop-up when the user taps on the integer number?
The numpad can be set to be invisible and put on top of everything, then you can have a function to enable its visibility and set it's target. When you are done with typing the number, you set the target value to the numpad value, and hide it again. This way you can target different spinboxes.
As of the actual method to request the keypad, you can put a MouseArea to fill the spinbox on top of it. Or you can make the mouse area narrower, so that the plus/minus buttons of the spinbox are still clickable.
Also keep in mind that numpad you have linked is not actually functional.
Thanks for your suggestion. I came up with a first quick solution based on your idea and the number pad from the example section. I post it here, just in case it helps someone else as starting point. I am a QML beginner, so happy to get any improvements or corrections.
See attached screenshot of the numeric virtual touchpad appearing when clicking on the spinbox number
SpinBox {
id: boxCommPos
x: 50
y: 50
z: 0
width: 200
height: 50
to: 360
editable: false
contentItem: TextInput {
z: 1
text: parent.textFromValue(parent.value, parent.locale)
font: parent.font
//color: "#21be2b"
//selectionColor: "#21be2b"
//selectedTextColor: "#ffffff"
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
readOnly: !parent.editable
validator: parent.validator
inputMethodHints: Qt.ImhFormattedNumbersOnly
}
Label {
id: commUnits
x: 125
y: 0
z: 3
text: qsTr("º")
font.pointSize: 16
anchors.right: parent.right
anchors.rightMargin: 45
}
MouseArea {
id: padCommPos
x: 40
y: 0
z: 2
width: parent.width-x-x
height: 50
onClicked: touchpad.visible=true
}
}
NumberTouchpad {
id: touchpad
x: 470
y: -20
z: 1
scale: 0.90
visible: false
Rectangle {
id: backrect
x: -parent.x/parent.scale
z: -1
width: parent.parent.width/parent.scale
height: parent.parent.height/parent.scale
color: "#eceeea"
opacity: 0.5
MouseArea {
anchors.fill: parent
}
}
}
The file NumberPad.qml
import QtQuick 2.0
Grid {
columns: 3
columnSpacing: 32
rowSpacing: 16
signal buttonPressed
Button { text: "7" }
Button { text: "8" }
Button { text: "9" }
Button { text: "4" }
Button { text: "5" }
Button { text: "6" }
Button { text: "1" }
Button { text: "2" }
Button { text: "3" }
Button { text: "0" }
Button { text: "."; dimmable: true }
//Button { text: " " }
Button { text: "±"; color: "#6da43d"; operator: true; dimmable: true }
//Button { text: "−"; color: "#6da43d"; operator: true; dimmable: true }
//Button { text: "+"; color: "#6da43d"; operator: true; dimmable: true }
//Button { text: "√"; color: "#6da43d"; operator: true; dimmable: true }
//Button { text: "÷"; color: "#6da43d"; operator: true; dimmable: true }
//Button { text: "×"; color: "#6da43d"; operator: true; dimmable: true }
Button { text: "C"; color: "#6da43d"; operator: true }
Button { text: "✔"; color: "#6da43d"; operator: true; dimmable: true }
Button { text: "X"; color: "#6da43d"; operator: true }
}
Display.qml
// Copyright (C) 2015 The Qt Company Ltd.
import QtQuick 2.0
import QtQuick.Window 2.0
Item {
id: display
property real fontSize: Math.floor(Screen.pixelDensity * 10.0)
property string fontColor: "#000000"
property bool enteringDigits: false
property int maxDigits: (width / fontSize) + 1
property string displayedOperand
property string errorString: qsTr("ERROR")
property bool isError: displayedOperand === errorString
function displayOperator(operator)
{
listView.model.append({ "operator": operator, "operand": "" })
enteringDigits = true
listView.positionViewAtEnd()
//console.log("display",operator);
}
function newLine(operator, operand)
{
displayedOperand = displayNumber(operand)
listView.model.append({ "operator": operator, "operand": displayedOperand })
enteringDigits = false
listView.positionViewAtEnd()
//console.log("newLine",operator);
}
function appendDigit(digit)
{
if (!enteringDigits)
listView.model.append({ "operator": "", "operand": "" })
var i = listView.model.count - 1;
listView.model.get(i).operand = listView.model.get(i).operand + digit;
enteringDigits = true
listView.positionViewAtEnd()
//console.log("num is ", digit);
}
function setDigit(digit)
{
var i = listView.model.count - 1;
listView.model.get(i).operand = digit;
listView.positionViewAtEnd()
//console.log("setDigit",digit);
}
function clear()
{
displayedOperand = ""
if (enteringDigits) {
var i = listView.model.count - 1
if (i >= 0)
listView.model.remove(i)
enteringDigits = false
}
//console.log("clearing");
}
// Returns a string representation of a number that fits in
// display.maxDigits characters, trying to keep as much precision
// as possible. If the number cannot be displayed, returns an
// error string.
function displayNumber(num) {
if (typeof(num) != "number")
return errorString;
var intNum = parseInt(num);
var intLen = intNum.toString().length;
// Do not count the minus sign as a digit
var maxLen = num < 0 ? maxDigits + 1 : maxDigits;
if (num.toString().length <= maxLen) {
if (isFinite(num))
return num.toString();
return errorString;
}
// Integer part of the number is too long - try
// an exponential notation
if (intNum == num || intLen > maxLen - 3) {
var expVal = num.toExponential(maxDigits - 6).toString();
if (expVal.length <= maxLen)
return expVal;
}
// Try a float presentation with fixed number of digits
var floatStr = parseFloat(num).toFixed(maxDigits - intLen - 1).toString();
if (floatStr.length <= maxLen)
return floatStr;
return errorString;
}
Item {
id: theItem
width: parent.width
height: parent.height
Rectangle {
id: rect
x: 0
color: "#eceeea"
height: parent.height
width: display.width
}
/*Image {
anchors.right: rect.left
source: "images/paper-edge-left.png"
height: parent.height
fillMode: Image.TileVertically
}
Image {
anchors.left: rect.right
source: "images/paper-edge-right.png"
height: parent.height
fillMode: Image.TileVertically
}
Image {
id: grip
source: "images/paper-grip.png"
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 20
}*/
ListView {
id: listView
width: display.width
height: display.height
delegate: Item {
height: display.fontSize * 1.1
width: parent.width
Text {
id: operator
font.pixelSize: display.fontSize
color: "#6da43d"
text: model.operator
}
Text {
id: operand
y:5
font.pixelSize: display.fontSize
color: display.fontColor
anchors.right: parent.right
anchors.rightMargin: 22
text: model.operand
}
}
model: ListModel { }
}
}
}
calculator.qs
// Copyright (C) 2015 The Qt Company Ltd.
var curVal = 0
var memory = 0
var lastOp = ""
var previousOperator = ""
var digits = ""
function disabled(op) {
if (op == "✔")
display.fontColor="#000000"
if (op=="X")
return false
else if (op == "✔" && (digits.toString().search(/\./) != -1 || digits.toString().search(/-/)!= -1 || parseInt(digits)>359)) {
display.fontColor="#ff0000"
return true
}
else if (digits == "" && !((op >= "0" && op <= "9") || op == "."))
return true
else if (op == '=' && previousOperator.length != 1)
return true
else if (op == "." && digits.toString().search(/\./) != -1) {
return true
} else if (op == "√" && digits.toString().search(/-/) != -1) {
return true
} else {
return false
}
}
function digitPressed(op)
{
if (disabled(op))
return
if (digits.toString().length >= display.maxDigits)
return
if (lastOp.toString().length == 1 && ((lastOp >= "0" && lastOp <= "9") || lastOp == ".") ) {
digits = digits + op.toString()
display.appendDigit(op.toString())
} else {
digits = op
display.appendDigit(op.toString())
}
lastOp = op
}
function operatorPressed(op)
{
if (disabled(op))
return
lastOp = op
if (op == "±") {
digits = Number(digits.valueOf() * -1)
display.setDigit(display.displayNumber(digits))
return
}
if (previousOperator == "+") {
digits = Number(digits.valueOf()) + Number(curVal.valueOf())
} else if (previousOperator == "−") {
digits = Number(curVal.valueOf()) - Number(digits.valueOf())
} else if (previousOperator == "×") {
digits = Number(curVal) * Number(digits.valueOf())
} else if (previousOperator == "÷") {
digits = Number(curVal) / Number(digits.valueOf())
}
if (op == "+" || op == "−" || op == "×" || op == "÷") {
previousOperator = op
curVal = digits.valueOf()
digits = ""
display.displayOperator(previousOperator)
return
}
if (op == "=") {
display.newLine("=", digits.valueOf())
}
curVal = 0
previousOperator = ""
if (op == "1/x") {
digits = (1 / digits.valueOf()).toString()
} else if (op == "x^2") {
digits = (digits.valueOf() * digits.valueOf()).toString()
} else if (op == "Abs") {
digits = (Math.abs(digits.valueOf())).toString()
} else if (op == "Int") {
digits = (Math.floor(digits.valueOf())).toString()
} else if (op == "√") {
digits = Number(Math.sqrt(digits.valueOf()))
display.newLine("√", digits.valueOf())
} else if (op == "mc") {
memory = 0;
} else if (op == "m+") {
memory += digits.valueOf()
} else if (op == "mr") {
digits = memory.toString()
} else if (op == "m-") {
memory = digits.valueOf()
} else if (op == "backspace") {
digits = digits.toString().slice(0, -1)
display.clear()
display.appendDigit(digits)
} else if (op == "✔") {
window.visible=false
boxCommPos.value=parseInt(digits)
display.clear()
curVal = 0
memory = 0
lastOp = ""
digits = ""
} else if (op == "X") {
window.visible=false
display.clear()
curVal = 0
memory = 0
lastOp = ""
digits = ""
}
// Reset the state on 'C' operator or after
// an error occurred
if (op == "C" || display.isError) {
display.clear()
curVal = 0
memory = 0
lastOp = ""
digits = ""
}
}
Button.qml
// Copyright (C) 2015 The Qt Company Ltd.
import QtQuick 2.0
Item {
id: button
property alias text: textItem.text
property color color: "#eceeea"
property bool operator: false
property bool dimmable: false
property bool dimmed: false
width: 30
height: 50
Text {
id: textItem
font.pixelSize: 48
wrapMode: Text.WordWrap
lineHeight: 0.75
color: (dimmable && dimmed) ? Qt.darker(button.color) : button.color
Behavior on color { ColorAnimation { duration: 120; easing.type: Easing.OutElastic} }
states: [
State {
name: "pressed"
when: mouse.pressed && !dimmed
PropertyChanges {
target: textItem
color: Qt.lighter(button.color)
}
}
]
}
MouseArea {
id: mouse
anchors.fill: parent
anchors.margins: -5
onClicked: {
if (operator)
window.operatorPressed(parent.text)
else
window.digitPressed(parent.text)
}
}
function updateDimmed() {
dimmed = window.isButtonDisabled(button.text)
}
Component.onCompleted: {
numPad.buttonPressed.connect(updateDimmed)
updateDimmed()
}
}

Flex sort Datagrid with custom compareFunction (sort numbers numerical and text alphanumerical)

I need following result.
All numbers use numeric sorting and all strings use alphanumeric sort. Further more , the numeric values should be listed before the string values:
Example:
before "i","9","89","0045","b","x"
after "9","0045","89","b","i","x"
My current code looks like this: (numeric sort works but my strings are distributed to the top and bottom?! -> "b","x","9","0045","89","i")
public function compareFunction(obj1:Object, obj2:Object):int {
var id1:String = (obj1 as WdProblem).id;
var id2:String = (obj2 as WdProblem).id;
if(id1.replace(' ', '') == "n") {
var sdld:int = 0;
}
var num1:int = Number(id1);
var num2:int = Number(id2);
if(stringIsAValidNumber(id1) && stringIsAValidNumber(id2)) {
if(num1 == num2) {
return 0;
} else {
if(num1 > num2) {
return 1;
} else {
return -1;
}
}
} else if(!stringIsAValidNumber(id1) && !stringIsAValidNumber(id2)) {
return ObjectUtil.compare(id1, id2);
//return compareString(id1, id2);
} else if(!stringIsAValidNumber(id1) && stringIsAValidNumber(id2)) {
return 1;
} else if(stringIsAValidNumber(id1) && !stringIsAValidNumber(id2)) {
return -1;
}
return -1;
}
private function stringIsAValidNumber(s:String):Boolean {
return Boolean(s.match("[0-9]+(\.[0-9][0-9]?)?"));
}
My suggestion is to break it down into it's constituent parts especially if you have a scenario like this with 1 or more priority sorts. The key is to move onto the next sort only when the first sort returns they are equal.
For your case, I would build 2 sorts, one for numeric and the other for alpha-numeric, then your main sort can prioritize these by calling the sub-sort.
For example I have something similar:
private function sort2DimensionsByIncomeVsTime(a:OLAPSummaryCategory, b:OLAPSummaryCategory, fields:Array = null):int
{
var sort:OLAPSort = new OLAPSort();
var incomeSort:int = sort.sortIncome(a, b);
var nameSort:int = sort.sortName(a, b);
var yrSort:int = sort.sortYear(a, b);
var moSort:int = sort.sortMonth(a, b);
if (incomeSort == 0)
{
if (nameSort == 0)
{
if (yrSort == 0)
{
//trace(a.name, a.year, a.month, 'vs:', b.name, b.year, b.month, 'month sort:', moSort);
return moSort;
}
else return yrSort;
}
else return nameSort;
}
else return incomeSort;
}
I use following sort function for AlphaNumeric sorting:
<?xml version="1.0" encoding="utf-8"?>
<s:Application
creationComplete="onCC()"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.utils.ObjectUtil;
import mx.utils.StringUtil;
import spark.collections.Sort;
import spark.collections.SortField;
public function onCC():void
{
var acAlphaNumericString:ArrayCollection = new ArrayCollection();
acAlphaNumericString.addItem({ name: "NUM10071" });
acAlphaNumericString.addItem({ name: "NUM9999" });
acAlphaNumericString.addItem({ name: "9997" });
acAlphaNumericString.addItem({ name: "9998" });
acAlphaNumericString.addItem({ name: "9996" });
acAlphaNumericString.addItem({ name: "9996F" });
acAlphaNumericString.addItem({ name: "i" });
acAlphaNumericString.addItem({ name: "9" });
acAlphaNumericString.addItem({ name: "89" });
acAlphaNumericString.addItem({ name: "0045" });
acAlphaNumericString.addItem({ name: "b" });
acAlphaNumericString.addItem({ name: "x" });
var sf:SortField = new SortField("name");
sf.compareFunction = function(o1:Object, o2:Object):int
{
return compare(o1.name, o2.name);
}
var sort:Sort = new Sort();
sort.fields = [ sf ];
acAlphaNumericString.sort = sort;
acAlphaNumericString.refresh();
for each (var o:Object in acAlphaNumericString)
trace(o.name);
}
public static function compare(firstString:String, secondString:String):int
{
if (secondString == null || firstString == null)
return 0;
var lengthFirstStr:int = firstString.length;
var lengthSecondStr:int = secondString.length;
var index1:int = 0;
var index2:int = 0;
while (index1 < lengthFirstStr && index2 < lengthSecondStr)
{
var ch1:String = firstString.charAt(index1);
var ch2:String = secondString.charAt(index2);
var space1:String = "";
var space2:String = "";
do
{
space1 += ch1;
index1++;
if (index1 < lengthFirstStr)
ch1 = firstString.charAt(index1);
else
break;
} while (isDigit(ch1) == isDigit(space1.charAt(0)));
do
{
space2 += ch2;
index2++;
if (index2 < lengthSecondStr)
ch2 = secondString.charAt(index2);
else
break;
} while (isDigit(ch2) == isDigit(space2.charAt(0)));
var str1:String = new String(space1);
var str2:String = new String(space2);
var result:int;
if (isDigit(space1.charAt(0)) && isDigit(space2.charAt(0)))
{
var firstNumberToCompare:int = parseInt(StringUtil.trim(str1));
var secondNumberToCompare:int = parseInt(StringUtil.trim(str2));
result = ObjectUtil.numericCompare(firstNumberToCompare, secondNumberToCompare);
}
else
result = ObjectUtil.compare(str1, str2);
if (result != 0)
return result;
}
return lengthFirstStr - lengthSecondStr;
function isDigit(ch:String):Boolean
{
var code:int = ch.charCodeAt(0);
return code >= 48 && code <= 57;
}
}
]]>
</fx:Script>
</s:Application>

Flex Datagrid + Tab Navigator

I have a several datagrids (with data being retrieved from some map service).
I want to place these data grids within seperate tabs of a tab navigator. All works fine apart from the first tab which always ends up without any datagrid in it.
I have tried creation policy="all" and stuff but the first tab always is empty. Does anybody have any ideas as to why the first tab is always empty.
Any workarounds.
Thanks
var box:HBox=new HBox();
var dg:DataGrid = new DataGrid();
dg.dataProvider = newAC;
box.label=title.text;
box.addChild(dg);
tabNaviId.addChild(box);
tabNaviId.selectedIndex=2;
resultsArea.addChild(tabNaviId);
dg is datagrid that is being filled up. The above code is in a loop, in each loop i am creating an Hbox+datagrid. then i am adding the Hbox to the navigator and final adding the navigator to resultsArea (which is a canvas).
The above code works great apart from first time.
The end result i get is, having a tab navigator with first tab without any datagrid but the remaining tabs all have the datagrids. Any ideas as to why this is happening.
Call to a function called createDatagrid is made:
dgCollection.addItem(parentApplication.resultsPanel.createDatagrid( token.name.toString() + " (" + recAC.length + " selected)", recAC, false, callsToMake ));
In another Mxml component this function exists
public function createDatagrid(titleText:String, recACAll:ArrayCollection, showContent:Boolean, callsToMake:Number):DataGrid
{
var dg:DataGrid = new DataGrid();
var newAC:ArrayCollection = new ArrayCollection();
var newDGCols:Array = new Array();
for( var i:Number = 0; i < recACAll.length; i ++)
{
var contentStr:String = recACAll[i][CONTENT_FIELD];
var featureGeo:Geometry = recACAll[i][GEOMETRY_FIELD];
var iconPath:String = recACAll[i][ICON_FIELD];
var linkStr:String = recACAll[i][LINK_FIELD];
var linkNameStr:String = recACAll[i][LINK_NAME_FIELD];
var featurePoint:MapPoint = recACAll[i][POINT_FIELD];
var titleStr:String = recACAll[i][TITLE_FIELD];
if( contentStr.length > 0)
{
var rows:Array = contentStr.split("\n");
var tmpObj:Object = new Object();
if(!showContent)
{
for( var j:Number = 0; j < rows.length; j++)
{
var tmpStr:String = rows[j] as String;
var header:String = tmpStr.substring(0,tmpStr.indexOf(":"));
var val:String = tmpStr.substring(tmpStr.indexOf(":") + 2);
if(header.length > 0)
{
tmpObj[header] = val;
if(newDGCols.length < rows.length - 1)
{
newDGCols.push( new DataGridColumn(header));
}
}
}
}
else
{
if(newDGCols.length == 0)
{
newDGCols.push(new DataGridColumn(CONTENT_FIELD));
newDGCols.push(new DataGridColumn(GEOMETRY_FIELD));
newDGCols.push(new DataGridColumn(ICON_FIELD));
newDGCols.push(new DataGridColumn(LINK_FIELD));
newDGCols.push(new DataGridColumn(LINK_NAME_FIELD));
newDGCols.push(new DataGridColumn(POINT_FIELD));
newDGCols.push(new DataGridColumn(TITLE_FIELD));
}
}
tmpObj[CONTENT_FIELD] = contentStr;
tmpObj[GEOMETRY_FIELD] = featureGeo;
tmpObj[ICON_FIELD] = iconPath;
tmpObj[LINK_FIELD] = linkStr;
tmpObj[LINK_NAME_FIELD] = linkNameStr;
tmpObj[POINT_FIELD] = featurePoint;
tmpObj[TITLE_FIELD] = titleStr;
newAC.addItem(tmpObj);
}
if( showHidePic.source == minSourceI )
{
showHidePic.source = minSource;
}
else if( showHidePic.source == maxSourceI )
{
showHidePic.source = maxSource;
}
curResults = curResults + recACAll.length;
if (curResults == 1)
{
showInfoWindow(tmpObj);
if(showContent)
{
parentApplication.maps.map.extent = featureGeo.extent;
}
}
else
{
showInfoWindow(null);
// Added to avoid the overview button problem (needs checking)
this.removeEventListener(MouseEvent.MOUSE_OVER, handleMouseOver, false);
this.removeEventListener(MouseEvent.MOUSE_MOVE,handleMouseOver,false);
this.removeEventListener(MouseEvent.MOUSE_OUT,handleMouseOut,false);
this.removeEventListener(MouseEvent.MOUSE_DOWN,handleMouseDrag,false);
this.removeEventListener(MouseEvent.MOUSE_UP,handleMouseDragStop,false);
this.parent.removeEventListener(MouseEvent.MOUSE_MOVE,handleParentMove,false);
this.parent.removeEventListener(MouseEvent.MOUSE_UP,handleMouseDragStop2,false);
maximizePanel();
}
}
dg.dataProvider = newAC;
dg.columns = newDGCols;
dg.rowCount = newAC.length;
var totalDGCWidth:Number = 0;
for( var m:Number = 0; m < dg.columns.length; m++)
{
var dgc2:DataGridColumn = dg.columns[m];
/*if(dgc2.headerText.toUpperCase()==LINK_FIELD.toUpperCase()){
//dgc.itemRenderer=new ClassFactory(CustomRenderer);
dgc2.itemRenderer=new ClassFactory(CustomRenderer);
}*/
var dgcWidth2:Number = dgc2.headerText.length * CHAR_LENGTH;
for( var l:Number = 0; l < newAC.length; l++)
{
var row2:Object = newAC.getItemAt(l) as Object;
var rowVal2:String = row2[dgc2.headerText];
if( rowVal2 != null)
{
var tmpLength2:Number = rowVal2.length * CHAR_LENGTH;
if(tmpLength2 < CHAR_MAX_LENGTH)
{
if(tmpLength2 > dgcWidth2)
{
dgcWidth2 = tmpLength2;
}
}
else
{
dgcWidth2 = CHAR_MAX_LENGTH
break;
}
}
}
// Added by FT:to change the item renderer for link field
if( dgc2.headerText == GEOMETRY_FIELD || dgc2.headerText == CONTENT_FIELD ||
dgc2.headerText == ICON_FIELD || dgc2.headerText == LINK_FIELD ||
dgc2.headerText == POINT_FIELD || dgc2.headerText == TITLE_FIELD ||
dgc2.headerText == LINK_NAME_FIELD)
{
if(dgc2.headerText == CONTENT_FIELD && showContent)
{
//something
}
else
{
dgcWidth2 = 0;
}
}
totalDGCWidth += dgcWidth2;
}
dg.width = totalDGCWidth;
for( var k:Number = 0; k < dg.columns.length; k++)
{
var dgc:DataGridColumn = dg.columns[k];
var dgcWidth:Number = dgc.headerText.length * CHAR_LENGTH;
for( var n:Number = 0; n < newAC.length; n++)
{
var row:Object = newAC.getItemAt(n) as Object;
var rowVal:String = row[dgc.headerText];
if(rowVal != null)
{
var tmpLength:Number = rowVal.length * CHAR_LENGTH;
if(tmpLength < CHAR_MAX_LENGTH)
{
if(tmpLength > dgcWidth)
{
dgcWidth = tmpLength;
}
}
else
{
dgcWidth = CHAR_MAX_LENGTH
break;
}
}
}
if( dgc.headerText == GEOMETRY_FIELD || dgc.headerText == CONTENT_FIELD ||
dgc.headerText == ICON_FIELD || dgc.headerText == LINK_FIELD ||
dgc.headerText == POINT_FIELD || dgc.headerText == TITLE_FIELD ||
dgc.headerText == LINK_NAME_FIELD)
{
if(dgc.headerText == CONTENT_FIELD && showContent)
{
dgc.visible = true;
}
else
{
dgc.visible = false;
dgcWidth = 0;
}
}
if( dgc.headerText == LINK_COL_NAME)
{
dgcWidth = LINK_COL_WIDTH;
}
dgc.width = dgcWidth;
}
dg.addEventListener(ListEvent.ITEM_CLICK,rowClicked);
dg.addEventListener(ListEvent.ITEM_ROLL_OVER,mouseOverRow);
dg.addEventListener(ListEvent.ITEM_ROLL_OUT,mouseOutRow);
var title:Text = new Text();
title.text = titleText;
title.setStyle("fontWeight","bold");
//resultsArea.addChild(title);
return dg;
//tabNaviId.selectedIndex=2;
}
public function populateGrid(dgCollection:ArrayCollection):void{
for( var k:Number = 0; k < dgCollection.length; k++)
{
var box:HBox=new HBox();
var dg2:DataGrid=dgCollection.getItemAt(k) as DataGrid;
box.label="some";
box.addChild(dg2);
tabNaviId.addChild(box);
}
resultsArea.addChild(tabNaviId);
}
and the tab navigator declared as
<mx:Image id="showHidePic" click="toggleResults()"/>
<mx:VBox y="20" styleName="ResultsArea" width="100%" height="100%">
<mx:HBox>
<mx:Button label="Export to Excel" click="downloadExcel()"/>
<mx:Button label="Clear" click="clear()" />
</mx:HBox>
<mx:VBox id="resultsArea" styleName="ResultsContent" paddingTop="10" paddingLeft="10" paddingRight="10" verticalScrollPolicy="off" horizontalScrollPolicy="off">
<mx:TabNavigator id="tabNaviId" width="622" height="274" creationPolicy="all">
</mx:TabNavigator>
</mx:VBox>
</mx:VBox>
Abstract, can we get the full code including the loop you mention, as well as the code where you create the TabNavigator?
It's possible that the TabNavigator already has an initial child, and all the children you're creating are being added after that.

Resources