在单击的位置添加新标签 SWIFT
Adding a new label where clicked SWIFT
我想为 MacOS 应用程序编写一个简单的 swift 代码,它会在用户在 window.
中执行鼠标单击的任何地方添加一个新标签
此代码编译但使应用程序崩溃:
@IBOutlet var here2 = [NSTextField]()
var count: Int = 0
func getCoordinates(){
NSEvent.addLocalMonitorForEvents(matching: [.leftMouseDown]) {
if self.location.x < 700 && self.location.y<750 {
self.here2.append(NSTextField.init())
self.here2[self.count].frame.origin = CGPoint(x: self.location.x, y: self.location.y)
self.here2[self.count].stringValue = String(self.count)
print("count is: " + String(self.here2.count))
self.count+=1
}
return [=11=]
}
您不能在 NSTextView
上调用 copy
,这会导致错误消息。
您可以通过对视图进行子类化来实现所有必需的方法,但我建议您以编程方式分配新的文本视图,并在代码中而不是在界面生成器中设置它们的样式。
这是另一个处理复制对象的线程:"[something copyWithZone:]: unrecognized selector sent to instance" when using Bindings / Core Data
这是一种编程方法,可能在终端中 运行。请注意,window.acceptsMouseMovedEvents 设置为 true。
//May be run in Terminal with:
//swiftc label.swift -framework Cocoa -o label && ./label
import Cocoa
class AppDelegate: NSObject, NSApplicationDelegate {
var window : NSWindow!
var here2 = [NSTextField]()
var count: Int = 0
let _wndW : CGFloat = 700
let _wndH : CGFloat = 750
let _labelW : CGFloat = 24
let _labelH : CGFloat = 24
@objc func getCoordinates(_ sender:AnyObject ) {
NSEvent.addLocalMonitorForEvents(matching: [.leftMouseDown]) {
var pt: NSPoint? { self.window.mouseLocationOutsideOfEventStream }
if let location = pt {
let msPt:NSPoint = self.window.contentView!.convert(location, from: nil)
print("x = \(msPt.x) : y = \(msPt.y)")
if msPt.x < (self._wndW - self._labelW) && msPt.y < (self._wndH - self._labelH ) {
self.here2.append(NSTextField.init())
self.here2[self.count].frame = NSMakeRect(msPt.x, msPt.y, self._labelW, self._labelH)
print(self.here2[self.count].frame)
self.window.contentView!.addSubview (self.here2[self.count])
self.here2[self.count].backgroundColor = NSColor.white
self.here2[self.count].isSelectable = false
self.here2[self.count].stringValue = String(self.count)
print("count is: " + String(self.here2.count))
self.count+=1
}
}
return [=10=]
}
}
func buildMenu() {
let mainMenu = NSMenu()
NSApp.mainMenu = mainMenu
// **** App menu **** //
let appMenuItem = NSMenuItem()
mainMenu.addItem(appMenuItem)
let appMenu = NSMenu()
appMenuItem.submenu = appMenu
appMenu.addItem(withTitle: "Quit", action:#selector(NSApplication.terminate), keyEquivalent: "q")
}
func buildWnd() {
window = NSWindow(contentRect:NSMakeRect(0,0,_wndW,_wndH),styleMask:[.titled, .closable, .miniaturizable, .resizable], backing:.buffered, defer:false)
window.center()
window.title = "Swift Test Window"
window.makeKeyAndOrderFront(window)
window.acceptsMouseMovedEvents = true
// **** Button **** //
let myBtn = NSButton (frame:NSMakeRect( _wndW - 180, 15, 135, 24 ))
myBtn.bezelStyle = .rounded
myBtn.autoresizingMask = [.maxXMargin,.minYMargin]
myBtn.title = "Start Label Maker"
myBtn.action = #selector(self.getCoordinates(_:))
window.contentView!.addSubview (myBtn)
// **** Quit btn **** //
let quitBtn = NSButton (frame:NSMakeRect( _wndW - 50, 10, 40, 40 ))
quitBtn.bezelStyle = .circular
quitBtn.autoresizingMask = [.minXMargin,.maxYMargin]
quitBtn.title = "Q"
quitBtn.action = #selector(NSApplication.terminate)
window.contentView!.addSubview(quitBtn)
}
func applicationDidFinishLaunching(_ notification: Notification) {
buildMenu()
buildWnd()
}
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true
}
}
let appDelegate = AppDelegate()
// **** main.swift **** //
let app = NSApplication.shared
app.delegate = appDelegate
app.setActivationPolicy(.regular)
app.activate(ignoringOtherApps:true)
app.run()
您无法在故事板中连接 NSTextField
的数组。在我看来,这是 Xcode 中的错误,IB 不应建立连接。这也是 AppKit 中的一个错误,我尝试了这个并得到了这个奇怪的错误:
Failed to set (contentViewController) user defined inspected property on (NSWindow): [<__NSTimeZone 0x6040000a2280> valueForUndefinedKey:]: this class is not key value coding-compliant for the key identifier.
解决方法:去掉IB中的连接,更改
@IBOutlet var here2 = [NSTextField]()
到
var here2 = [NSTextField]()
@IBOutlet weak var here2TextField: NSTextField!
在 IB 中连接 here2TextField
并将 here2TextField
附加到 viewDidLoad()
中的 here2
。
@Marco:我发布的代码是创建应用程序的编程方法的模板(又名样板)示例。我所做的只是 copy/paste 您的函数进入模板的 AppDelegate class 并将其连接到一个按钮。从那里我修改了您的代码,直到获得所需的结果。该技术不使用 XIB 或故事板,而是要求源代码由作者编写(或使用模板)。好消息是您可以控制您的应用程序,不会有人在您背后做任何事情;你所看到的就是你得到的。缺点是该技术对于真正的大型项目来说很麻烦;为此,我依赖 Xcode 和 XIB。 Xcode 的自动完成功能也非常有用,而使用编程方法您必须依赖 Xcode/Help/DeveloperDocumentation 以及互联网搜索,尤其是 Whosebug(通常其他人遇到了与您遇到的相同问题).代替使用终端的命令行进行每次编译,我使用一个非常简单的编辑器自动化了该过程,该编辑器是使用 Xcode(使用 XIB)在 Swift 中编写的。但是,通过执行以下操作,发布的代码也可以是 Xcode 中的 运行:
1) 使用 Swift 创建一个新的 macOS 应用程序(用户界面是 XIB,但演示不需要)
2) 使用File/New/File添加一个Swift文件并命名为‘main.swift’
3) 在新的 main.swift 文件中,将“import Foundation”更改为“import Cocoa”
4) Copy/paste 将演示的最后五行(标记为 main.swift)放入此文件
5) 进入 Apple 提供的 AppDelegate 文件,删除除“import Cocoa”之外的所有内容
6) Copy/paste 已发布代码的整个 AppDelegate class(一直到您已经使用过的 main.swift 部分)
7) 点击‘运行’按钮,编译应该没有错误。
希望对您有所帮助,祝您项目顺利。感谢发帖。
我想为 MacOS 应用程序编写一个简单的 swift 代码,它会在用户在 window.
中执行鼠标单击的任何地方添加一个新标签此代码编译但使应用程序崩溃:
@IBOutlet var here2 = [NSTextField]()
var count: Int = 0
func getCoordinates(){
NSEvent.addLocalMonitorForEvents(matching: [.leftMouseDown]) {
if self.location.x < 700 && self.location.y<750 {
self.here2.append(NSTextField.init())
self.here2[self.count].frame.origin = CGPoint(x: self.location.x, y: self.location.y)
self.here2[self.count].stringValue = String(self.count)
print("count is: " + String(self.here2.count))
self.count+=1
}
return [=11=]
}
您不能在 NSTextView
上调用 copy
,这会导致错误消息。
您可以通过对视图进行子类化来实现所有必需的方法,但我建议您以编程方式分配新的文本视图,并在代码中而不是在界面生成器中设置它们的样式。
这是另一个处理复制对象的线程:"[something copyWithZone:]: unrecognized selector sent to instance" when using Bindings / Core Data
这是一种编程方法,可能在终端中 运行。请注意,window.acceptsMouseMovedEvents 设置为 true。
//May be run in Terminal with:
//swiftc label.swift -framework Cocoa -o label && ./label
import Cocoa
class AppDelegate: NSObject, NSApplicationDelegate {
var window : NSWindow!
var here2 = [NSTextField]()
var count: Int = 0
let _wndW : CGFloat = 700
let _wndH : CGFloat = 750
let _labelW : CGFloat = 24
let _labelH : CGFloat = 24
@objc func getCoordinates(_ sender:AnyObject ) {
NSEvent.addLocalMonitorForEvents(matching: [.leftMouseDown]) {
var pt: NSPoint? { self.window.mouseLocationOutsideOfEventStream }
if let location = pt {
let msPt:NSPoint = self.window.contentView!.convert(location, from: nil)
print("x = \(msPt.x) : y = \(msPt.y)")
if msPt.x < (self._wndW - self._labelW) && msPt.y < (self._wndH - self._labelH ) {
self.here2.append(NSTextField.init())
self.here2[self.count].frame = NSMakeRect(msPt.x, msPt.y, self._labelW, self._labelH)
print(self.here2[self.count].frame)
self.window.contentView!.addSubview (self.here2[self.count])
self.here2[self.count].backgroundColor = NSColor.white
self.here2[self.count].isSelectable = false
self.here2[self.count].stringValue = String(self.count)
print("count is: " + String(self.here2.count))
self.count+=1
}
}
return [=10=]
}
}
func buildMenu() {
let mainMenu = NSMenu()
NSApp.mainMenu = mainMenu
// **** App menu **** //
let appMenuItem = NSMenuItem()
mainMenu.addItem(appMenuItem)
let appMenu = NSMenu()
appMenuItem.submenu = appMenu
appMenu.addItem(withTitle: "Quit", action:#selector(NSApplication.terminate), keyEquivalent: "q")
}
func buildWnd() {
window = NSWindow(contentRect:NSMakeRect(0,0,_wndW,_wndH),styleMask:[.titled, .closable, .miniaturizable, .resizable], backing:.buffered, defer:false)
window.center()
window.title = "Swift Test Window"
window.makeKeyAndOrderFront(window)
window.acceptsMouseMovedEvents = true
// **** Button **** //
let myBtn = NSButton (frame:NSMakeRect( _wndW - 180, 15, 135, 24 ))
myBtn.bezelStyle = .rounded
myBtn.autoresizingMask = [.maxXMargin,.minYMargin]
myBtn.title = "Start Label Maker"
myBtn.action = #selector(self.getCoordinates(_:))
window.contentView!.addSubview (myBtn)
// **** Quit btn **** //
let quitBtn = NSButton (frame:NSMakeRect( _wndW - 50, 10, 40, 40 ))
quitBtn.bezelStyle = .circular
quitBtn.autoresizingMask = [.minXMargin,.maxYMargin]
quitBtn.title = "Q"
quitBtn.action = #selector(NSApplication.terminate)
window.contentView!.addSubview(quitBtn)
}
func applicationDidFinishLaunching(_ notification: Notification) {
buildMenu()
buildWnd()
}
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true
}
}
let appDelegate = AppDelegate()
// **** main.swift **** //
let app = NSApplication.shared
app.delegate = appDelegate
app.setActivationPolicy(.regular)
app.activate(ignoringOtherApps:true)
app.run()
您无法在故事板中连接 NSTextField
的数组。在我看来,这是 Xcode 中的错误,IB 不应建立连接。这也是 AppKit 中的一个错误,我尝试了这个并得到了这个奇怪的错误:
Failed to set (contentViewController) user defined inspected property on (NSWindow): [<__NSTimeZone 0x6040000a2280> valueForUndefinedKey:]: this class is not key value coding-compliant for the key identifier.
解决方法:去掉IB中的连接,更改
@IBOutlet var here2 = [NSTextField]()
到
var here2 = [NSTextField]()
@IBOutlet weak var here2TextField: NSTextField!
在 IB 中连接 here2TextField
并将 here2TextField
附加到 viewDidLoad()
中的 here2
。
@Marco:我发布的代码是创建应用程序的编程方法的模板(又名样板)示例。我所做的只是 copy/paste 您的函数进入模板的 AppDelegate class 并将其连接到一个按钮。从那里我修改了您的代码,直到获得所需的结果。该技术不使用 XIB 或故事板,而是要求源代码由作者编写(或使用模板)。好消息是您可以控制您的应用程序,不会有人在您背后做任何事情;你所看到的就是你得到的。缺点是该技术对于真正的大型项目来说很麻烦;为此,我依赖 Xcode 和 XIB。 Xcode 的自动完成功能也非常有用,而使用编程方法您必须依赖 Xcode/Help/DeveloperDocumentation 以及互联网搜索,尤其是 Whosebug(通常其他人遇到了与您遇到的相同问题).代替使用终端的命令行进行每次编译,我使用一个非常简单的编辑器自动化了该过程,该编辑器是使用 Xcode(使用 XIB)在 Swift 中编写的。但是,通过执行以下操作,发布的代码也可以是 Xcode 中的 运行:
1) 使用 Swift 创建一个新的 macOS 应用程序(用户界面是 XIB,但演示不需要) 2) 使用File/New/File添加一个Swift文件并命名为‘main.swift’ 3) 在新的 main.swift 文件中,将“import Foundation”更改为“import Cocoa” 4) Copy/paste 将演示的最后五行(标记为 main.swift)放入此文件 5) 进入 Apple 提供的 AppDelegate 文件,删除除“import Cocoa”之外的所有内容 6) Copy/paste 已发布代码的整个 AppDelegate class(一直到您已经使用过的 main.swift 部分) 7) 点击‘运行’按钮,编译应该没有错误。
希望对您有所帮助,祝您项目顺利。感谢发帖。