在 macOS 中打印多页内容 - 仅在第一页调用绘制方法

问题描述 投票:0回答:1

我正在尝试为 macOS 应用程序实现打印。我创建了一个自定义 NSView 类来处理它,如 Apple 开发人员文档中所述。为了方便多页打印,我遵循了布局页面内容页面中的指导。

我的 PrintView 类代码如下所示:

import Cocoa

class PrintView: NSView {
    let configuration: PrintConfiguration // a struct with some margin info and helpers
    let info = NSPrintInfo.shared
    private(set) var pageNum = 0
    
    private(set) var ranges: [NSRange] = [] // array of pre-calculated page content
    private(set) var content: NSAttributedString 

    override var isFlipped: Bool {
        return true
    }
    
    init(printContent: NSAttributedString, config: PrintConfiguration, ranges: [NSRange]) {
        self.content = printContent
        self.ranges = ranges
        self.configuration = config
        super.init(frame: CGRect(origin: .zero, size: info.paperSize))
        self.frame.size.height = config.printHeight
        info.verticalPagination = .automatic
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    
    override func draw(_ dirtyRect: NSRect) {
        print("Entering draw - dirtyRect: \(dirtyRect)")
        
        let rangeNum = pageNum - 1 // adjust to 0-based for accessing array
        let range = ranges[rangeNum]
        let text = self.content.attributedSubstring(from: range)
        let drawRect = configuration.printRect
        text.draw(in: drawRect)
    }
    
    override func knowsPageRange(_ range: NSRangePointer) -> Bool {
        print("Entering knowsPageRange")
        range.pointee.location = 1
        range.pointee.length = self.ranges.count
        
        print("Page range: \(range.pointee)")
        return true
    }
    
    override func rectForPage(_ page: Int) -> NSRect {
        print("Entering rectForPage")
        self.pageNum = page
        let pageHeight = configuration.printHeight
        let pageNum = CGFloat(page - 1)
        let printRect = CGRect(x: configuration.leftMargin,
                               y: (pageNum * pageHeight) + configuration.topMargin,
                               width: configuration.printWidth,
                               height: configuration.printHeight)
        print("Print rect: \(printRect)")
        return printRect
    }
    
    override func locationOfPrintRect(_ rect: NSRect) -> NSPoint { // only included this method to see if it's called -- it doesn't appear to be required for my implementation
        print("Entering locationOfPrintRect")
        return NSPoint(x: self.configuration.leftMargin, y: self.configuration.topMargin)
    }
}

然后从视图的打印方法中,我可以这样调用它:

        let printView = PrintView(printContent: text, config: printConfiguration, ranges: ranges)

        let info = NSPrintInfo.shared
        
        let printOp = NSPrintOperation(view: printView, printInfo: info)
        printOp.jobTitle = title // a view property
        printOp.canSpawnSeparateThread = true
        printOp.run()

当我从正在运行的应用程序中使用应扩展到两页的文本调用它时,我会在控制台中看到以下内容:

Entering knowsPageRange
Page range: {1, 2}
Entering knowsPageRange
Page range: {1, 2}
Entering rectForPage
Print rect: (40.0, 80.0, 532.0, 652.0)
Entering locationOfPrintRect
Entering draw - dirtyRect: (40.0, 80.0, 532.0, 572.0)
Entering rectForPage
Print rect: (40.0, 732.0, 532.0, 652.0)
Entering locationOfPrintRect

换句话说,我期望被调用两次的所有方法(每个页面一次)都被调用了两次(或者在knowsPageRange的情况下调用更多),除了draw方法。正如该行为所预期的那样,仅呈现第一页。打印预览对话框确实显示要打印的两页,但第二页是空白的。

同样,如果我选择打印对话框选项将打印作业发送到预览应用程序,它只会显示第一页文本。

最初写完我的问题后,我遛了狗,我突然想到我应该尝试使用应该将文本扩展到两页以上的文本。当我回来执行此操作时,它再次创建了正确的页面数,但仅绘制第一页的文本。然而,对于 6 页的文本,分页方法只调用了 3 次:

Entering knowsPageRange
Page range: {1, 6}
Entering knowsPageRange
Page range: {1, 6}
Entering rectForPage
Print rect: (40.0, 80.0, 532.0, 652.0)
Entering locationOfPrintRect
Entering draw - dirtyRect: (40.0, 80.0, 532.0, 572.0)
Entering rectForPage
Print rect: (40.0, 732.0, 532.0, 652.0)
Entering locationOfPrintRect
Entering rectForPage
Print rect: (40.0, 1384.0, 532.0, 652.0)
Entering locationOfPrintRect

如果有人能告诉我我做错了什么,我将不胜感激。

macos cocoa printing
1个回答
0
投票

感谢 @Willeke 引导我走向正确的方向,我的代码现在可以通过对

rectForPage
方法进行以下更改来使用:

    override func rectForPage(_ page: Int) -> NSRect {
        self.pageNum = page
        let printRect = CGRect(x: configuration.leftMargin,
                               y: configuration.topMargin,
                               width: configuration.printWidth,
                               height: configuration.info.paperSize.height - configuration.bottomMargin)
        return printRect
    }
© www.soinside.com 2019 - 2024. All rights reserved.