I’m trying to append a image cell to a data source but it’s giving me a error.
MyDataSource is my data source.
theData is just a string, and theImage is a string value of the picture.
the table view has columns called Name and Pic
on AppendData(theData, theImage)
set NewItem to {} --Init the aray
set thePic to image --Init the pic
set thePic to load image (theImage as string) --load the pic. Note: the picture file usually is kept in the resource fork.
set NewItem to {{|Name|:theData,|Pic|:thePic}} --create the data to appen with.
tell MyDataSource to append with NewItem --append it to the datasource
end AppendData
the error happens while appending usually. It’ll gave a class missmatch error.
I’ve also tried setting thePic to image cell, but i cannot load the ‘load image’
i can add a new row like this, but i’d rather append the data instead of changing a created row.
set the_table to table view "images" of scroll view "images" of window "main"
set the_data_source to data source of the_table
tell the_data_source
set the_row to make new data row at end of data rows
set contents of data cell "image" of the_row to (load image (choose file))
end tell
tell the_table to update
You mean to say that you have a table view, for example, in your nib, and dragged a image view cell onto the column header… and it worked! My application kept crashing and giving errors until I got rid of the image cell for some reason… If it worked for you and you can load the image as shown in the second part (set contents of data cell “image” of newRow to load image theImage) I would be happy to hear any tips you had to get that part working… Or if anyone knows about getting a value from a popup cell (I figured out how to create a menu and attach it to the cell… but then I couldn’t figure out how to query it’s value in AS…)…
When you set the menu items for the data cell using something like:
then later, when you get the data for the data cells formatted with the popup, the values will be 1, 2, or 3 and you’ll have to then assign the value to item 1, 2, or 3 of the_list. A little bit of a pain but certainly not too bad. Haven’t tried an image cell formatter yet…
Here’s a demo project with an image cell formatter, but it doesn’t use the append command, it iterates through the images as it loads them into the data source:
That doesn’t make a difference in my project, both lines cause the error “NSImageCell’s object value must be an NSImage”. Only iterating through the images and loading the image into the data cell directly seems to work.
So I have an interest in making this work out… I am doing it in the standard: “make new data row … set contents of data cell …” kind of order and it works, but I am getting a “the variable result is not defined” in my log file the first time I add an item, but the mystery is that my code neither has a log statement, nor uses the result variable… :shock: … I can’t debug this statement because it’s a script closure I generate for a menu item at run time (see my plugins how to thread…)… there is a couple other strange issues poping up. I think it is related to creating the row without having the image in place at the time I make the row…
Okay, here’s what i got. It’s still not what i want though.
I want to be able to make a data row using the append command.
if anyone has any more ideas, i’d like to know.
--Assume that there's a table view called tvdata (inside svData), in a window called frmMain
--frmMain has a Awake from nib handler. There is a .icns file in the project called "Green"
--There's 2 columns called Pic and description. Pic is a image cell.
on awake from nib theObject
if name of theObject is equal to "frmMain" then
set theSource to missing value
set newRow to missing value
set theSource to make new data source at the end of data sources with properties {name:"dsData"}
tell table view "tvData" of scroll view "svData" of window "frmMain"
make new data column at the end of data columns of theSource with properties {name:"Pic"}
make new data column at the end of data columns of theSource with properties {name:"Description"}
end tell
set data source of table view "tvData" of scroll view "svData" of window "frmMain" to theSource
set newRow to make new data row at the end of data rows of theSource
set contents of data cell "Pic" of newRow to load image "Green"
set contents of data cell "Description" of newRow to "My Custum Icon"
tell table view "tvData" of scroll view "svData" of window "frmMain" to update
end if
end awake from nib
Does this actually still work in the current version of xcode?
For me, the NSButtonCell works just fine, but I cannot get the NSImageCell to actually load an image.
when the cell trys to draw I get this…
NSImageCell's object value must be an NSImage.
Here’s how I try to implement it…
set theTable to table view id 5 of scroll view id 4 of view id 3 of tab view id 2 of window id 1
set theDataSource to data source of theTable
set theDataRow to make new data row at end of data rows of theDataSource
tell theDataSource
make new data column at the end of the data columns with properties {name:"valid_name"}
make new data column at the end of the data columns with properties {name:"file_name"}
make new data column at the end of the data columns with properties {name:"file_path"}
end tell
set contents of data cell "valid_name" of theDataRow to "myImage"
in IB I have place the NSImageCell into the first column.
set contents of data cell "valid_name" of theDataRow to "myImage"
“myImage” is a string, which is certainly not an NSImage. You probably mean…
set contents of data cell "valid_name" of theDataRow to myImage
If that deosn’t resolve things for you, this worked for me…
property theDataSource : null
property TableView : null
on awake from nib theObject
if name of theObject is "TableView" then
set TableView to theObject
set theDataSource to make new data source at end of data sources with properties {name:"TableViewDataSource"}
set data source of theObject to theDataSource
tell theDataSource
make new data column at the end of the data columns with properties {name:"Icon"}
make new data column at the end of the data columns with properties {name:"Text"}
end tell
end if
end awake from nib
on clicked theObject
if name of theObject is "AddRow" then
set theRow to make new data row at the end of the data rows of theDataSource
set tmpImage to (load image "Proxy_File")
set content of data cell "Icon" of theRow to tmpImage
delete tmpImage
set content of data cell "Text" of theRow to "Some text"
end if
end clicked
Discussion:
While apple’s data source docs tout datasources as ‘all that and a bag of chips’, I find them confusing and counterproductive… especially when working with table views (vs. outline views). The only advantage to using a data source is in getting the freebie feature of column sorting. If you don’t need table column sorting then I’d recommend that you pitch data sources out the window and stick with using ‘cell value’ and ‘number of rows’ to manually build your tables. This is standard practice in obj-c, and I find it to be more straightforward. With tables, you’re starting with a source list anyways, so why bother building a data source out of it and then working with that when you can just access the list items directly by row index?
Another thing to note is the 3 lines in my code where you load, set, and then delete the image used in the data cell. When you issue a “load image…” command, it retains the image in memory. If you are building a list of 100 items in your code that all use the same icon, issuing the load image command on the same image 100 times will result in 100 copies of the same image saved into your application’s memory space. It’s best to load the image, set it in the data cell, the delete it right away. When you set the image of the data cell, the data cell retains it’s own copy of the image, so the one you loaded is no longer needed.
Hope these help you get it figured out and also cleans up your implementation a bit.
j
Hi I have tried the load, set, and then delete, for when I load an image into my table view image cell.
But the memory does not recover . It appears the delete is not actually deleting the image in memory…
Does anyone have a clue why this would be…
This is the part of the code which is in a repeat loop for each image (in a on drop handler)
set tmpImage to (load image theItem)
set contents of data cell "image" of theDataRow to tmpImage
delete tmpImage
set contents of data cell "file name" of theDataRow to theName
I experienced a similar behavior in one of my apps. It happened when I had an image view and I would quickly change the image in that image view… sometimes the images wouldn’t be deleted (released). This is the code I used to handle that. You could probably adapt it for your use. Basically I found that I could see all of the images that were in memory for the image view using set theImages to images. A list of the current images is returned. Since I only had one image view I only required one image to be in that list. As such if I found more than one I repeated through that list and deleted them again… except the last one which is the one that I needed.
set oldImage to call method "image" of (image view "iv" of scroll view "sv" of window nameMainWindow)
set newImage to load image (item theCounter of posixFileList)
try
delete oldImage
set imageCount to count of images
if imageCount > 1 then -- when switching between large images fast, images can build up... so we delete them to free the memory
set theImages to images
repeat with i from 1 to (imageCount - 1) -- the last image in the list of images is always newImage, so we don't delete that
delete (item i of theImages)
end repeat
end if
end try
The problem is, I am adding images to a table view with image cells.
I drag and drop new images on to the table. It displays a thumbnail in the image column and a file name in the file name column.
Each image is loaded via a repeat loop one at a time.
the repeat loop iterates basically :
repeat with theItem in theFiles
set theDataRow to make new data row at end of data rows of theDataSource
set theName to displayed name of (info for ((POSIX file theItem)))
set tmpImage to (load image theItem)
set contents of data cell "image" of theDataRow to tmpImage
delete tmpImage
set contents of data cell "file name" of theDataRow to theName
end repeat
So there is only one image to ever purge at a time. ??
It maybe my brain is fried, but i do not see a way to incorporate your script…
I would try this… basically after you come out of the repeat loop you have all the images placed in the table that you want. Therefore you know how many images should actually be in memory, which is either the count of theFiles if that’s all you’re showing in the table or it’s the count of rows in the table. My example uses the count of theFiles. Use this after the repeat loop or in an “on idle” handler. I’d probably try an “on idle” handler so that your project continually makes sure that there are no extra images in memory.
try
set imageCount to count of images
if imageCount is greater than count of theFiles then
set theImages to images
repeat with i from 1 to (imageCount - (count of theFiles))
delete (item i of theImages)
end
end
end
This assumes that the line set theImages to images will give you all of the images in memory… which in my image view application it did. You can log theImages to see the list of the images to make sure.
Hi ,
thanks again, but that does not work
image cells…:mad:
.
The memory use stays the same. and goes up rather than down… So I added a simply say to see if the count actually got to the delete. It does not get past 1
try
set imageCount to count of images
say 1
if imageCount is greater than (count of theFiles) then
say 2
set theImages to images
repeat with i from 1 to (imageCount - (count of theFiles))
delete (item i of theImages)
end repeat
end if
end try
try
set imageCount to count of images
say 1
if imageCount is greater than 0 then
say 2
set theImages to images
repeat with i from 1 to (imageCount)
say 3
delete (item i of theImages)
end repeat
end if
end try
So a little bit more playing and I can get to 3 in this. It will say 3 the same amount of times as the number of images I throw on.
i then added a delete images within the other repeat loop ( just after I load and add the image).
Than i only get to 1.
This tells me the images in memory are actually getting deleted.
So why is the Real memory and virtual memory not being released??