带滑块和MIDI的Swift Scroll View

时间:2017-03-25 12:53:48

标签: swift macos scroll xcode8 midi

我使用滚动视图滚动图片。我正在使用滑块1 - 26从数组中检索CGPoint的x轴点。一切都像预期的那样,图像在过渡中是平滑的。

我还设置了一个按钮,按下该按钮从1 - 26开始计数并循环以从数组中为x轴点检索CGPoint。一切都像预期的那样,图像在过渡时是平滑的。

我还设置了MIDI,根据发送到滑块的速度发送数据1 - 26,滑块按预期移动。我还使用MIDI从数组中检索CGPoint的x轴点。不幸的是,虽然它想滚动下面的图片显示发生了什么,你只能看到它滚动的4个图像,你可以通过移动滑块出现时看出

Under Midi Control

我非常有信心Midi正常工作,因为我一直用它来读取数组。我也试过从Midi触发一个虚拟按键。这可以按预期工作,但显示与直接从midi触发相同。只要滚动源自IB组件,似乎一切都很好。

在Midi控制下,滚动条也会断断续续,但如果我设置

clipView.wantsLayer = true 

图片不会在midi下滚动,但滚动条会按预期移动。即使滑块和按钮按预期工作。

我也尝试过playMidi中注释掉的所有内容。同样尝试IB部分中的所有不同参数。

我正处于一个可以帮助的地方。 这是我的代码,希望也能解释我的尝试。 我也尝试了各种

needsDisplay = true 
所有观点

Xcode 8 Swift3 OSX而不是iOS

谢谢你的时间

import Cocoa
import CoreMIDI

class MainWindowController: NSWindowController {
    static var subWindowController: MainWindowController!

    var pointArray:[Double] = [99.00,0.00,40.00,80.00,120.00,160.00,200.00,240.00,280.00,320.00,360.00,400.00,440.00,480.00,520.00,560.00,600.00,640.00,680.00,720.00,760.00,800.00,840.00,880.00,920.00,960.00,1000.00]

    @IBOutlet weak var scrollView: NSScrollView!
    @IBOutlet weak var clipView: NSClipView!
    @IBOutlet weak var ImageView: NSImageView!
    @IBOutlet var scrollerBar: NSScroller!
    @IBOutlet weak var sliderControl: NSSlider!

    var myPointer = CGPoint.init(x: 0.0, y: 0.0)
    var fromArray:Double = 0.0
    var buttonCount = 0

    override func windowDidLoad() {
        super.windowDidLoad()
        MainWindowController.subWindowController = self // USED for midi

        //Initialize midi client
        var midiClient: MIDIClientRef = 0;
        var inPort:MIDIPortRef = 0;
        var src:MIDIEndpointRef = MIDIGetSource(0);
        MIDIClientCreate("MidiTestClient" as CFString, nil, nil, &midiClient);
        MIDIInputPortCreate(midiClient, "MidiTest_InPort" as CFString, MyMIDIReadProc, nil, &inPort);
        MIDIPortConnectSource(inPort, src, &src);

        //Set paramameters
        scrollerBar.doubleValue = 0.9

        let scrollViewSize = NSSize(width: 287, height: 119)
        scrollView.setFrameSize(scrollViewSize)
        let scrollViewColor = CGColor(red: 0.0, green: 0.0, blue: 0.9, alpha: 0.5)
        scrollView.wantsLayer = false
        scrollView.layer?.backgroundColor = scrollViewColor
        scrollView.drawsBackground = false

        let clipViewSize = NSSize(width: 1274, height: 88)
        clipView.setFrameSize(clipViewSize)
        let clipViewColor = CGColor(red: 0.0, green: 0.0, blue: 0.9, alpha: 0.5)
        clipView.wantsLayer = false //If true image freezes but scoller moves with midi
        clipView.layer?.backgroundColor = clipViewColor
        clipView.drawsBackground = false

        let ImageViewSize = NSSize(width: 1274, height: 87)
        ImageView.setFrameSize(ImageViewSize)
        /* let ImageViewColor = CGColor(red: 0.0, green: 0.9, blue: 0.0, alpha: 0.5)
         ImageView.wantsLayer = false
         ImageView.layer?.backgroundColor = ImageViewColor*/

    }//EO Overide


    func playMidi(count:Int){

        //print("MIDi",count)
        let fromCountIndex = count // Gets 1 to 26 from midi

        //Gets double from Array 1 to 26 on Index == 0.0 to 960.0
        fromArray = pointArray[fromCountIndex]

        /*SCROLL BAR THINGS I HAVE TRIED*/
        let scrollerValue = fromArray/960
        scrollerBar.doubleValue = scrollerValue
      /*  scrollerBar.display()
        scrollerBar.isContinuous = true */

        /*CLIP VIEW SCROLL FROM ARRAY TRIGGERED BY MIDI */
        myPointer = CGPoint(x:fromArray,y:0.0)
        clipView.scroll(myPointer)
        /*scrollView.scroll(clipView, to: myPointer)*/

        /*THIS FAKES A BUTTON FIRE BUT STILL SAME PROBLEM*/
        /* let mySelector = #selector(myButton(_:))
         myButton(mySelector as AnyObject)*/

        /* DISPLAY VIEWS I HAVE TRIED*/
        // scrollView.scrollsDynamically = true

        /*MOVES THE SLIDER USING MIDI*/
        sliderControl.integerValue = count

    }//eo playMidi


    @IBAction func myButton(_ sender: AnyObject) {
        fromArray = pointArray[buttonCount]
        myPointer = CGPoint(x:fromArray,y:0.0)
        clipView.scroll(myPointer)
        buttonCount = buttonCount + 1
        if (buttonCount > 26){buttonCount = 0}
        print("buttonCount",buttonCount)
    }

    @IBAction func mySlider(_ sender: AnyObject) {
        let fromSlider = sender.integerValue * 1
        //Gets double from Array 1 to 26 on Index == 0.0 to 960.0 on array set to 40 when using slider moves scroll bar
        fromArray = pointArray[fromSlider]
        myPointer = CGPoint(x:fromArray,y:0.0)
        clipView.scroll(myPointer)
        print("fromSlider",fromSlider)
    }


}//EnD oF thE wORld

1 个答案:

答案 0 :(得分:0)

除了我上面的代码,我没有回答这个问题,而是找到了“绕过”。我真的不为此感到自豪,但它似乎提出了一个问题,也许有人可能会帮助回答。由于上面的代码使用Scroll View无法正常工作,我尝试使用CAScrollLayer。

基本设置如下。我在该视图中有一个视图,我创建了一个Scroll Layer,并在其中创建了一个图层。再如上所述如果我使用计时器来触发滚动视图,一切都很完美。如上所述,如果我使用Midi,则滚动不会发生。所以解决的问题是。 midi 1-26读取点值,但不是尝试将其发送到滚动,而是将其发送到transistion变量。

我在界面上有一个“运行按钮”,这通常可以使用scrollLayerScroll。它仍然以令人难以置信的速度完成此任务。但是它不是生成自己的转换变量,而是使用创建的midi函数。有一段代码可以确保只发送一个唯一的号码。

这种方法很有效,但是对于有史以来最糟糕的编码确实值得一试。

我认为计时器刷新我需要提取的所有内容的方式。我希望有人可能仍然会怜悯和帮助

再次感谢

这里是修改后的代码Xcode 8 Swift3 OSX而不是iOS

import Cocoa
import CoreMIDI

class MainWindowController: NSWindowController {
    static var subWindowController: MainWindowController!

    var myLayer = CALayer()
    var myPointer = CGPoint.init(x: 0.0, y: 0.0)
    var fromArray:Double = 0.0
    var buttonCount = 0
    var pointArray:[Double] = [99.00,0.00,40.00,80.00,120.00,160.00,200.00,240.00,280.00,320.00,360.00,400.00,440.00,480.00,520.00,560.00,600.00,640.00,680.00,720.00,760.00,800.00,840.00,880.00,920.00,960.00,1000.00]

    @IBOutlet weak var myCustomView: NSView!

    var translation: CGFloat = 0.0
    var newTranslation:CGFloat = 0.0
    var comp6:CGFloat = 0.0
    var comp6a:CGFloat = 0.0


    var scrollLayer : CAScrollLayer = {
        let scrollLayer = CAScrollLayer() // 8
        scrollLayer.bounds = CGRect(x: 0.0, y: 0.0, width: 150.0, height: 200.0) // 9
        scrollLayer.position = CGPoint(x: 300/2, y: 180/2) // 10 //not sure about this
        scrollLayer.borderColor = CGColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.8)
        scrollLayer.borderWidth = 5.0 // 12
        scrollLayer.scrollMode = kCAScrollHorizontally // 13
        return scrollLayer
    }()

    var scrollTimer = Timer()
    var layer = CALayer()

    override func windowDidLoad() {
        super.windowDidLoad()
        MainWindowController.subWindowController = self // USED for midi

        //Initialize midi client
        var midiClient: MIDIClientRef = 0;
        var inPort:MIDIPortRef = 0;
        var src:MIDIEndpointRef = MIDIGetSource(0);
        MIDIClientCreate("MidiTestClient" as CFString, nil, nil, &midiClient);
        MIDIInputPortCreate(midiClient, "MidiTest_InPort" as CFString, MyMIDIReadProc, nil, &inPort);
        MIDIPortConnectSource(inPort, src, &src);

        //Set up layer
        let img = NSImage(named: "smallSky.png")
        let imageSize = img?.size
        print (imageSize)
        let layer = CALayer()
        layer.bounds = CGRect(x: 0.0, y: 0.0, width: (imageSize?.width)!, height: (imageSize?.height)!) // 3
        layer.position = CGPoint(x: (imageSize?.width)!/4, y: (imageSize?.height)!/2) // 4
        layer.contents = img//5


        myCustomView.layer?.addSublayer(scrollLayer)
        scrollLayer.addSublayer(layer)

        myCustomView.layer = scrollLayer
        myCustomView.wantsLayer = true

    }//EO Overide


    @IBAction func runButton(_ sender: AnyObject) {
        print("run")
        //Sets of timer at very high Speed
        scrollTimer = Timer.scheduledTimer(timeInterval: 0.0001, target: self, selector: #selector(MainWindowController.scrollLayerScroll as (MainWindowController) -> () -> ()), userInfo: nil, repeats: true)
    }

    func scrollLayerScroll(){//FIRED START FROM RUN BUTTON
        //Collects data from translation and only sends to newTranslation when number is different
        comp6a = translation
        if (comp6a != comp6){
            newTranslation = translation
            print("newTranslation",newTranslation)
            let newPoint = CGPoint(x: newTranslation,y:0.0)
            scrollLayer.scroll(to: newPoint)

        }
        comp6 = comp6a
    }//eo scrollLayerScroll


    func playMidi(count:Int){

        let fromCountIndex = count // Gets 1 to 26 from midi
        fromArray = pointArray[fromCountIndex]
        translation = CGFloat(fromArray)
    }//eo playMidi

}//EnD oF thE wORld