So, I have a databases that populates a listbox. The listbox contains
0 Name, 1 picture, 2 SequenceID
I thought it maybe good to reorder them so my users could have their favourite ones at the top. They choose notes on the fretboard and the sequences will play them.
I enabled re-order. 0 and 2 moved to the new row - but the pictures stay in the same row that i dragged from. I have tried quite few tactics to get them to update… Doing something in callbackground paint… a completely new method to put the pictures in column 1.
Any ideas?
Which event handlers have you implemented in th elistbox?
Show us the code you used to display the images…
Also, you have to know that sorting the ListBox change nothing to the data base row order.
This is also because databases don’t have a row order. The database can return rows to you in ANY order, UNLESS you have an ORDER BY clause in your SQL.
Here’s what I put in cell background paint
if column=1 and patt(row)<>nil then
g.DrawPicture (patt(row),0,0,patt(row).width*0.60,40,0,0,patt(row).Width,patt(row).Height)
end if
return true
as for the code to populate patt(row) it’s
dim f AS FolderItem
SequenceData.databaseFile =specialfolder.ApplicationData.child("Guitar SightReader Toolbox").child("database").child("SequenceDataBase")
Dim rs as RecordSet
dim rec as DatabaseRecord
rec = New DatabaseRecord
dim i as integer=0
dim p as Picture
f=specialfolder.ApplicationData.child("Guitar SightReader Toolbox").child("Invertor order.txt")
if f=Nil or f.exists=false then
rs = SequenceData.SQLSelect( "SELECT * FROM Sequences" )
// Clear the passed listbox
SequenceList.DeleteAllRows
SequenceList.GridLinesHorizontal=2
While Not rs.EOF
SequenceList.AddRow (rs.field("Name"))
i=SequenceList.LastIndex
patt(i)=StringtoPicture(rs.field("Image"))
SequenceList.cell(i,2)=rs.field("SequenceID")
rs.MoveNext
Wend
end if
So you’re storing the pictures in your own array, not the Listbox and that’s why they’re not reordering. You’ll have to reorder your array or, which I recommend more, store the picture as either a RowTag or CellTag, and it will move for you.
I’ll try it
Or
While Not rs.EOF
SequenceList.AddRow (rs.field(“Name”))
i=SequenceList.LastIndex
SequenceList.rowtag(i) = i
plus
if column=1 and patt(row)<>nil then
dim actualimage as integer = me.rowtag(row)
g.DrawPicture (patt(actualimage),0,0,patt(actualimage).width*0.60,40,0,0,patt(actualimage).Width,patt(actualimage).Height)
end if
return true
You will need to do something to save the new positions of the list when the window closes, of course.
The problem is that ‘row’ does not change when you re-order the listbox.
Two possible solutions:
1.When you add the data to the listbox store a copy of the index in a cell tag which you can then look up during the paint event.
Populate Data:
While Not rs.EOF
SequenceList.AddRow (rs.field("Name"))
i=SequenceList.LastIndex
patt(i)=StringtoPicture(rs.field("Image"))
SequenceList.cell(i,2)=rs.field("SequenceID")
SequenceList.celltag(i,0)=i
rs.MoveNext
Wend
Paint Event:
Dim index As Integer
index = Me.CellTag(row, 0)
if column=1 and patt(index)<>nil then
g.DrawPicture (patt(index),0,0,patt(index).width*0.60,40,0,0,patt(index).Width,patt(index).Height)
end if
return true
2.Store the picture in a cell tag rather than storing it in an array.
Populate Data:
While Not rs.EOF
SequenceList.AddRow (rs.field("Name"))
i=SequenceList.LastIndex
SequenceList.cell(i,2)=rs.field("SequenceID")
SequenceList.celltag(i,0)=StringtoPicture(rs.field("Image"))
rs.MoveNext
Wend
Paint Event:
Dim p As Picture
p = Me.CellTag(row, 0)
if column=1 and p<>nil then
g.DrawPicture (p,0,0,p.width*0.60,40,0,0,p.Width,p.Height)
end if
return true
Did you do any debugging in order to find out what was going on?
Old method:
While Not rs.EOF
SequenceList.AddRow (rs.field("Name"))
i=SequenceList.LastIndex
patt(i)=StringtoPicture(rs.field("Image"))
SequenceList.cell(i,2)=rs.field("SequenceID")
rs.MoveNext
Wend
new method I propose:
While Not rs.EOF
SequenceList.AddRow (rs.field("Name"))
Bad : i=SequenceList.LastIndex
Good: i=SequenceList.LastAddedRowIndex
var dico as New Dictionary
For rang As Integer = 0 To rs.LastColumnIndex
dico.Value ( rs.ColumnAt(i).Name ) = rs.ColumnAt(i rang)
next
SequenceList.RowTagAt(LastAddedRowIndex ) = dico
patt(i)=StringtoPicture(rs.field("Image"))
SequenceList.cell(i,2)=rs.field("SequenceID")
rs.MoveNext
Wend
Well, all answers were winning!
It works and drags to reorder the lists including the Image (there are 2 - the main screen and the editor (all in the same window)). My question is… how would you keep the order of the list when reopening the tool? My first thought is to textoutput a text file with the list of sequenceIDs. Your thoughts?
Here’s working my code so far:
dim f AS FolderItem
SequenceData.databaseFile =specialfolder.ApplicationData.child("Guitar SightReader Toolbox").child("database").child("SequenceDataBase")
Dim rs as RecordSet
dim rec as DatabaseRecord
rec = New DatabaseRecord
dim i as integer=0
dim p as Picture
SequenceList.DeleteAllRows
SequenceList2.DeleteAllRows
rs = SequenceData.SQLSelect( "SELECT * FROM Sequences" )
While Not rs.EOF
SequenceList.AddRow (rs.field("Name"))
SequenceList2.AddRow (rs.field("Name"))
i=SequenceList.LastIndex
patt(i)=StringtoPicture(rs.field("Image"))
SequenceList.cell(i,2)=rs.field("SequenceID")
SequenceList2.cell(i,2)=rs.field("SequenceID")
SequenceList.celltag(i,0)=i
SequenceList2.celltag(i,0)=i
rs.MoveNext
Wend
and in the cellbackgroundpaint event:
Dim index As Integer
index = SequenceList.CellTag(row, 0)
if column=1 and patt(index)<>nil then
g.DrawPicture (patt(index),0,0,patt(index).width*0.60,40,0,0,patt(index).Width,patt(index).Height)
end if
return true
You can use my class
lb_pptes.xojo_binary_project.zip (12.9 KB)
That’s your answer ?
Uh-oh… Big hiccup.
Using the method
SequenceList.DeleteAllRows
rs = SequenceData.SQLSelect( "SELECT * FROM Sequences" )
While Not rs.EOF
SequenceList.AddRow (rs.field("Name"))
i=SequenceList.LastIndex
patt(i)=StringtoPicture(rs.field("Image"))
SequenceList.cell(i,2)=rs.field("SequenceID")
SequenceList.celltag(i,0)=i
rs.MoveNext
Wend
I have 42 items in the database. It’s all good until I scroll down to the bottom - then I get a out of bounds error in the cellbackgroundpaint event if the row=42. I know the sequencelist listindexs should only up to 41 (0 based list). But for some reason, I have this error. What am I missing? Why is there even a row 42 able to be called here? Apart from this it’s working well.
Thanks to Wayne Goldings example, I changed my cellbackground event to
If row < me.ListCount Then
Dim index As Integer
index = SequenceList2.CellTag(row, 0)
if column=1 and patt(index)<>nil then
g.DrawPicture (patt(index),0,0,patt(index).width*0.60,40,0,0,patt(index).Width,patt(index).Height)
end if
end if
return true
That
If row<me.listcount then… made it work
(Waynes example used row count - but I’m using 2019r1 on high sierra - I don’t want to upgrade until Xojo implements JPEG from HTML again - and because I’m poor)
Method:
SequenceList.DeleteAllRows
rs = SequenceData.SQLSelect( "SELECT * FROM Sequences" )
While Not rs.EOF
SequenceList.AddRow ( rs.field("Name") , "???" , rs.field("SequenceID" )
SequenceList.RowTagAt ( SequenceList.LastAddedRowIndex ) = rs.field("Image")
rs.MoveNext
Wend
Event PaintCellBack:
If row < Me.ListCount Then
Var p As Picture
p = Me.RowTagAt ( row )
DrawPicture( p , X As Double, Y As Double, [destWidth As Double], [destHeight As Double], [sourceX As Double], [sourceY As Double], [sourceWidth As Double], [sourceHeight As Double])
End If