【问题标题】:NSWindow scaled drawing in contentViewcontentView 中的 NSWindow 缩放绘图
【发布时间】:2018-07-23 07:07:22
【问题描述】:

我正在以编程方式创建一个简单的窗口,我只需要在其内容视图中绘制一些线条。线条所在区域的大小(worldBounds)需要按比例缩小,我假设我需要 contentView 边界原点与 worldBounds 原点相同,以便它可以绘制所有内容。方法是将框架设置为大小的 1/8,然后在 contentView 上使用 setBoundsOriginsetBoundsSize,据我所知是缩放坐标系。

问题是没有绘图出现。窗口以正确的大小出现。我设置了一个函数 drawTestLines 来测试它。如果我删除对 setBounds 的调用,一切都很好,但当然边界与 worldBounds 不匹配。非常感谢任何帮助!

var worldBounds = NSRect()
let scale: CGFloat = 0.125

func drawMap() {

    boundLineStore(lineStore, &worldBounds)
    worldBounds.origin.x -= 8
    worldBounds.origin.y -= 8
    worldBounds.size.width += 16
    worldBounds.size.height += 16

    if !draw {
        return
    }

    let scaled = NSRect(x: 300.0,  // to set the window size/position
                        y: 80,
                        width: worldBounds.size.width*scale,   // 575
                        height: worldBounds.size.height*scale) // 355

    window = NSWindow(contentRect: scaled,
                      styleMask: .titled,
                      backing: .buffered,
                      defer: false)
    window.display()
    window.orderFront(nil)

    window.contentView!.setBoundsSize(worldBounds.size)     // (4593, 2833)
    window.contentView!.setBoundsOrigin(worldBounds.origin) // (-776, -4872)

    // Draw map lines
    window.contentView!.lockFocus()
    drawTestLines(in: window.contentView!)
    window.contentView!.unlockFocus()
}

// for testing
func drawTestLines(in view: NSView) {

    let bottom = view.bounds.minY
    let top = view.bounds.maxY
    let left = view.bounds.minX
    let right = view.bounds.maxX

    NSColor.black.setStroke()
    for i in Int(left)..<Int(right) { // draw vertical lines across the view just to see if it works!
        if i%64 == 0 {
            NSBezierPath.strokeLine(from: NSPoint(x: CGFloat(i), y: bottom), to: NSPoint(x: CGFloat(i), y: top))
        }
    }
    NSBezierPath.strokeLine(from: NSPoint(x: left, y: bottom), to: NSPoint(x: right, y: top))
    NSBezierPath.strokeLine(from: NSPoint.zero, to: NSPoint(x: 50.0, y: 50.0))
}

【问题讨论】:

  • 这不是您在 Cocoa 中绘制的方式。您永远不会(永远!)将焦点锁定在视图上并直接绘制。您覆盖drawRect 并让框架告诉您的视图何时该绘制其内容。见Drawing View Content
  • 如果 origin.y 是 -4872 并且高度是 2833 你什么都看不到。不要更改contentView.bounds.origin。见Understanding a View's Frame and Bounds
  • 谢谢,威勒克。我遇到的问题是要绘制的对象具有负坐标,如果原点必须是(0,0),如何处理?我试过只添加一个带有这些边界的子视图,但仍然没有。

标签: swift cocoa drawing nsview nswindow


【解决方案1】:

实验:创建一个新的 Xcode 项目。换applicationDidFinishLaunching

func applicationDidFinishLaunching(_ aNotification: Notification) {
    if let contentBounds = window.contentView?.bounds {
        let scale: CGFloat = 0.5
        let worldBounds = CGRect(x: 0.0, y: 0.0, width: contentBounds.size.width * scale, height: contentBounds.size.height * scale)
        window.contentView!.bounds = worldBounds
    }
}

将IB中窗口的内容视图的类更改为MyView。添加一个新类MyViewNSView 的子类。将draw 更改为:

override func draw(_ dirtyRect: NSRect) {
    super.draw(dirtyRect)

    let bottom = self.bounds.minY
    let top = self.bounds.maxY
    let left = self.bounds.minX
    let right = self.bounds.maxX

    NSColor.black.setStroke()
    for i in Int(left)..<Int(right) { // draw vertical lines across the view just to see if it works!
        if i%64 == 0 {
            NSBezierPath.strokeLine(from: NSPoint(x: CGFloat(i), y: bottom), to: NSPoint(x: CGFloat(i), y: top))
        }
    }
    NSBezierPath.strokeLine(from: NSPoint(x: left, y: bottom), to: NSPoint(x: right, y: top))
    NSBezierPath.strokeLine(from: NSPoint.zero, to: NSPoint(x: 50.0, y: 50.0))
}

查看更改scaleworldBounds 的来源时会发生什么。

【讨论】:

    猜你喜欢
    • 2013-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多