I'm trying to print a document. The document is an array of NSImageReps, or a single NSPDFImageRep, which has multiple pages. I'm having trouble figuring out how to use the NSPrintOperation class to print this.
The NSPrintOperation seems to need an NSView to print. Do I need to manually add each image into the view at a calculated position and then let 开发者_C百科it do the pagination? that seems like it isn't in the spirit of Cocoa... is there some technique that I'm missing?
Despite this having an accepted answer, it doesn't really answer the basic question, just gives a work-around.
I just had a similar problem (I have an array of objects each rendered by the same NSView
subclass, one per page). Here's how I solved it, without the baroque nonsense of creating one giant view that holds all the pages...
1) We have an NSView
subclass that has a model associated with it (NSImage
in your case, ModelData
in my case)
class BaseView: NSView {
var modelData: ModelData /* Whatever your view needs to draw */
//...
}
2) We have an array var models: [ModelData]
in your document controller.
3) Create a new subclass that will be the printer view.
class PrinterView: BaseView {
var pageIndex: Int = 1
var modelArray: [ModelData]
init(frame: NSRect, models: [ModelData]) {
self.modelArray = models
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("invalid initializer")
}
override func knowsPageRange(_ range: NSRangePointer) -> Bool {
range.pointee.location = 1
range.pointee.length = self.modelArray.count
return true
}
override func rectForPage(_ page: Int) -> NSRect {
self.pageIndex = page
return self.bounds
}
override func draw(_ dirtyRect: NSRect) {
self.model = self.modelArray[self.page - 1] // Pages are 1, not 0, based
super.draw(dirtyRect)
}
} // That's it! That's all...
4) Do this in your document controller:
override func printOperation(withSettings printSettings: [String : Any]) throws -> NSPrintOperation {
self.printInfo.horizontalPagination = .fitPagination
self.printInfo.verticalPagination = .clipPagination
let printView = PrinterView(size: self.printInfo.paperSize, models: self.models)
return NSPrintOperation(view: printView, printInfo: self.printInfo)
}
You can't print something that can't be drawn. NSView is how you draw what you want to print. You can make an NSView subclass just for printing that decides how you want the printing to work (e.g. do you want one NSImageRep for page — ANY size page?) by using NSView's pagination methods. Just override knowsPageRange:
to return YES.
You can create view that that displays what you want to print. Then you use it to create print operation.
You would typically created a view that displays your image. You implement an algorithm to figure out what image you want to display on which page. Then you return number of pages available to print and implement method to print specific page.
- If you have 10 images and you want to print one per page that's easy.
- If you want to print records per page and you have 100 records then you calculate how many records you can fit on a page (using current font size and number of lines per record).
- Then you figure out from records per page how many pages you need to display all records - this is your number of pages (range of pages).
- When requested to print specific range of pages you select the records that should be show on given page and display them.
- See references below on how to implement these steps. See the custom pagination info for example how to implement these steps, it's not difficult.
See Print Programming Topics, or the full example I reference bellow from the book has pagination which I did not included here. Have a look at the custom pagination for more hints.
If you have Document Based application and a view that you want to dump to printer, then in our MyDocument
(or whatever you call it) that extends NSDocument
you would implement:
- (NSPrintOperation *)printOperationWithSettings:(NSDictionary *)ps
error:(NSError **)e
The view then uses standard drawRect:
for drawing.
Example, here PeopleView
just draws a table
of people details, it takes a NSDictonary
of people employees
here:
- (NSPrintOperation *)printOperationWithSettings:(NSDictionary *)ps
error:(NSError **)e
{
PeopleView * view = [[PeopleView alloc] initWithPeople:employees];
NSPrintInfo * printInfo = [self printInfo];
NSPrintOperation * printOp
= [NSPrintOperation printOperationWithView:view
printInfo:printInfo];
[view release];
return printOp;
}
You can look for more details in chapter 27, Printing, in Hillegass' Cocoa Programming For Mac OS X.
For Future reference, I believe the answer is PDFViews. you can add a PDFPage all at once to a PDFView (Via a PDFDocument) and then you can print with printWithInfo:autoRotate:
In theory at least, I have gotten the view created, and the print dialog comes up, but when I hit "print" the dialog doesn't disappear...
But that's a different question.
精彩评论