Gitarrentabulatur darstellen, wie?

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Gitarrentabulatur darstellen, wie?

    Hallo,

    ich möchte gerne eine Gitarrentabulatur darstellen, die Zahlen auf der Tabulatur müssen Individuell eingesetzt werden. (Dies soll nicht der Benutzer machen, sondern kommen später aus eine MusicXML)
    Das ganze sieht dann so aus.

    [Blockierte Grafik: https://www.ultimate-guitar.com/static/article/draft/116184_C3bCiH53IvvROhX-_54633.png]
    Ich habe leider gar keine Ahnung wie man hier beginnt.

    Muss ich ein Bild der Tabulatur ohne Zahlen verwenden und dann die Zahlen auf das Bild zeichnen?
    Oder das ganze Bild zeichnen?

    Die App soll eine macOS App werden evtl. lese ich mich auch noch in SwiftUI ein, so das es auch unter iPad oder iOS läuft, mal sehen. In Moment ist mir nur macOS wichtig.
    Leider habe ich gar keine Ahnung wie man das am besten realisieren könnte und mit welchen Frameworks man dies umsetzt.

    Alles, was ich im Internet gefunden habe, bezieht sich auf iOS und ich habe es nicht geschafft dies auf macOS anzupassen.
    Ich bin neu in Swift und macOS und evtl. fehlen mir die richtigen Schlagwörter und Hintergrundwissen um auf dem rechten Pfad zu kommen.
    Ich hoffe, ihr könnt mir dabei helfen.

    Nützlich wäre, ein Tipp mit was man dies umsetzen würde, Tutorials oder ähnliches. (NSScrollView -> NSImageView) usw.
    Wenn mein Vorhaben für einen Anfänger zu schwer ist, mit was sollte ich mich vorher beschäftigen, um an mein Ziel zu kommen?

    Danke im Voraus.
  • Ich würde mir eine eigene NSView-Klasse erstellen, die einen angepasste drawRect-Methode implementiert. In dieser kannst Du dann z. B. mit Core Graphics zeichnen. Diese View müsste dann in eine NSScrollView eingebettet werden.

    Den Hintergrund in ein Image o. ä. auslagern, lohnt sich meiner Meinung nach nicht, da die paar Linien schnell gezeichnet sind (und sich ja auch beispielsweise an die View-Grösse anpassen sollten).

    Zusätzlich würde ich mir einzelne Methoden schreiben, die 1-2 Parameter mit den Bundnummern bekommen und dann die entsprechenden Symbole wie Slide, Hammer-On, Pull-Off ... zeichnen. Diese kannst Du dann aus o. g. drawRect-Methode heraus aufrufen.

    Ich glaube, auch hier bieten fertige Images mehr Nach- als Vorteile im Handling (Positionierung, Skalierung). Performanz ist bei so einfachen Symbolen kein Thema, eher das Coden der entsprechenden Pfade. Hier mag ein Tool wie PaintCode helfen.

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • Ich habe diesen Link gefunden und am Experimentieren Basic 2D Graphics.
    Ist auch speziell für macOS, obwohl Swift 4 funktionierte die Einführung sehr gut.
    Da mein Englisch nicht so gut ist, brauche ich etwas länger ... aber ich sehe Erfolg.

    Ich schaue mir ein Link auf jeden Fall auch noch durch. Obwohl ich die Einführung durch habe, checke ich es noch nicht so recht. Das braucht noch ein bissel bis es bei mir klick macht ;)

    Sandy
  • Ich würde es ohne CoreGraphics und Quartz2D etc. machen. Das ist hier m.E. Overkill.
    NSBezierPath reicht sehr gut um Linien (und ggf. Kurven) zu malen. NSString hat die Methode drawInRect oder drawAtPoint um Ziffern zu pinseln.
    Und wenn man Bildchen anzeigen will, dann mit NSImage laden und auch hier mit draw innerhalb des NSCutomView machen.
    D.h. es geht alles innerhalb des AppKit.framework.
    1. Subclass von NSView anlegen
    2. draw-Methode implementieren und dort die Dinge die man malen will malen
    Koordinaten leitet man von [self bounds] ab.
    was zu malen ist könnte z.B. über ein Array gesteuert werden für das es einen Setter gibt
    3. im InterfaceBuilder eine Instanz eines NSCustomView anlegen
    4. die View-Klasse wählen
    5. in einen NSScrollView packen

    Hier ist ein Beispiel wie NSBox implementiert sein kann (speziell NSBoxSeparator):
    git.goldelico.com/?p=mySTEP.gi…hb=refs/heads/master#l277
  • Hallo hns, meinst du so etwas in der Art?

    C-Quellcode

    1. let start = CGPoint(x:10, y: 20)
    2. let end = CGPoint(x:400, y:900)
    3. let line = NSBezierPath()
    4. line.move(to: start)
    5. line.line(to: end) // iOS addLine gibt es in macOS nicht.
    6. line.lineWidth = 3
    7. NSColor.red.setStroke()
    8. line.stroke()
    Damit spiele ich gerade etwas rum.

    Mir hat PaintCode sehr gut gefallen von der Idee her, aber 200€ für ein Hobby-Projekt und das auch noch Jährlich, weil ein Abo ist mir etwas zu viel. Deswegen habe ich mal nach alternativen gesucht und bin auf QuartzCode gestoßen. Kostet die Hälfte. Werde mir beides mal testen. Aber falls jemand beide kennt, kann gerne die Vor und Nachteile beide Programme mit uns teilen. Ein Bild gedanklich zu haben und zu Coden scheint mir schon etwas schwer zu sein.
  • Ich habe jetzt mal etwas Code.


    C-Quellcode

    1. import Cocoa
    2. class MyView: NSView {
    3. let length: Double = 900
    4. let cstart: Double = 235.5
    5. let start: Double = 10.5
    6. override func draw(_ dirtyRect: NSRect) {
    7. super.draw(dirtyRect)
    8. // Drawing code here.
    9. var pos = 102.5
    10. let beginPos = pos
    11. for gString in 1...6 {
    12. if gString != 1 {
    13. pos = (pos - 10.0)
    14. }
    15. guitarString(pos: pos)
    16. }
    17. begin(pos: beginPos)
    18. }
    19. func begin(pos: Double) {
    20. let startLineBP = NSBezierPath()
    21. startLineBP.move(to: NSPoint(x: start, y: pos))
    22. startLineBP.curve(to: NSPoint(x: start, y: (pos - 50)), controlPoint1: NSPoint(x: start, y: (pos + 1)), controlPoint2: NSPoint(x: start, y: (pos - 50)))
    23. NSColor.black.setStroke()
    24. startLineBP.lineWidth = 5
    25. startLineBP.stroke()
    26. }
    27. func guitarString(pos: Double) {
    28. let guitarStringBP = NSBezierPath()
    29. guitarStringBP.move(to: NSPoint(x:start, y:pos))
    30. guitarStringBP.curve(to: NSPoint(x:cstart, y:pos), controlPoint1: NSPoint(x:length, y:pos), controlPoint2: NSPoint(x:cstart, y:pos))
    31. NSColor.black.setStroke()
    32. guitarStringBP.lineWidth = 1
    33. guitarStringBP.stroke()
    34. }
    35. }
    Alles anzeigen
    Das Resultat siehe Bild im Anhang.

    Natürlich müsste ich jetzt eine Möglichkeit finden wie ich darauf noch Zahlen und Gitarren-Techniken abbilden kann.
    Da Swift und macOS für mich neu ist, wollte ich euch mal mein Resultat Zeigen damit ihr mir ggf. schon mal den Kopf waschen könnt, weil ich totalen Schrott gemacht habe ;)

    Nochmal vielen Dank an alle, ohne euch hätte ich es so weit nicht geschafft und schon gar nicht in dieser kurzen Zeit. Hab viel dazu gelernt.

    Obwohl meine Frage eigentlich beantwortet ist, würde ich gerne diesen Post noch offen lassen bis ich ein NSScrollView eingebaut habe und die ersten Zahlen und Effekte zum testen integriert habe. Es muss jetzt erst mal nicht Perfekt werden, dies ist ein kleiner Teil meiner App-Idee die ich in viele kleine teile gesplittet habe und festzustellen ob ich es überhaupt gebacken bekomme.

    Bisher bin ich gute Dinge, das ich es, dank euch, hinbekomme.


    LG,
    Sandy
    Dateien
  • Glückwunsch!

    Für mich als nicht-Swifty sieht es soweit gut aus, auch wenn ich die Schleife über die Saiten anders implementieren würde: Da Du für die kommenden Symbole sehr häufig den y-Offset einer Saite benötigen wirst, macht es vielleicht Sinn, diese in einem Array vorzuhalten und nur bei Beginn einer neuen Tabulator-Zeile zu setzen. Oder gar eine Funktion zu nutzen, der Du die Zeilennummer übergibst und die Dir entsprechende Offsets liefert. Aber das ist Optimierungspotential ... und persönlicher Geschmack.

    Den Aufruf von [super.draw(dirtyRect) kannst Du Dir übrigens sparen:

    Apple schrieb:

    If your custom view is a direct NSView subclass, you do not need to call super.
    Vielleicht noch ein Hinweis, solltest Du in der NSScrollView mit Zoom und ggf. auch Kacheln arbeiten: dirtyRect kann eine Untermenge der angezeigten View sein. Du musst Dich also entscheiden, ob Du - wie oben - dirtyRect ignorierst und immer alles zeichnest, oder nur innerhalb des übergebenen Rechteckes. Meistens eine Performanz-Abwägung und bei Deiner Ausgabe m. E. nicht erforderlich.

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • MyMattes schrieb:

    Du musst Dich also entscheiden, ob Du - wie oben - dirtyRect ignorierst und immer alles zeichnest, oder nur innerhalb des übergebenen Rechteckes. Meistens eine Performanz-Abwägung und bei Deiner Ausgabe m. E. nicht erforderlich.
    Hallo Mattes,

    das habe ich noch nicht verstanden.
    Hast Du zufällig ein Beispiel parat oder kennst Dokumentation dazu damit ich mich hier einlesen kann?

    Hab aus mein NSView ein NSCrollViewer gemacht, erkenne noch kein Unterschied, vermutlich noch zu wenig Inhalt um zu scrollen?

    Wegen y Offset und Array usw. Ich habe ja eine MusicXML die ich später mithilfe von Swift MusicXML Library parsen möchte. Habe mich zwar noch nicht damit beschäftigt (steht als nächsten Schritt auf meiner TODO wenn ich mit Grafik durch bin), ich hoffte das ich ermitteln kann aus wie viele Takte ein Song besteht und dann die Linien verlängere. Bzw. später eine Methode Implementiere, der mir immer den nächsten Takt als Tabulatur einfügt (anhängt).

    Hatte heute leider wenig Zeit dafür, aber bisher hab ich hierfür noch keine passende Möglichkeit gefunden (ich Zeichne alles immer neu anstatt anzuhängen bzw. übermale es).

    Und ich muss noch einiges Nachlesen, z.B.

    hns schrieb:

    Koordinaten leitet man von [self bounds] ab.
    Habe zwar Apple Dokumentation zu bounds schon gefunden und gelesen aber noch nicht verstanden was ich damit anfangen soll.

    Deswegen bin ich noch auf der Suche nach Tutorials, Dokumentation usw. das mir weiterhilft das ganze zu verstehen.
  • knasan schrieb:

    Hab aus mein NSView ein NSCrollViewer gemacht, erkenne noch kein Unterschied, vermutlich noch zu wenig Inhalt um zu scrollen?
    Ne, so klappt das nicht, lies Dir mal die Doku zu NSScrollView durch. Grob gesagt hat eine NSScrollView drei Subviews: Die zwei NSScroller und die NSClipView. Letztere ist sozusagen ein "Fenster" in die grössere documentView. Einfach nur von einer anderen Klasse ableiten ist zu wenig, Du musst die o. g. Properties zuweisen.

    Das Thema drawRect hat ein simples Prinzip: Nicht immer muss die ganze View neu gezeichnet werden, falls z. B. ein Teil gar nicht sichtbar ist. Dann wird die Methode mit den Rechtecken als Parameter aufgerufen, die aktualisiert werden müssen. Wenn Du diese ignorierst und immer die gesamte View zeichnest, verschenkst Du Leistung. Dürfte bei den paar Strichen aber vollkommen egal sein.

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • knasan schrieb:

    Habe zwar Apple Dokumentation zu bounds schon gefunden und gelesen aber noch nicht verstanden was ich damit anfangen soll.
    Ja, die Klassendokumentationen sind (eher waren) gut, wenn Du die Syntax, Übergabe- und Rückgabeparameter bestimmter Methoden suchst ... für das allgemeine Verständnis eher weniger.

    Hier helfen „Programming Guides“, viele inzwischen schon im Archiv ... aber zum Glück ändern sich Konzepte nicht so schnell.

    Schau mal im View Programming Guide in das Kapitel „View Geometry“: Dort findest Du eine gute, illustrierte Beschreibung von Frames und Bounds.

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.