How to scroll efficiently in an NSScrollview with huge amount of data? - cocoa

I'm scrolling in a huge set of data points (CGPoints in a custom view, like a graph) and its obviously slow and laggy. Is there a common way to load and draw only the chunk of data I need to display? Does [[[myScrollview] documentView] documentVisibleRect] the trick?
I also want to zoom in and out and therefore change the data point's detail.
Thanks for any tips.

How you do this is completely up to you. It's your custom view, you can draw whatever you like. Your view controller should keep track of the zoom level and current location and your view should just draw that part of the data.
There's nothing magic that's going to make this easier, you have to program it yourself.

Related

how to translate and scale a NSImage?

I have built so far an application that allows the user to drag and drop images onto a NSImageView. However, I want to be able to move these images by simply clicking on any image and hold down the mouse button to move it's location.
How can I manipulate NSImageView to translate/scale after setting the images down? Is that possible? I've read about the NSAffineTransform, but it seems like that is moving the images before creating the image itself. I already have the images on the canvas, and simply want to click and hold the image and move it with my mouse. Please help anyone!
There are two sides to this.
NSImage is the model object, which you might want to display in different ways, save to disk/archive, etc. If you want to actually change the model (scaling, rotating, etc.), implying a permanent change, then you are going to probably want to look at NSAffineTransform, Quartz drawing, etc.
But you probably didn't mean that. Instead you probably are interested in NSImageView, which is a view object, displaying the contents of the NSImage model object using whatever display attributes are desired. If you only want to change how an image is displayed, not what the actual bytes in the image are, then you are going to manipulate the NSImageView at run-time. You can use NSAffineTransform here as well, but it's somewhat uncommon (and usually unnecessary).
The key thing to note that is the NSImageView inherits from NSView, so you have all its power at your disposal. Take a look at certain methods, such as:
-setFrameSize: - useful for changing the view size, and thus the image display scale
-setFrameOrigin: - useful for changing the view position, and thus the apparent image position
Note again that these have nothing to do with images per se, and apply to all Cocoa views. You may want to take a look at a book like Cocoa Programming for Mac OS X to get you past the basics. (You can then do more interesting things, like rotation, animation, etc.)

Touch to move through images

I have an NSMutableArray of jpg images and I want to be able to touch and, moving my finger from right to left, move through the array of images in order. I've been reading about UIScrollView, but I'm not sure if this accomplishes what I am looking for. It seems to me that UIScrollView is more used for viewing an object that is too large to be displayed entirely on the screen and you need to be able to move to see every part of the object. I need to move to an entirely new image, the next image in my array. What is the best way to go about this?
You certainly can use a UIScrollView for what you want. A scroll view can be used, as you noted, to scroll an area that is too large for the screen. However, you can also use it to scroll through "pages". This is really the best way to do what you want, short of rolling your won scroll view.
There is a property of UIScrollView, called pagingEnabled, which you'll want to set to YES. I suggest that you give it a try. Also, have a look at the UIScrollView documentation and the Scroll View programming guide. It will tell you all that you need to know about UIScrollViews. Also, remember that for proper memory management, you'll want to only load three images at any given time. See this answer that I wrote for more information on that, and on UIScrollViews in general.

Cocoa - efficient view drawing

in my program, I'm implementing a custom view, a bit like a table view. To do so, I have subclassed NSView. Now my question is, what's the most efficient way to draw all the table view cells. Should I just use NSViews or possibly something else, like CALayers?
Thanks!
P.S.: This is on Mac OS X, not on iOS.
Based on your question and comment, I propose two alternatives:
NSCollectionView / NSCollectionViewItem - This is useful only if all of your "cells" (instances of your prototype view) are the same dimensions. That is, you can't have one that's wider or taller than the others (or narrower or shorter). This is highly efficient and a ready part of AppKit. Even with a single column and n rows, it works like a charm.
Roll Your Own - This is harder but gives you flexibility. Much like NSCollectionView / NSCollectionViewItem, you'd have a view that serves as the container and you'd ideally have a view you reuse to draw the various "items" it's showing. Using the same view to set its represented object and "stamp" it into place (pose it and draw it), you can roll through your entire collection in one go then use that same view as the live, active view for whatever selected, focused item you have. Even faster: roll through and cache the images and sizes of each item with your reusable item view and draw all from the cache except the selected item (which would use a live, real view posed in its proper location, updating the cached image of itself as its contents change for when it's not selected). Faster still: 1 live view and 1 "for caching" view, and draw only the computed rects of the cached images that intersect the visible rect (sans the "live" / selected view). Note: the caching will have to be re-done each time the container's frame's width changes, since presumably shrinking horizontally means all items grow vertically. If you can, take advantage of NSOperation / NSOperationQueue to handle the caching in the background, only flagging for re-display when all cached items 0 - n (where n is the highest-indexed item intersecting the visible rect) are available.
I use something very close to the latter in one of my own applications, where the "item" is an entry with varying-length text. I don't employ all the tactics I mentioned in my own solution but most and the performance increase is very satisfying. :-)
Hope this helps.

How does CATransition work?

CATransition is quite unusual. Consider the following code.
CATransition* trans=[CATransition animation];
trans.duration=0.5;
trans.type=kCATransitionFade;
[self.holdingView.layer addAnimation:trans forKey:nil];
self.loadingView.hidden=YES;
self.displayView.hidden=NO;
Notice that nowhere did I tell the transition that I wanted to display the displayView rather than loadingView, so the views must somehow access the transition themselves. Can anyone explain in more detail how this works?
When you add the transition as an animation, an implicit CATransaction is begun. From that point on, all modifications to layer properties are going to be animated rather than immediately applied. The way the CATransition performs this animation to to take a snapshot of the view before the layer properties are changed, and a snapshot of what the view will look like after the layer properties are changed. It then uses a filter (on Mac this is Core Image, but on iPhone I'm guessing it's just hard-coded math) to iterate between those two images over time.
This is a key feature of Core Animation. Your draw logic doesn't generally need to deal with the animation. You're given a graphics context, you draw into it, you're done. The system handles compositing that with other images over time (or rotating it in space, or whatever). So in the case of changing the hidden state, the initial-state fully composited image is blended with the final-state composted image. Very fast on a GPU, and it doesn't really matter what change you made to the view.

Qt - Drawing a Rect/Frame out of a bigger Pixmap image

I've been banging my head about this seemingly easy task and I could really use some help.
I have a wide Image loaded in the gui (using the designer..) and I want to be able to draw only a portion of it, a rectangle.
I need to be able to change this rectangle position over the large image, in order to draw a different part of the larger image at will. In this process the rect must maintain its size.
Using the Ui::MainWindow object I'm able to access the label holding the image and a solution that involves using this option is preferred (in order to keep up with the rest of the code I've already written )
Any solution will be much appreciated :)
Thanks,
Itamar
I would definitely (for ease of use) just place an empty label as placeholder in Designer.
Then implement the paintEvent for this label (delegate it to your own method). You'll have also have to look into QPainter, QPixMap, etc... Should be doable based on these hints and the documentation.
If you want more, I suggest you provide a small code snippet to work upon.
If you want to do this more or less purely through designer, you could put a QScrollArea where you want the portion of the image to appear. If you set the scroll area's scrollbar policy to be never shown, you can then manually change what part is visible via the scroll area widget. However, this would probably be more complex that creating a derived widget and reimplementing the paint function.

Resources