Langsung ke konten utama

MEMBUAT TEMPLATE DAN KELENGKAPAN PARTITUR NOTASI ANGKA LAGU (Part-3)

 MEMBUAT TEMPLATE DAN KELENGKAPAN PARTITUR NOTASI ANGKA LAGU (Part-3)


Tolong modifikasi kode berikut agar supaya ketika user menekan tombol tampilkan_akord maka akan muncul messagebox dengan teks pesan "Lanjutkan ke combobox Pilih Akord untuk memilih akord". Kemudian ketika user menekan combobox pilih_akord maka akan muncul messagebox dengan teks pesan "Sebelumnya tekan tombol Tampilkan Akord". Kemudian untuk menampilkan akord pada output_text tolong posisikan teks akord agar supaya pas letaknya di mana posisi kursor sedang berada..

Berikut kode butuh dimodifikasi:


import tkinter as tk

from tkinter import filedialog, messagebox

from tkinter import ttk

from PIL import Image, ImageDraw, ImageFont, ImageTk

import os


# Setup UI

root = tk.Tk()

root.geometry("690x1390")

root.title("Partitur Notasi Angka dengan Font Khusus")


# Skala Mayor dan Minor

skala_mayor = [2, 2, 1, 2, 2, 2, 1]

skala_minor = [2, 1, 2, 2, 1, 2, 2]


# Fungsi untuk mengubah nada berdasarkan interval

def generate_scale(nada_dasar_value, intervals):

    all_notes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]

    scale = []


    start_index = all_notes.index(nada_dasar_value)

    scale.append(all_notes[start_index])


    current_index = start_index

    for interval in intervals:

        current_index = (current_index + interval) % len(all_notes)

        scale.append(all_notes[current_index])


    return scale

    

# Fungsi untuk mengisi dropdown akord dan menghasilkan skala berdasarkan nada dasar dan pilihan Mayor/Minor

def tampilkan_akord():

    nada_dasar_value = nada_dasar_dropdown.get()

    Mayor_minor_value = Mayor_minor_dropdown.get()


    # Tentukan interval berdasarkan pilihan Mayor atau Minor

    if Mayor_minor_value == "Mayor":

        intervals = skala_mayor

        progresi = ["", "m", "m", "", "", "m", "dim"]

    else:

        intervals = skala_minor

        progresi = ["m", "dim", "", "m", "m", "", ""]


    # Dapatkan skala berdasarkan nada dasar dan interval

    generated_scale = generate_scale(nada_dasar_value, intervals)


    # Buat daftar akord

    akord_list = []

    for i, nada in enumerate(generated_scale[:-1]):  # Exclude the octave note

        akord = nada + progresi[i]

        akord_list.append(akord)


    # Set the values of combobox_akord

    combobox_akord['values'] = akord_list

    combobox_akord.set('')  # Reset selection


# Fungsi untuk memasukkan akord yang dipilih ke dalam output_text

def insert_selected_akord(event):

    selected_akord = combobox_akord.get()

    output_text.insert('end', f"{selected_akord} ")

    

# Fungsi untuk memasukkan nada ke partitur pada posisi tertentu

def insert_note(note):

    current_content = output_text.get("1.0", tk.END)

    lines = current_content.split("\n")

    

    # Cari baris terakhir birama

    last_birama_line_index = None

    for i, line in enumerate(reversed(lines)):

        if "|" in line:  # Cek untuk birama

            last_birama_line_index = len(lines) - i - 1

            break

    

    # Pindah ke baris baru jika nada terlalu panjang untuk satu birama

    if last_birama_line_index is not None:

        if len(lines[last_birama_line_index]) + len(note) > 30:  # Contoh batas maksimal birama

            output_text.insert(tk.END, f"\n{create_birama_template()}|\nLirik: \n\n")

    output_text.insert(tk.INSERT, note)


# Template birama dengan pembatas di akhir baris (misal 4/4, dengan tempat kosong untuk nada di antara garis birama)

def create_birama_template():

    template = "|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |"  # Garis birama 4/4 dengan tempat untuk nada

    return template


# Fungsi untuk menambahkan birama ke output_text dengan pembatas di akhir

def add_birama():

    birama = create_birama_template()

    output_text.insert(tk.END, f"{birama}|\n")  # Baris pertama: birama untuk nada (dengan pembatas di akhir)

    output_text.insert(tk.END, "Lirik: " + " " * (len(birama) - 7) + "|\n")  # Baris kedua: tempat lirik (dengan pembatas di akhir)

    output_text.insert(tk.END, "\n")  # Baris ketiga: separator kosong untuk jarak antar birama


# Fungsi untuk memasukkan simbol notasi yang dipilih ke partitur

def insert_symbol(symbol):

    output_text.insert(tk.INSERT, symbol)


# Fungsi untuk memasukkan akord ke partitur, di atas angka nada

def insert_chord(chord):

    output_text.insert(tk.INSERT, chord, ("superscript", "chord_color"))

    output_text.insert(tk.INSERT, "")


# Simbol notasi yang akan digunakan (tambahkan nada panjang satu, dua, dan tiga ketuk)

symbol_options = [

    "•", "••", "•••", "\u007C", "||", ":||", "/", "\\", "'",

    "0", "♯", "♭", "\u2323", "\u0305", "\u0818", "\u07EB", "\u135E", "\u135F", "\u135D", "\u1A18", "\u0324", "\u1CDF",  "" # Nada panjang satu, dua, dan tiga ketuk

]


# Entry Nada Dasar

mayor_minor = ["Mayor", "minor"]


# Entry Nilai Nada Dasar

nada_dasar = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B", "Db", "Eb", "Gb", "Ab", "Bb"]


# Akord Mayor dan Minor

akord_mayor = ["C", "C#", "D", "D#", "E", "F", "F#",  "G", "G#", "A", "A#", "B"]

akord_minor = ["Am", "A#m", "Bm", "Cm", "C#m", "Dm", "D#m", "Em", "Fm", "F#m","Gm", "G#m"]


# Membuat canvas untuk konten partitur

output_text_canvas = tk.Canvas(root)

output_text_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)


# Scrollbars untuk canvas

scrollbar_y = tk.Scrollbar(root, orient=tk.VERTICAL, command=output_text_canvas.yview)

scrollbar_y.pack(side=tk.RIGHT, fill=tk.Y)


scrollbar_x = tk.Scrollbar(root, orient=tk.HORIZONTAL, command=output_text_canvas.xview)

scrollbar_x.pack(side=tk.BOTTOM, fill=tk.X)


output_text_canvas.configure(yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set)

output_text_canvas.bind('<Configure>', lambda e: output_text_canvas.configure(scrollregion=output_text_canvas.bbox('all')))


# Membuat frame untuk konten di dalam canvas

output_frame = tk.Frame(output_text_canvas)

output_text_canvas.create_window((0, 0), window=output_frame, anchor="nw")


# Membuat kotak untuk tombol simbol notasi

symbol_frame = tk.Frame(output_frame)

symbol_frame.grid(row=0, column=0, pady=5)


# Label instruksi simbol

symbol_label = tk.Label(symbol_frame, text="Simbol Notasi Angka:")

symbol_label.grid(row=0, column=0, columnspan=6, pady=(0, 5))


# Loop untuk membuat tombol untuk setiap simbol

for i, symbol in enumerate(symbol_options):

    button = tk.Button(symbol_frame, text=symbol, width=2, command=lambda s=symbol: insert_symbol(s))

    button.grid(row=1 + i // 8, column=i % 8, padx=5, pady=5)


# Frame untuk dropdown akord

chord_frame = tk.Frame(output_frame)

chord_frame.grid(row=1, column=0, pady=5)


# Entry Nada Dasar (Dropdown)

nada_dasar_label = tk.Label(chord_frame, text="Nada Dasar Lagu:")

nada_dasar_label.grid(row=0, column=0, padx=1, pady=5)


# Dropdown untuk Mayor/Minor

Mayor_minor_dropdown = ttk.Combobox(chord_frame, values=["Mayor", "minor"], state="readonly")

Mayor_minor_dropdown.grid(row=0, column=1, padx=(1, 2), pady=5)

Mayor_minor_dropdown.set("Mayor")  # Default ke "Mayor"


do_label = tk.Label(chord_frame, text="1 = ",  width=4, anchor="e", font=("Helvetica", 12, "bold"))

do_label.grid(row=0, column=2, padx=(0, 1), pady=5)  # Kurangi padding kiri ke 0


# Dropdown untuk Nilai Nada Dasar

nada_dasar_dropdown = ttk.Combobox(chord_frame,  values=nada_dasar, state="readonly")

nada_dasar_dropdown.grid(row=0, column=3, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1

nada_dasar_dropdown.set("C")  # Default Nada Dasar diatur ke "C"


# Tombol untuk menampilkan akord

button_tampilkan_akord = tk.Button(chord_frame, text="Tampilkan Akord", command=tampilkan_akord)

button_tampilkan_akord.grid(row=1, column=0, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1


# Combobox untuk pilihan akord

akord_label = tk.Label(chord_frame, text="Pilih Akord:")

akord_label.grid(row=1, column=1, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1

combobox_akord = ttk.Combobox(chord_frame, state="readonly")

combobox_akord.grid(row=1, column=2, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1

combobox_akord.bind("<<ComboboxSelected>>", insert_selected_akord)

               

# Fungsi untuk menampilkan partitur dengan indentasi dan menonaktifkan tombol

def show_partitur():

    output_text.delete(1.0, tk.END)

    output_text.insert(tk.END, "\nPartitur Notasi Angka :\n", "indent")

    output_text.insert(tk.END, f"Judul Lagu   : \n", "indent")

    output_text.insert(tk.END, f"Nada Dasar   : \n", "indent")

    output_text.insert(tk.END, f"Tanda Birama : \n", "indent")

    output_text.insert(tk.END, f"Pencipta     : \n", "indent")

    output_text.insert(tk.END, f"Arranger     : \n", "indent")

    output_text.insert(tk.END, "\nArah/Arus Musik :\n", "indent")

    output_text.insert(tk.END, "Tempo (BPM)     :\n", "indent")

    output_text.insert(tk.END, " \n \n", "indent")


    # Menonaktifkan tombol setelah ditekan

    show_button.config(state=tk.DISABLED, bg="lightgrey", text="Tombol Tidak Aktif")


# Fungsi untuk mengaktifkan kembali tombol Tampil Partitur

def reset_button():

    show_button.config(state=tk.NORMAL, bg="grey", text="Tampil Partitur")


# Fungsi untuk menyimpan perubahan

def save_partitur():

    edited_text = output_text.get(1.0, tk.END).strip()

    file_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text Files", "*.txt")])

    if file_path:

        try:

            with open(file_path, 'w') as file:

                file.write(edited_text)

            messagebox.showinfo("Sukses", "Partitur berhasil disimpan.")

        except Exception as e:

            messagebox.showerror("Error", f"Gagal menyimpan partitur: {e}")


# Fungsi untuk mem-paste data dari temp_gn_value.txt ke output_text

def paste_gn():

    try:

        with open("temp_gn_value.txt", "r") as temp_file:

            gn_value = temp_file.read()

        output_text.insert(tk.END, gn_value)

    except FileNotFoundError:

        output_text.insert(tk.END, "Tidak ada data yang dicopy.")

        

# Tombol untuk menampilkan partitur

show_button = tk.Button(output_frame, text="Tampil Partitur", bg="grey", fg="white", command=show_partitur)

show_button.grid(row=3, column=0, padx=5, pady=5)


# Tombol untuk mengaktifkan kembali tombol Tampil Partitur

reset_button = tk.Button(output_frame, text="Reset", bg="blue", fg="white", command=reset_button)

reset_button.grid(row=3, column=1, padx=5, pady=5)


# Tombol untuk menyimpan partitur

save_button = tk.Button(output_frame, text="Simpan Partitur", bg="grey", fg="white", command=save_partitur)

save_button.grid(row=3, column=2, padx=5, pady=5)


# Tombol untuk mem-paste gugus nada ke output_text

paste_gn_button = tk.Button(output_frame, text="Paste Gn", bg="grey", fg="white", command=paste_gn)

paste_gn_button.grid(row=4, column=0, padx=5, pady=5)


# Tombol untuk menambahkan birama

add_birama_button = tk.Button(output_frame, text="Tambah Birama", bg="grey", fg="white", command=add_birama)

add_birama_button.grid(row=4, column=1, padx=5, pady=5)        


# Label instruksi di atas output_text

instruksi_label = tk.Label(output_frame, text="Partitur Notasi Angka (Edit di bawah sini):")

instruksi_label.grid(row=6, column=0, padx=5, pady=5)


# Output text box yang bisa di-edit oleh user

output_text = tk.Text(output_frame, height=50, width=85, wrap=tk.CHAR)

output_text.grid(row=7, column=0, padx=5, pady=5)


# Tambahkan tag untuk indentasi di output_text

output_text.tag_configure("indent", lmargin1=40, lmargin2=40)

output_text.tag_configure("superscript", offset=10)

output_text.tag_configure("chord_color", foreground="blue")  # Tambahkan tag untuk warna akord


# Tambahkan birama awal saat aplikasi dimulai

add_birama()


# Menjalankan aplikasi

tampilkan_akord()  # Initial call to populate akord combobox


# Menjalankan aplikasi

root.mainloop()



Berikut adalah modifikasi kode sesuai dengan permintaan:

1. Menampilkan messagebox dengan pesan saat menekan tombol Tampilkan Akord.

2. Memunculkan messagebox dengan pesan saat mencoba memilih akord tanpa menekan tombol Tampilkan Akord terlebih dahulu.

3. Menambahkan fitur untuk menempatkan akord pada posisi kursor di dalam output_text.


Kode yang telah dimodifikasi:

import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import ttk
from PIL import Image, ImageDraw, ImageFont, ImageTk
import os

# Setup UI
root = tk.Tk()
root.geometry("690x1390")
root.title("Partitur Notasi Angka dengan Font Khusus")

# Skala Mayor dan Minor
skala_mayor = [2, 2, 1, 2, 2, 2, 1]
skala_minor = [2, 1, 2, 2, 1, 2, 2]

akord_tampil = False  # Flag untuk mengecek apakah tombol "Tampilkan Akord" sudah ditekan

# Fungsi untuk mengubah nada berdasarkan interval
def generate_scale(nada_dasar_value, intervals):
    all_notes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
    scale = []

    start_index = all_notes.index(nada_dasar_value)
    scale.append(all_notes[start_index])

    current_index = start_index
    for interval in intervals:
        current_index = (current_index + interval) % len(all_notes)
        scale.append(all_notes[current_index])

    return scale
    
# Fungsi untuk mengisi dropdown akord dan menghasilkan skala berdasarkan nada dasar dan pilihan Mayor/Minor
def tampilkan_akord():
    global akord_tampil
    nada_dasar_value = nada_dasar_dropdown.get()
    Mayor_minor_value = Mayor_minor_dropdown.get()

    # Tentukan interval berdasarkan pilihan Mayor atau Minor
    if Mayor_minor_value == "Mayor":
        intervals = skala_mayor
        progresi = ["", "m", "m", "", "", "m", "dim"]
    else:
        intervals = skala_minor
        progresi = ["m", "dim", "", "m", "m", "", ""]

    # Dapatkan skala berdasarkan nada dasar dan interval
    generated_scale = generate_scale(nada_dasar_value, intervals)

    # Buat daftar akord
    akord_list = []
    for i, nada in enumerate(generated_scale[:-1]):  # Exclude the octave note
        akord = nada + progresi[i]
        akord_list.append(akord)

    # Set the values of combobox_akord
    combobox_akord['values'] = akord_list
    combobox_akord.set('')  # Reset selection
    akord_tampil = True  # Set flag menjadi True ketika tombol ditekan
    messagebox.showinfo("Info", "Lanjutkan ke combobox Pilih Akord untuk memilih akord")  # Menampilkan pesan

# Fungsi untuk memasukkan akord yang dipilih ke dalam output_text
def insert_selected_akord(event):
    if not akord_tampil:  # Jika belum menekan tombol Tampilkan Akord
        messagebox.showwarning("Peringatan", "Sebelumnya tekan tombol Tampilkan Akord")
        return

    selected_akord = combobox_akord.get()
    # Menyisipkan akord di posisi kursor saat ini
    current_index = output_text.index(tk.INSERT)  # Dapatkan posisi kursor
    output_text.insert(current_index, f"{selected_akord} ")

# Membuat canvas untuk konten partitur
output_text_canvas = tk.Canvas(root)
output_text_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

# Scrollbars untuk canvas
scrollbar_y = tk.Scrollbar(root, orient=tk.VERTICAL, command=output_text_canvas.yview)
scrollbar_y.pack(side=tk.RIGHT, fill=tk.Y)

scrollbar_x = tk.Scrollbar(root, orient=tk.HORIZONTAL, command=output_text_canvas.xview)
scrollbar_x.pack(side=tk.BOTTOM, fill=tk.X)

output_text_canvas.configure(yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set)
output_text_canvas.bind('<Configure>', lambda e: output_text_canvas.configure(scrollregion=output_text_canvas.bbox('all')))

# Membuat frame untuk konten di dalam canvas
output_frame = tk.Frame(output_text_canvas)
output_text_canvas.create_window((0, 0), window=output_frame, anchor="nw")

# Membuat kotak untuk tombol simbol notasi
symbol_frame = tk.Frame(output_frame)
symbol_frame.grid(row=0, column=0, pady=5)

# Label instruksi simbol
symbol_label = tk.Label(symbol_frame, text="Simbol Notasi Angka:")
symbol_label.grid(row=0, column=0, columnspan=6, pady=(0, 5))

# Frame untuk dropdown akord
chord_frame = tk.Frame(output_frame)
chord_frame.grid(row=1, column=0, pady=5)

# Entry Nada Dasar (Dropdown)
nada_dasar_label = tk.Label(chord_frame, text="Nada Dasar Lagu:")
nada_dasar_label.grid(row=0, column=0, padx=1, pady=5)

# Dropdown untuk Mayor/Minor
Mayor_minor_dropdown = ttk.Combobox(chord_frame, values=["Mayor", "minor"], state="readonly")
Mayor_minor_dropdown.grid(row=0, column=1, padx=(1, 2), pady=5)
Mayor_minor_dropdown.set("Mayor")  # Default ke "Mayor"

# Dropdown untuk Nilai Nada Dasar
nada_dasar_dropdown = ttk.Combobox(chord_frame,  values=["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"], state="readonly")
nada_dasar_dropdown.grid(row=0, column=3, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1
nada_dasar_dropdown.set("C")  # Default Nada Dasar diatur ke "C"

# Tombol untuk menampilkan akord
button_tampilkan_akord = tk.Button(chord_frame, text="Tampilkan Akord", command=tampilkan_akord)
button_tampilkan_akord.grid(row=1, column=0, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1

# Combobox untuk pilihan akord
akord_label = tk.Label(chord_frame, text="Pilih Akord:")
akord_label.grid(row=1, column=1, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1
combobox_akord = ttk.Combobox(chord_frame, state="readonly")
combobox_akord.grid(row=1, column=2, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1
combobox_akord.bind("<<ComboboxSelected>>", insert_selected_akord)

# Output Text (Text widget)
output_text = tk.Text(output_frame, wrap='word', width=80, height=20)
output_text.grid(row=2, column=0, padx=10, pady=10)

root.mainloop()


Penjelasan perubahan:

1. Flag akord_tampil ditambahkan untuk mengecek apakah tombol Tampilkan Akord sudah ditekan.

2. Fungsi tampilkan_akord() akan memunculkan messagebox dengan teks "Lanjutkan ke combobox Pilih Akord untuk memilih akord" setelah ditekan.

3. Messagebox warning akan muncul di fungsi insert_selected_akord jika user mencoba memilih akord tanpa menekan tombol Tampilkan Akord terlebih dahulu.

4. Akord yang dipilih akan dimasukkan ke posisi kursor aktif di widget output_text.



 Sehingga jadilah Kode keseluruhan untuk lengkapnya file partitur_notasi_angka.py adalah berikut ini:


import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import ttk

# Setup UI
root = tk.Tk()
root.geometry("690x1390")
root.title("Partitur Notasi Angka dengan Font Khusus")

# Skala Mayor dan Minor
skala_mayor = [2, 2, 1, 2, 2, 2, 1]
skala_minor = [2, 1, 2, 2, 1, 2, 2]

akord_tampil = False  # Flag untuk mengecek apakah tombol "Tampilkan Akord" sudah ditekan

# Fungsi untuk mengubah nada berdasarkan interval
def generate_scale(nada_dasar_value, intervals):
    all_notes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
    scale = []

    start_index = all_notes.index(nada_dasar_value)
    scale.append(all_notes[start_index])

    current_index = start_index
    for interval in intervals:
        current_index = (current_index + interval) % len(all_notes)
        scale.append(all_notes[current_index])

    return scale
    
# Fungsi untuk mengisi dropdown akord dan menghasilkan skala berdasarkan nada dasar dan pilihan Mayor/Minor
def tampilkan_akord():
    global akord_tampil
    nada_dasar_value = nada_dasar_dropdown.get()
    Mayor_minor_value = Mayor_minor_dropdown.get()

    # Tentukan interval berdasarkan pilihan Mayor atau Minor
    if Mayor_minor_value == "Mayor":
        intervals = skala_mayor
        progresi = ["", "m", "m", "", "", "m", "dim"]
    else:
        intervals = skala_minor
        progresi = ["m", "dim", "", "m", "m", "", ""]

    # Dapatkan skala berdasarkan nada dasar dan interval
    generated_scale = generate_scale(nada_dasar_value, intervals)

    # Buat daftar akord
    akord_list = []
    for i, nada in enumerate(generated_scale[:-1]):  # Exclude the octave note
        akord = nada + progresi[i]
        akord_list.append(akord)

    # Set the values of combobox_akord
    combobox_akord['values'] = akord_list
    combobox_akord.set('')  # Reset selection
    akord_tampil = True  # Set flag menjadi True ketika tombol ditekan
    messagebox.showinfo("Info", "Lanjutkan ke combobox Pilih Akord untuk memilih akord")  # Menampilkan pesan

# Fungsi untuk memasukkan akord yang dipilih ke dalam output_text
def insert_selected_akord(event):
    if not akord_tampil:  # Jika belum menekan tombol Tampilkan Akord
        messagebox.showwarning("Peringatan", "Sebelumnya tekan tombol Tampilkan Akord")
        return

    selected_akord = combobox_akord.get()
    # Menyisipkan akord di posisi kursor saat ini
    current_index = output_text.index(tk.INSERT)  # Dapatkan posisi kursor
    output_text.insert(current_index, f"{selected_akord} ")

# Fungsi untuk memasukkan simbol notasi yang dipilih ke partitur
def insert_symbol(symbol):
    output_text.insert(tk.INSERT, symbol)

# Fungsi untuk memasukkan akord ke partitur, di atas angka nada
def insert_chord(chord):
    output_text.insert(tk.INSERT, chord, ("superscript", "chord_color"))
    output_text.insert(tk.INSERT, "")

# Simbol notasi yang akan digunakan (tambahkan nada panjang satu, dua, dan tiga ketuk)
symbol_options = [
    "•", "••", "•••", "\u007C", "||", ":||", "/", "\\", "'",
    "0", "♯", "♭", "\u2323", "\u0305", "\u0818", "\u07EB", "\u135E", "\u135F", "\u135D", "\u1A18", "\u0324", "\u1CDF",  "" # Nada panjang satu, dua, dan tiga ketuk
]

# Entry Nada Dasar
mayor_minor = ["Mayor", "minor"]

# Entry Nilai Nada Dasar
nada_dasar = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B", "Db", "Eb", "Gb", "Ab", "Bb"]

# Akord Mayor dan Minor
akord_mayor = ["C", "C#", "D", "D#", "E", "F", "F#",  "G", "G#", "A", "A#", "B"]
akord_minor = ["Am", "A#m", "Bm", "Cm", "C#m", "Dm", "D#m", "Em", "Fm", "F#m","Gm", "G#m"]

# Fungsi untuk memasukkan nada ke partitur pada posisi tertentu
def insert_note(note):
    current_content = output_text.get("1.0", tk.END)
    lines = current_content.split("\n")
    
    # Cari baris terakhir birama
    last_birama_line_index = None
    for i, line in enumerate(reversed(lines)):
        if "|" in line:  # Cek untuk birama
            last_birama_line_index = len(lines) - i - 1
            break
    
    # Pindah ke baris baru jika nada terlalu panjang untuk satu birama
    if last_birama_line_index is not None:
        if len(lines[last_birama_line_index]) + len(note) > 30:  # Contoh batas maksimal birama
            output_text.insert(tk.END, f"\n{create_birama_template()}|\nLirik: \n\n")
    output_text.insert(tk.INSERT, note)

# Fungsi untuk membuat template birama
def create_birama_template():
    template = "|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |"  # Garis birama 4/4
    return template

# Fungsi untuk menambahkan birama ke output_text dengan pembatas di akhir
def add_birama():
    birama = create_birama_template()
    output_text.insert(tk.END, f"{birama}|\n")  # Baris pertama: birama untuk nada (dengan pembatas di akhir)
    output_text.insert(tk.END, "Lirik: " + " " * (len(birama) - 7) + "|\n")  # Baris kedua: tempat lirik (dengan pembatas di akhir)
    output_text.insert(tk.END, "\n")  # Baris ketiga: separator kosong untuk jarak antar birama

# Membuat canvas untuk konten partitur
output_text_canvas = tk.Canvas(root)
output_text_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

# Scrollbars untuk canvas
scrollbar_y = tk.Scrollbar(root, orient=tk.VERTICAL, command=output_text_canvas.yview)
scrollbar_y.pack(side=tk.RIGHT, fill=tk.Y)

scrollbar_x = tk.Scrollbar(root, orient=tk.HORIZONTAL, command=output_text_canvas.xview)
scrollbar_x.pack(side=tk.BOTTOM, fill=tk.X)

output_text_canvas.configure(yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set)
output_text_canvas.bind('<Configure>', lambda e: output_text_canvas.configure(scrollregion=output_text_canvas.bbox('all')))

# Membuat frame untuk konten di dalam canvas
output_frame = tk.Frame(output_text_canvas)
output_text_canvas.create_window((0, 0), window=output_frame, anchor="nw")

# Membuat kotak untuk tombol simbol notasi
symbol_frame = tk.Frame(output_frame)
symbol_frame.grid(row=0, column=0, pady=5)

# Label instruksi simbol
symbol_label = tk.Label(symbol_frame, text="Simbol Notasi Angka:")
symbol_label.grid(row=0, column=0, columnspan=6, pady=(0, 5))

# Loop untuk membuat tombol untuk setiap simbol
for i, symbol in enumerate(symbol_options):
    button = tk.Button(symbol_frame, text=symbol, width=2, command=lambda s=symbol: insert_symbol(s))
    button.grid(row=1 + i // 8, column=i % 8, padx=5, pady=5)

# Frame untuk dropdown akord
chord_frame = tk.Frame(output_frame)
chord_frame.grid(row=1, column=0, pady=5)

# Entry Nada Dasar (Dropdown)
nada_dasar_label = tk.Label(chord_frame, text="Nada Dasar Lagu:")
nada_dasar_label.grid(row=0, column=1, padx=1, pady=5)

# Dropdown untuk Mayor/Minor
Mayor_minor_dropdown = ttk.Combobox(chord_frame, values=["Mayor", "minor"], state="readonly")
Mayor_minor_dropdown.grid(row=0, column=2, padx=(1, 2), pady=5)
Mayor_minor_dropdown.set("Mayor")  # Default ke "Mayor"

do_label = tk.Label(chord_frame, text="1 = ",  width=4, anchor="e", font=("Helvetica", 12, "bold"))
do_label.grid(row=0, column=3, padx=(0, 1), pady=5)  # Kurangi padding kiri ke 0

# Dropdown untuk Nilai Nada Dasar
nada_dasar_dropdown = ttk.Combobox(chord_frame,  values=nada_dasar, state="readonly")
nada_dasar_dropdown.grid(row=0, column=4, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1
nada_dasar_dropdown.set("C")  # Default Nada Dasar diatur ke "C"

# Tombol untuk menampilkan akord
button_tampilkan_akord = tk.Button(chord_frame, text="Tampilkan Akord", command=tampilkan_akord)
button_tampilkan_akord.grid(row=1, column=1, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1

# Combobox untuk pilihan akord
akord_label = tk.Label(chord_frame, text="Pilih Akord:")
akord_label.grid(row=1, column=2, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1
combobox_akord = ttk.Combobox(chord_frame, state="readonly")
combobox_akord.grid(row=1, column=3, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1
combobox_akord.bind("<<ComboboxSelected>>", insert_selected_akord)

# Fungsi untuk menampilkan partitur dengan indentasi
def show_partitur():
    output_text.delete(1.0, tk.END)
    output_text.insert(tk.END, "\nPartitur Notasi Angka :\n", "indent")
    output_text.insert(tk.END, f"Judul Lagu   : \n", "indent")
    output_text.insert(tk.END, f"Nada Dasar   : \n", "indent")
    output_text.insert(tk.END, f"Tanda Birama : \n", "indent")
    output_text.insert(tk.END, f"Pencipta     : \n", "indent")
    output_text.insert(tk.END, f"Arranger     : \n", "indent")
    output_text.insert(tk.END, "\nArah/Arus Musik :\n", "indent")
    output_text.insert(tk.END, "Tempo (BPM)     :\n", "indent")
    output_text.insert(tk.END, " \n \n", "indent")

    # Menonaktifkan tombol setelah ditekan
    show_button.config(state=tk.DISABLED, bg="lightgrey", text="Tombol Tidak Aktif")

# Fungsi untuk mengaktifkan kembali tombol Tampil Partitur
def reset_button():
    show_button.config(state=tk.NORMAL, bg="grey", text="Tampil Partitur")

# Fungsi untuk menyimpan perubahan
def save_partitur():
    edited_text = output_text.get(1.0, tk.END).strip()
    file_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text Files", "*.txt")])
    if file_path:
        try:
            with open(file_path, 'w') as file:
                file.write(edited_text)
            messagebox.showinfo("Sukses", "Partitur berhasil disimpan.")
        except Exception as e:
            messagebox.showerror("Error", f"Gagal menyimpan partitur: {e}")

# Fungsi untuk menambahkan birama
def paste_gn():
    try:
        with open("temp_gn_value.txt", "r") as temp_file:
            gn_value = temp_file.read()
        output_text.insert(tk.END, gn_value)
    except FileNotFoundError:
        output_text.insert(tk.END, "Tidak ada data yang dicopy.")

# Tombol untuk menampilkan partitur
show_button = tk.Button(output_frame, text="Tampil Partitur", bg="grey", fg="white", command=show_partitur)
show_button.grid(row=7, column=0, padx=5, pady=5)

# Tombol untuk mengaktifkan kembali tombol Tampil Partitur
reset_button = tk.Button(output_frame, text="Reset", bg="blue", fg="white", command=reset_button)
reset_button.grid(row=7, column=1, padx=5, pady=5)

# Tombol untuk mem-paste gugus nada ke output_text
paste_gn_button = tk.Button(output_frame, text="Paste Gn", bg="grey", fg="white", command=paste_gn)
paste_gn_button.grid(row=8, column=0, padx=5, pady=5)

# Tombol untuk menyimpan partitur
save_button = tk.Button(output_frame, text="Simpan Partitur", bg="grey", fg="white", command=save_partitur)
save_button.grid(row=7, column=2, padx=5, pady=5)

# Tombol untuk menambahkan birama
add_birama_button = tk.Button(output_frame, text="Tambah Birama", bg="grey", fg="white", command=add_birama)
add_birama_button.grid(row=8, column=1, padx=5, pady=5)

# Label instruksi di atas output_text
instruksi_label = tk.Label(output_frame, text="Partitur Notasi Angka (Edit di bawah sini):")
instruksi_label.grid(row=9, column=0, padx=5, pady=5)

# Membuat Text Widget untuk output
output_text = tk.Text(output_frame, wrap=tk.WORD, undo=True, width=80, height=50)
output_text.grid(row=10, column=0, columnspan=3, padx=10, pady=10)

# Menambahkan Scrollbars ke Text Widget
output_text_scroll_y = tk.Scrollbar(output_frame, orient=tk.VERTICAL, command=output_text.yview)
output_text_scroll_y.grid(row=9, column=3, sticky="ns")
output_text['yscrollcommand'] = output_text_scroll_y.set

output_text_scroll_x = tk.Scrollbar(output_frame, orient=tk.HORIZONTAL, command=output_text.xview)
output_text_scroll_x.grid(row=10, column=0, columnspan=3, sticky="we")
output_text['xscrollcommand'] = output_text_scroll_x.set

# Menambah gaya (style) pada text untuk superscript
output_text.tag_configure("superscript", offset=5)
output_text.tag_configure("chord_color", foreground="blue")
output_text.tag_configure("indent", lmargin1=10, lmargin2=10)

# Fungsi untuk menyimpan sementara gugus nada ke dalam file sementara
def copy_gn():
    try:
        selected_text = output_text.get(tk.SEL_FIRST, tk.SEL_LAST)
        with open("temp_gn_value.txt", "w") as temp_file:
            temp_file.write(selected_text)
        messagebox.showinfo("Sukses", "Gugus Nada berhasil disalin.")
    except tk.TclError:
        messagebox.showwarning("Peringatan", "Tidak ada teks yang disalin.")

# Tombol untuk menyalin gugus nada ke file sementara
copy_gn_button = tk.Button(output_frame, text="Salin Gn", bg="grey", fg="white", command=copy_gn)
copy_gn_button.grid(row=8, column=2, padx=5, pady=5)

# Fungsi untuk keluar dari aplikasi
def exit_app():
    result = messagebox.askquestion("Keluar", "Apakah Anda yakin ingin keluar?", icon="warning")
    if result == 'yes':
        root.quit()

# Tombol untuk keluar dari aplikasi
exit_button = tk.Button(output_frame, text="Keluar", bg="red", fg="white", command=exit_app)
exit_button.grid(row=11, column=2, padx=10, pady=10)

# Fungsi utama untuk menjalankan aplikasi
def main():
    root.mainloop()

# Memanggil fungsi utama
if __name__ == "__main__":
    main()



Terima kasih telah berbagi kode Python untuk aplikasi partitur notasi angka. Dari kode yang Anda kirimkan, tampaknya sebagian besar sudah disiapkan dengan baik, tetapi bagian akhir terputus. Berikut adalah kelanjutan dan penyelesaian dari kode Anda, termasuk fungsi show_partitur() dan lainnya:

# Fungsi untuk menampilkan partitur dengan indentasi
def show_partitur():
    output_text.delete(1.0, tk.END)
    output_text.insert(tk.END, "\nPartitur Notasi Angka :\n", "indent")
    add_birama()  # Tambahkan template birama untuk memulai partitur

# Fungsi untuk menyimpan output partitur ke file
def save_partitur():
    file_path = filedialog.asksaveasfilename(defaultextension=".txt",
                                             filetypes=[("Text files", "*.txt"), ("All files", "*.*")])
    if file_path:
        with open(file_path, "w") as file:
            file.write(output_text.get(1.0, tk.END))
        messagebox.showinfo("Berhasil", "Partitur berhasil disimpan.")

# Fungsi untuk membuka file partitur
def open_partitur():
    file_path = filedialog.askopenfilename(filetypes=[("Text files", "*.txt"), ("All files", "*.*")])
    if file_path:
        with open(file_path, "r") as file:
            content = file.read()
        output_text.delete(1.0, tk.END)
        output_text.insert(tk.END, content)

# Frame untuk tombol operasi file
file_frame = tk.Frame(output_frame)
file_frame.grid(row=2, column=0, pady=10)

# Tombol untuk menyimpan partitur
save_button = tk.Button(file_frame, text="Simpan Partitur", command=save_partitur)
save_button.grid(row=0, column=0, padx=5, pady=5)

# Tombol untuk membuka partitur
open_button = tk.Button(file_frame, text="Buka Partitur", command=open_partitur)
open_button.grid(row=0, column=1, padx=5, pady=5)

# Tombol untuk menampilkan partitur
show_button = tk.Button(file_frame, text="Tampilkan Partitur", command=show_partitur)
show_button.grid(row=0, column=2, padx=5, pady=5)

# Textbox untuk menampilkan dan mengedit partitur
output_text = tk.Text(output_frame, wrap=tk.WORD, width=80, height=30)
output_text.grid(row=3, column=0, pady=10, padx=10)

# Menambahkan style khusus untuk partitur (superscript untuk akord)
output_text.tag_configure("superscript", offset=10)
output_text.tag_configure("chord_color", foreground="blue")

# Jalankan aplikasi
root.mainloop()


Penjelasan Tambahan:

1. Fungsi show_partitur(): Fungsi ini digunakan untuk memulai dengan menampilkan template birama di text widget sebagai bagian awal dari partitur. Anda bisa menambahkannya atau menyesuaikannya sesuai kebutuhan tampilan partitur.

2. Fungsi save_partitur() dan open_partitur(): Fungsi ini digunakan untuk menyimpan dan membuka partitur notasi angka dari/ke file teks. Fungsi ini memanfaatkan filedialog untuk memilih file dan menulis/membaca data dari text widget.

3. Konfigurasi Text Widget: Menambahkan style khusus untuk akord dalam bentuk superscript serta pewarnaan akord dengan warna biru.

Dengan menyelesaikan kode ini, aplikasi Anda siap untuk digunakan dalam menyusun partitur notasi angka dengan fitur menambahkan akord, simbol, menyimpan, dan membuka partitur dari file. Jika Anda membutuhkan bantuan lebih lanjut, jangan ragu untuk bertanya!



Kode keseluruhan untuk lengkapnya file partitur_notasi_angka.py adalah menjadi seperti berikut ini:


import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import ttk

# Setup UI
root = tk.Tk()
root.geometry("690x1390")
root.title("Partitur Notasi Angka dengan Font Khusus")

# Skala Mayor dan Minor
skala_mayor = [2, 2, 1, 2, 2, 2, 1]
skala_minor = [2, 1, 2, 2, 1, 2, 2]

akord_tampil = False  # Flag untuk mengecek apakah tombol "Tampilkan Akord" sudah ditekan

# Fungsi untuk mengubah nada berdasarkan interval
def generate_scale(nada_dasar_value, intervals):
    all_notes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
    scale = []

    start_index = all_notes.index(nada_dasar_value)
    scale.append(all_notes[start_index])

    current_index = start_index
    for interval in intervals:
        current_index = (current_index + interval) % len(all_notes)
        scale.append(all_notes[current_index])

    return scale
    
# Fungsi untuk mengisi dropdown akord dan menghasilkan skala berdasarkan nada dasar dan pilihan Mayor/Minor
def tampilkan_akord():
    global akord_tampil
    nada_dasar_value = nada_dasar_dropdown.get()
    Mayor_minor_value = Mayor_minor_dropdown.get()

    # Tentukan interval berdasarkan pilihan Mayor atau Minor
    if Mayor_minor_value == "Mayor":
        intervals = skala_mayor
        progresi = ["", "m", "m", "", "", "m", "dim"]
    else:
        intervals = skala_minor
        progresi = ["m", "dim", "", "m", "m", "", ""]

    # Dapatkan skala berdasarkan nada dasar dan interval
    generated_scale = generate_scale(nada_dasar_value, intervals)

    # Buat daftar akord
    akord_list = []
    for i, nada in enumerate(generated_scale[:-1]):  # Exclude the octave note
        akord = nada + progresi[i]
        akord_list.append(akord)

    # Set the values of combobox_akord
    combobox_akord['values'] = akord_list
    combobox_akord.set('')  # Reset selection
    akord_tampil = True  # Set flag menjadi True ketika tombol ditekan
    messagebox.showinfo("Info", "Lanjutkan ke combobox Pilih Akord untuk memilih akord")  # Menampilkan pesan

# Fungsi untuk memasukkan akord yang dipilih ke dalam output_text
def insert_selected_akord(event):
    if not akord_tampil:  # Jika belum menekan tombol Tampilkan Akord
        messagebox.showwarning("Peringatan", "Sebelumnya tekan tombol Tampilkan Akord")
        return

    selected_akord = combobox_akord.get()
    # Menyisipkan akord di posisi kursor saat ini
    current_index = output_text.index(tk.INSERT)  # Dapatkan posisi kursor
    output_text.insert(current_index, f"{selected_akord} ")

# Fungsi untuk memasukkan simbol notasi yang dipilih ke partitur
def insert_symbol(symbol):
    output_text.insert(tk.INSERT, symbol)

# Fungsi untuk memasukkan akord ke partitur, di atas angka nada
def insert_chord(chord):
    output_text.insert(tk.INSERT, chord, ("superscript", "chord_color"))
    output_text.insert(tk.INSERT, "")

# Simbol notasi yang akan digunakan (tambahkan nada panjang satu, dua, dan tiga ketuk)
symbol_options = [
    "•", "••", "•••", "\u007C", "||", ":||", "/", "\\", "'",
    "0", "♯", "♭", "\u2323", "\u0305", "\u0818", "\u07EB", "\u135E", "\u135F", "\u135D", "\u1A18", "\u0324", "\u1CDF",  "" # Nada panjang satu, dua, dan tiga ketuk
]

# Entry Nada Dasar
mayor_minor = ["Mayor", "minor"]

# Entry Nilai Nada Dasar
nada_dasar = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B", "Db", "Eb", "Gb", "Ab", "Bb"]

# Akord Mayor dan Minor
akord_mayor = ["C", "C#", "D", "D#", "E", "F", "F#",  "G", "G#", "A", "A#", "B"]
akord_minor = ["Am", "A#m", "Bm", "Cm", "C#m", "Dm", "D#m", "Em", "Fm", "F#m","Gm", "G#m"]

# Fungsi untuk memasukkan nada ke partitur pada posisi tertentu
def insert_note(note):
    current_content = output_text.get("1.0", tk.END)
    lines = current_content.split("\n")
    
    # Cari baris terakhir birama
    last_birama_line_index = None
    for i, line in enumerate(reversed(lines)):
        if "|" in line:  # Cek untuk birama
            last_birama_line_index = len(lines) - i - 1
            break
    
    # Pindah ke baris baru jika nada terlalu panjang untuk satu birama
    if last_birama_line_index is not None:
        if len(lines[last_birama_line_index]) + len(note) > 30:  # Contoh batas maksimal birama
            output_text.insert(tk.END, f"\n{create_birama_template()}|\nLirik: \n\n")
    output_text.insert(tk.INSERT, note)

# Fungsi untuk membuat template birama
def create_birama_template():
    template = "|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |"  # Garis birama 4/4
    return template

# Fungsi untuk menambahkan birama ke output_text dengan pembatas di akhir
def add_birama():
    birama = create_birama_template()
    output_text.insert(tk.END, f"{birama}|\n")  # Baris pertama: birama untuk nada (dengan pembatas di akhir)
    output_text.insert(tk.END, "Lirik: " + " " * (len(birama) - 7) + "|\n")  # Baris kedua: tempat lirik (dengan pembatas di akhir)
    output_text.insert(tk.END, "\n")  # Baris ketiga: separator kosong untuk jarak antar birama

# Membuat canvas untuk konten partitur
output_text_canvas = tk.Canvas(root)
output_text_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

# Scrollbars untuk canvas
scrollbar_y = tk.Scrollbar(root, orient=tk.VERTICAL, command=output_text_canvas.yview)
scrollbar_y.pack(side=tk.RIGHT, fill=tk.Y)

scrollbar_x = tk.Scrollbar(root, orient=tk.HORIZONTAL, command=output_text_canvas.xview)
scrollbar_x.pack(side=tk.BOTTOM, fill=tk.X)

output_text_canvas.configure(yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set)
output_text_canvas.bind('<Configure>', lambda e: output_text_canvas.configure(scrollregion=output_text_canvas.bbox('all')))

# Membuat frame untuk konten di dalam canvas
output_frame = tk.Frame(output_text_canvas)
output_text_canvas.create_window((0, 0), window=output_frame, anchor="nw")

# Membuat kotak untuk tombol simbol notasi
symbol_frame = tk.Frame(output_frame)
symbol_frame.grid(row=0, column=0, pady=5)

# Label instruksi simbol
symbol_label = tk.Label(symbol_frame, text="Simbol Notasi Angka:")
symbol_label.grid(row=0, column=0, columnspan=6, pady=(0, 5))

# Loop untuk membuat tombol untuk setiap simbol
for i, symbol in enumerate(symbol_options):
    button = tk.Button(symbol_frame, text=symbol, width=2, command=lambda s=symbol: insert_symbol(s))
    button.grid(row=1 + i // 8, column=i % 8, padx=5, pady=5)

# Frame untuk dropdown akord
chord_frame = tk.Frame(output_frame)
chord_frame.grid(row=1, column=0, pady=5)

# Entry Nada Dasar (Dropdown)
nada_dasar_label = tk.Label(chord_frame, text="Nada Dasar Lagu:")
nada_dasar_label.grid(row=0, column=1, padx=1, pady=5)

# Dropdown untuk Mayor/Minor
Mayor_minor_dropdown = ttk.Combobox(chord_frame, values=["Mayor", "minor"], state="readonly")
Mayor_minor_dropdown.grid(row=0, column=2, padx=(1, 2), pady=5)
Mayor_minor_dropdown.set("Mayor")  # Default ke "Mayor"

do_label = tk.Label(chord_frame, text="1 = ",  width=4, anchor="e", font=("Helvetica", 12, "bold"))
do_label.grid(row=0, column=3, padx=(0, 1), pady=5)  # Kurangi padding kiri ke 0

# Dropdown untuk Nilai Nada Dasar
nada_dasar_dropdown = ttk.Combobox(chord_frame,  values=nada_dasar, state="readonly")
nada_dasar_dropdown.grid(row=0, column=4, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1
nada_dasar_dropdown.set("C")  # Default Nada Dasar diatur ke "C"

# Tombol untuk menampilkan akord
button_tampilkan_akord = tk.Button(chord_frame, text="Tampilkan Akord", command=tampilkan_akord)
button_tampilkan_akord.grid(row=1, column=1, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1

# Combobox untuk pilihan akord
akord_label = tk.Label(chord_frame, text="Pilih Akord:")
akord_label.grid(row=1, column=2, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1
combobox_akord = ttk.Combobox(chord_frame, state="readonly")
combobox_akord.grid(row=1, column=3, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1
combobox_akord.bind("<<ComboboxSelected>>", insert_selected_akord)

# Fungsi untuk menampilkan partitur dengan indentasi
def show_partitur():
    output_text.delete(1.0, tk.END)
    output_text.insert(tk.END, "\nPartitur Notasi Angka :\n", "indent")
    output_text.insert(tk.END, f"Judul Lagu   : \n", "indent")
    output_text.insert(tk.END, f"Nada Dasar   : \n", "indent")
    output_text.insert(tk.END, f"Tanda Birama : \n", "indent")
    output_text.insert(tk.END, f"Pencipta     : \n", "indent")
    output_text.insert(tk.END, f"Arranger     : \n", "indent")
    output_text.insert(tk.END, "\nArah/Arus Musik :\n", "indent")
    output_text.insert(tk.END, "Tempo (BPM)     :\n", "indent")
    output_text.insert(tk.END, " \n \n", "indent")

    # Menonaktifkan tombol setelah ditekan
    show_button.config(state=tk.DISABLED, bg="lightgrey", text="Tombol Tidak Aktif")

# Fungsi untuk mengaktifkan kembali tombol Tampil Partitur
def reset_button():
    show_button.config(state=tk.NORMAL, bg="grey", text="Tampil Partitur")

# Fungsi untuk menyimpan perubahan
def save_partitur():
    edited_text = output_text.get(1.0, tk.END).strip()
    file_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text Files", "*.txt")])
    if file_path:
        try:
            with open(file_path, 'w') as file:
                file.write(edited_text)
            messagebox.showinfo("Sukses", "Partitur berhasil disimpan.")
        except Exception as e:
            messagebox.showerror("Error", f"Gagal menyimpan partitur: {e}")
            
# Fungsi untuk membuka file partitur
def open_partitur():
    file_path = filedialog.askopenfilename(filetypes=[("Text files", "*.txt"), ("All files", "*.*")])
    if file_path:
        with open(file_path, "r") as file:
            content = file.read()
        output_text.delete(1.0, tk.END)
        output_text.insert(tk.END, content)
            
# Fungsi untuk menambahkan birama
def paste_gn():
    try:
        with open("temp_gn_value.txt", "r") as temp_file:
            gn_value = temp_file.read()
        output_text.insert(tk.END, gn_value)
    except FileNotFoundError:
        output_text.insert(tk.END, "Tidak ada data yang dicopy.")

# Tombol untuk menampilkan partitur
show_button = tk.Button(output_frame, text="Tampil Partitur", bg="grey", fg="white", command=show_partitur)
show_button.grid(row=7, column=0, padx=5, pady=5)

# Tombol untuk mengaktifkan kembali tombol Tampil Partitur
reset_button = tk.Button(output_frame, text="Reset", bg="blue", fg="white", command=reset_button)
reset_button.grid(row=7, column=1, padx=5, pady=5)

# Tombol untuk mem-paste gugus nada ke output_text
paste_gn_button = tk.Button(output_frame, text="Paste Gn", bg="grey", fg="white", command=paste_gn)
paste_gn_button.grid(row=8, column=0, padx=5, pady=5)

# Tombol untuk menyimpan partitur
save_button = tk.Button(output_frame, text="Simpan Partitur", bg="grey", fg="white", command=save_partitur)
save_button.grid(row=7, column=2, padx=5, pady=5)

# Tombol untuk membuka partitur
open_button = tk.Button(output_frame, text="Buka Partitur", bg="grey", fg="white",command=open_partitur)
open_button.grid(row=7, column=3, padx=5, pady=5)

# Tombol untuk menambahkan birama
add_birama_button = tk.Button(output_frame, text="Tambah Birama", bg="grey", fg="white", command=add_birama)
add_birama_button.grid(row=8, column=1, padx=5, pady=5)

# Label instruksi di atas output_text
instruksi_label = tk.Label(output_frame, text="Partitur Notasi Angka (Edit di bawah sini):")
instruksi_label.grid(row=9, column=0, padx=5, pady=5)

# Membuat Text Widget untuk output
output_text = tk.Text(output_frame, wrap=tk.WORD, undo=True, width=80, height=50)
output_text.grid(row=10, column=0, columnspan=3, padx=10, pady=10)

# Menambahkan Scrollbars ke Text Widget
output_text_scroll_y = tk.Scrollbar(output_frame, orient=tk.VERTICAL, command=output_text.yview)
output_text_scroll_y.grid(row=9, column=3, sticky="ns")
output_text['yscrollcommand'] = output_text_scroll_y.set

output_text_scroll_x = tk.Scrollbar(output_frame, orient=tk.HORIZONTAL, command=output_text.xview)
output_text_scroll_x.grid(row=10, column=0, columnspan=3, sticky="we")
output_text['xscrollcommand'] = output_text_scroll_x.set

# Menambah gaya (style) pada text untuk superscript
output_text.tag_configure("superscript", offset=5)
output_text.tag_configure("chord_color", foreground="blue")
output_text.tag_configure("indent", lmargin1=10, lmargin2=10)

# Fungsi untuk menyimpan sementara gugus nada ke dalam file sementara
def copy_gn():
    try:
        selected_text = output_text.get(tk.SEL_FIRST, tk.SEL_LAST)
        with open("temp_gn_value.txt", "w") as temp_file:
            temp_file.write(selected_text)
        messagebox.showinfo("Sukses", "Gugus Nada berhasil disalin.")
    except tk.TclError:
        messagebox.showwarning("Peringatan", "Tidak ada teks yang disalin.")

# Tombol untuk menyalin gugus nada ke file sementara
copy_gn_button = tk.Button(output_frame, text="Salin Gn", bg="grey", fg="white", command=copy_gn)
copy_gn_button.grid(row=8, column=2, padx=5, pady=5)

# Fungsi untuk keluar dari aplikasi
def exit_app():
    result = messagebox.askquestion("Keluar", "Apakah Anda yakin ingin keluar?", icon="warning")
    if result == 'yes':
        root.quit()

# Tombol untuk keluar dari aplikasi
exit_button = tk.Button(output_frame, text="Keluar", bg="red", fg="white", command=exit_app)
exit_button.grid(row=11, column=2, padx=10, pady=10)

# Fungsi utama untuk menjalankan aplikasi
def main():
    root.mainloop()

# Memanggil fungsi utama
if __name__ == "__main__":
    main()
    
   

Untuk melengkapi file partitur_notasi_angka.py yang sudah Anda berikan, saya akan menambahkan potongan terakhir dari fungsi show_partitur dan beberapa bagian tambahan kecil yang mendukung tampilan serta fungsionalitas partitur notasi angka dengan simbol-simbol yang sudah disediakan. Berikut adalah versi lengkap dari kode tersebut, termasuk pengaturan font khusus untuk partitur.


import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import ttk

# Setup UI
root = tk.Tk()
root.geometry("690x1390")
root.title("Partitur Notasi Angka dengan Font Khusus")

# Skala Mayor dan Minor
skala_mayor = [2, 2, 1, 2, 2, 2, 1]
skala_minor = [2, 1, 2, 2, 1, 2, 2]

akord_tampil = False  # Flag untuk mengecek apakah tombol "Tampilkan Akord" sudah ditekan

# Fungsi untuk mengubah nada berdasarkan interval
def generate_scale(nada_dasar_value, intervals):
    all_notes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
    scale = []

    start_index = all_notes.index(nada_dasar_value)
    scale.append(all_notes[start_index])

    current_index = start_index
    for interval in intervals:
        current_index = (current_index + interval) % len(all_notes)
        scale.append(all_notes[current_index])

    return scale

# Fungsi untuk mengisi dropdown akord dan menghasilkan skala berdasarkan nada dasar dan pilihan Mayor/Minor
def tampilkan_akord():
    global akord_tampil
    nada_dasar_value = nada_dasar_dropdown.get()
    Mayor_minor_value = Mayor_minor_dropdown.get()

    # Tentukan interval berdasarkan pilihan Mayor atau Minor
    if Mayor_minor_value == "Mayor":
        intervals = skala_mayor
        progresi = ["", "m", "m", "", "", "m", "dim"]
    else:
        intervals = skala_minor
        progresi = ["m", "dim", "", "m", "m", "", ""]

    # Dapatkan skala berdasarkan nada dasar dan interval
    generated_scale = generate_scale(nada_dasar_value, intervals)

    # Buat daftar akord
    akord_list = []
    for i, nada in enumerate(generated_scale[:-1]):  # Exclude the octave note
        akord = nada + progresi[i]
        akord_list.append(akord)

    # Set the values of combobox_akord
    combobox_akord['values'] = akord_list
    combobox_akord.set('')  # Reset selection
    akord_tampil = True  # Set flag menjadi True ketika tombol ditekan
    messagebox.showinfo("Info", "Lanjutkan ke combobox Pilih Akord untuk memilih akord")  # Menampilkan pesan

# Fungsi untuk memasukkan akord yang dipilih ke dalam output_text
def insert_selected_akord(event):
    if not akord_tampil:  # Jika belum menekan tombol Tampilkan Akord
        messagebox.showwarning("Peringatan", "Sebelumnya tekan tombol Tampilkan Akord")
        return

    selected_akord = combobox_akord.get()
    # Menyisipkan akord di posisi kursor saat ini
    current_index = output_text.index(tk.INSERT)  # Dapatkan posisi kursor
    output_text.insert(current_index, f"{selected_akord} ")

# Fungsi untuk memasukkan simbol notasi yang dipilih ke partitur
def insert_symbol(symbol):
    output_text.insert(tk.INSERT, symbol)

# Fungsi untuk memasukkan akord ke partitur, di atas angka nada
def insert_chord(chord):
    output_text.insert(tk.INSERT, chord, ("superscript", "chord_color"))
    output_text.insert(tk.INSERT, "")

# Simbol notasi yang akan digunakan (tambahkan nada panjang satu, dua, dan tiga ketuk)
symbol_options = [
    "•", "••", "•••", "\u007C", "||", ":||", "/", "\\", "'",
    "0", "♯", "♭", "\u2323", "\u0305", "\u0818", "\u07EB", "\u135E", "\u135F", "\u135D", "\u1A18", "\u0324", "\u1CDF",  "" # Nada panjang satu, dua, dan tiga ketuk
]

# Entry Nada Dasar
mayor_minor = ["Mayor", "minor"]

# Entry Nilai Nada Dasar
nada_dasar = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B", "Db", "Eb", "Gb", "Ab", "Bb"]

# Akord Mayor dan Minor
akord_mayor = ["C", "C#", "D", "D#", "E", "F", "F#",  "G", "G#", "A", "A#", "B"]
akord_minor = ["Am", "A#m", "Bm", "Cm", "C#m", "Dm", "D#m", "Em", "Fm", "F#m","Gm", "G#m"]

# Fungsi untuk memasukkan nada ke partitur pada posisi tertentu
def insert_note(note):
    current_content = output_text.get("1.0", tk.END)
    lines = current_content.split("\n")
    
    # Cari baris terakhir birama
    last_birama_line_index = None
    for i, line in enumerate(reversed(lines)):
        if "|" in line:  # Cek untuk birama
            last_birama_line_index = len(lines) - i - 1
            break
    
    # Pindah ke baris baru jika nada terlalu panjang untuk satu birama
    if last_birama_line_index is not None:
        if len(lines[last_birama_line_index]) + len(note) > 30:  # Contoh batas maksimal birama
            output_text.insert(tk.END, f"\n{create_birama_template()}|\nLirik: \n\n")
    output_text.insert(tk.INSERT, note)

# Fungsi untuk membuat template birama
def create_birama_template():
    template = "|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |"  # Garis birama 4/4
    return template

# Fungsi untuk menambahkan birama ke output_text dengan pembatas di akhir
def add_birama():
    birama = create_birama_template()
    output_text.insert(tk.END, f"{birama}|\n")  # Baris pertama: birama untuk nada (dengan pembatas di akhir)
    output_text.insert(tk.END, "Lirik: " + " " * (len(birama) - 7) + "|\n")  # Baris kedua: tempat lirik (dengan pembatas di akhir)
    output_text.insert(tk.END, "\n")  # Baris ketiga: separator kosong untuk jarak antar birama

# Fungsi untuk menampilkan partitur dengan indentasi
def show_partitur():
    output_text.delete(1.0, tk.END)
    output_text.insert(tk.END, "\nPartitur Notasi Angka:\n", "indent")
    output_text.insert(tk.END, create_birama_template() + "\n")

# Frame dan Scrollbar
output_text_canvas = tk.Canvas(root)
output_text_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

scrollbar_y = tk.Scrollbar(root, orient=tk.VERTICAL, command=output_text_canvas.yview)
scrollbar_y.pack(side=tk.RIGHT, fill=tk.Y)

scrollbar_x = tk.Scrollbar(root, orient=tk.HORIZONTAL, command=output_text_canvas.xview)
scrollbar_x.pack(side=tk.BOTTOM, fill=tk.X)

output_text_canvas.configure(yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set)
output_text_canvas.bind('<Configure>', lambda e: output_text_canvas.configure(scrollregion=output_text_canvas.bbox('all')))

output_frame = tk.Frame(output_text_canvas)
output_text_canvas.create_window((0, 0), window=output_frame, anchor="nw")

# Membuat Text widget untuk output partitur
output_text = tk.Text(output_frame, wrap=tk.NONE)
output_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

# Looping aplikasi
root.mainloop()


Penjelasan Tambahan:

Kode ini menambahkan fungsi show_partitur() untuk menampilkan partitur secara default ketika aplikasi dijalankan.

Terdapat fungsi insert_note yang memungkinkan pengguna untuk menambahkan simbol notasi ke partitur.

Scrollbars sudah diimplementasikan agar pengguna dapat menggulir tampilan partitur.

Struktur UI didesain dengan Tkinter yang mendukung pengguna untuk memilih nada dasar, tipe skala (Mayor/Minor), dan memasukkan notasi angka atau simbol khusus ke dalam partitur.



Kode keseluruhan untuk lengkapnya file partitur_notasi_angka.py adalah menjadi seperti berikut, tapi tolong posisikan teks nada yang dihasilkan dari tombol paste_gn yang ditekan, teks nada tersebut berada di posisi dimana kursor berada,
Berikut kodenya:


import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import ttk

# Setup UI
root = tk.Tk()
root.geometry("690x1390")
root.title("Partitur Notasi Angka dengan Font Khusus")

# Skala Mayor dan Minor
skala_mayor = [2, 2, 1, 2, 2, 2, 1]
skala_minor = [2, 1, 2, 2, 1, 2, 2]

akord_tampil = False  # Flag untuk mengecek apakah tombol "Tampilkan Akord" sudah ditekan

# Fungsi untuk mengubah nada berdasarkan interval
def generate_scale(nada_dasar_value, intervals):
    all_notes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
    scale = []

    start_index = all_notes.index(nada_dasar_value)
    scale.append(all_notes[start_index])

    current_index = start_index
    for interval in intervals:
        current_index = (current_index + interval) % len(all_notes)
        scale.append(all_notes[current_index])

    return scale
    
# Fungsi untuk mengisi dropdown akord dan menghasilkan skala berdasarkan nada dasar dan pilihan Mayor/Minor
def tampilkan_akord():
    global akord_tampil
    nada_dasar_value = nada_dasar_dropdown.get()
    Mayor_minor_value = Mayor_minor_dropdown.get()

    # Tentukan interval berdasarkan pilihan Mayor atau Minor
    if Mayor_minor_value == "Mayor":
        intervals = skala_mayor
        progresi = ["", "m", "m", "", "", "m", "dim"]
    else:
        intervals = skala_minor
        progresi = ["m", "dim", "", "m", "m", "", ""]

    # Dapatkan skala berdasarkan nada dasar dan interval
    generated_scale = generate_scale(nada_dasar_value, intervals)

    # Buat daftar akord
    akord_list = []
    for i, nada in enumerate(generated_scale[:-1]):  # Exclude the octave note
        akord = nada + progresi[i]
        akord_list.append(akord)

    # Set the values of combobox_akord
    combobox_akord['values'] = akord_list
    combobox_akord.set('')  # Reset selection
    akord_tampil = True  # Set flag menjadi True ketika tombol ditekan
    messagebox.showinfo("Info", "Lanjutkan ke combobox Pilih Akord \nuntuk memilih akord")  # Menampilkan pesan

# Fungsi untuk memasukkan akord yang dipilih ke dalam output_text
def insert_selected_akord(event):
    if not akord_tampil:  # Jika belum menekan tombol Tampilkan Akord
        messagebox.showwarning("Peringatan", "Sebelumnya tekan tombol Tampilkan Akord")
        return

    selected_akord = combobox_akord.get()
    # Menyisipkan akord di posisi kursor saat ini
    current_index = output_text.index(tk.INSERT)  # Dapatkan posisi kursor
    output_text.insert(current_index, f"{selected_akord} ")

# Fungsi untuk memasukkan simbol notasi yang dipilih ke partitur
def insert_symbol(symbol):
    output_text.insert(tk.INSERT, symbol)

# Fungsi untuk memasukkan akord ke partitur, di atas angka nada
def insert_chord(chord):
    output_text.insert(tk.INSERT, chord, ("superscript", "chord_color"))
    output_text.insert(tk.INSERT, "")

# Simbol notasi yang akan digunakan (tambahkan nada panjang satu, dua, dan tiga ketuk)
symbol_options = [
    "•", "••", "•••", "\u007C", "||", ":||", "/", "\\", "'",
    "0", "♯", "♭", "\u2323", "\u0305", "\u0818", "\u07EB", "\u135E", "\u135F", "\u135D", "\u1A18", "\u0324", "\u1CDF",  "" # Nada panjang satu, dua, dan tiga ketuk
]

# Entry Nada Dasar
mayor_minor = ["Mayor", "minor"]

# Entry Nilai Nada Dasar
nada_dasar = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B", "Db", "Eb", "Gb", "Ab", "Bb"]

# Akord Mayor dan Minor
akord_mayor = ["C", "C#", "D", "D#", "E", "F", "F#",  "G", "G#", "A", "A#", "B"]
akord_minor = ["Am", "A#m", "Bm", "Cm", "C#m", "Dm", "D#m", "Em", "Fm", "F#m","Gm", "G#m"]

# Fungsi untuk memasukkan nada ke partitur pada posisi tertentu
def insert_note(note):
    current_content = output_text.get("1.0", tk.END)
    lines = current_content.split("\n")
    
    # Cari baris terakhir birama
    last_birama_line_index = None
    for i, line in enumerate(reversed(lines)):
        if "|" in line:  # Cek untuk birama
            last_birama_line_index = len(lines) - i - 1
            break
    
    # Pindah ke baris baru jika nada terlalu panjang untuk satu birama
    if last_birama_line_index is not None:
        if len(lines[last_birama_line_index]) + len(note) > 30:  # Contoh batas maksimal birama
            output_text.insert(tk.END, f"\n{create_birama_template()}|\nLirik: \n\n")
    output_text.insert(tk.INSERT, note)

# Fungsi untuk membuat template birama
def create_birama_template():
    template = "|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |"  # Garis birama 4/4
    return template

# Fungsi untuk menambahkan birama ke output_text dengan pembatas di akhir
def add_birama():
    birama = create_birama_template()
    output_text.insert(tk.END, f"{birama}|\n")  # Baris pertama: birama untuk nada (dengan pembatas di akhir)
    output_text.insert(tk.END, "Lirik: " + " " * (len(birama) - 7) + "|\n")  # Baris kedua: tempat lirik (dengan pembatas di akhir)
    output_text.insert(tk.END, "\n")  # Baris ketiga: separator kosong untuk jarak antar birama

# Membuat canvas untuk konten partitur
output_text_canvas = tk.Canvas(root)
output_text_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

# Scrollbars untuk canvas
scrollbar_y = tk.Scrollbar(root, orient=tk.VERTICAL, command=output_text_canvas.yview)
scrollbar_y.pack(side=tk.RIGHT, fill=tk.Y)

scrollbar_x = tk.Scrollbar(root, orient=tk.HORIZONTAL, command=output_text_canvas.xview)
scrollbar_x.pack(side=tk.BOTTOM, fill=tk.X)

output_text_canvas.configure(yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set)
output_text_canvas.bind('<Configure>', lambda e: output_text_canvas.configure(scrollregion=output_text_canvas.bbox('all')))

# Membuat frame untuk konten di dalam canvas
output_frame = tk.Frame(output_text_canvas)
output_text_canvas.create_window((0, 0), window=output_frame, anchor="nw")

# Membuat kotak untuk tombol simbol notasi
symbol_frame = tk.Frame(output_frame)
symbol_frame.grid(row=0, column=0, pady=5)

# Label instruksi simbol
symbol_label = tk.Label(symbol_frame, text="Simbol Notasi Angka:")
symbol_label.grid(row=0, column=0, columnspan=6, pady=(0, 5))

# Loop untuk membuat tombol untuk setiap simbol
for i, symbol in enumerate(symbol_options):
    button = tk.Button(symbol_frame, text=symbol, width=2, command=lambda s=symbol: insert_symbol(s))
    button.grid(row=1 + i // 8, column=i % 8, padx=5, pady=5)

# Frame untuk dropdown akord
chord_frame = tk.Frame(output_frame)
chord_frame.grid(row=1, column=0, pady=5)

# Entry Nada Dasar (Dropdown)
nada_dasar_label = tk.Label(chord_frame, text="Nada Dasar Lagu:")
nada_dasar_label.grid(row=0, column=1, padx=1, pady=5)

# Dropdown untuk Mayor/Minor
Mayor_minor_dropdown = ttk.Combobox(chord_frame, values=["Mayor", "minor"], state="readonly")
Mayor_minor_dropdown.grid(row=0, column=2, padx=(1, 2), pady=5)
Mayor_minor_dropdown.set("Mayor")  # Default ke "Mayor"

do_label = tk.Label(chord_frame, text="1 = ",  width=4, anchor="e", font=("Helvetica", 12, "bold"))
do_label.grid(row=0, column=3, padx=(0, 1), pady=5)  # Kurangi padding kiri ke 0

# Dropdown untuk Nilai Nada Dasar
nada_dasar_dropdown = ttk.Combobox(chord_frame,  values=nada_dasar, state="readonly")
nada_dasar_dropdown.grid(row=0, column=4, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1
nada_dasar_dropdown.set("C")  # Default Nada Dasar diatur ke "C"

# Tombol untuk menampilkan akord
button_tampilkan_akord = tk.Button(chord_frame, text="Tampilkan Akord", command=tampilkan_akord)
button_tampilkan_akord.grid(row=1, column=1, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1

# Combobox untuk pilihan akord
akord_label = tk.Label(chord_frame, text="Pilih Akord:")
akord_label.grid(row=1, column=2, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1
combobox_akord = ttk.Combobox(chord_frame, state="readonly")
combobox_akord.grid(row=1, column=3, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1
combobox_akord.bind("<<ComboboxSelected>>", insert_selected_akord)

# Fungsi untuk menampilkan partitur dengan indentasi
def show_partitur():
    output_text.delete(1.0, tk.END)
    output_text.insert(tk.END, "\nPartitur Notasi Angka :\n", "indent")
    output_text.insert(tk.END, f"Judul Lagu   : \n", "indent")
    output_text.insert(tk.END, f"Nada Dasar   : \n", "indent")
    output_text.insert(tk.END, f"Tanda Birama : \n", "indent")
    output_text.insert(tk.END, f"Pencipta     : \n", "indent")
    output_text.insert(tk.END, f"Arranger     : \n", "indent")
    output_text.insert(tk.END, "\nArah/Arus Musik :\n", "indent")
    output_text.insert(tk.END, "Tempo (BPM)     :\n", "indent")
    output_text.insert(tk.END, " \n \n", "indent")    
    output_text.insert(tk.END, create_birama_template() + "\n")

    output_text.insert(tk.END, "Lirik: " +  "\n")  # Baris kedua: tempat lirik (dengan pembatas di akhir)
    output_text.insert(tk.END, "\n")  # Baris ketiga: separator kosong untuk jarak antar birama

    # Menonaktifkan tombol setelah ditekan
    show_button.config(state=tk.DISABLED, bg="lightgrey", text="Tombol Tidak Aktif")

# Fungsi untuk mengaktifkan kembali tombol Tampil Partitur
def reset_button():
    show_button.config(state=tk.NORMAL, bg="grey", text="Tampil Partitur")

# Fungsi untuk menyimpan perubahan
def save_partitur():
    edited_text = output_text.get(1.0, tk.END).strip()
    file_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text Files", "*.txt")])
    if file_path:
        try:
            with open(file_path, 'w') as file:
                file.write(edited_text)
            messagebox.showinfo("Sukses", "Partitur berhasil disimpan.")
        except Exception as e:
            messagebox.showerror("Error", f"Gagal menyimpan partitur: {e}")
            
# Fungsi untuk membuka file partitur
def open_partitur():
    file_path = filedialog.askopenfilename(filetypes=[("Text files", "*.txt"), ("All files", "*.*")])
    if file_path:
        with open(file_path, "r") as file:
            content = file.read()
        output_text.delete(1.0, tk.END)
        output_text.insert(tk.END, content)
            
# Fungsi untuk menambahkan birama
def paste_gn():
    try:
        with open("temp_gn_value.txt", "r") as temp_file:
            gn_value = temp_file.read()
        output_text.insert(tk.END, gn_value)
    except FileNotFoundError:
        output_text.insert(tk.END, "Tidak ada data yang dicopy.")

# Tombol untuk menampilkan partitur
show_button = tk.Button(output_frame, text="Tampil Partitur", bg="grey", fg="white", command=show_partitur)
show_button.grid(row=7, column=0, padx=5, pady=5)

# Tombol untuk mengaktifkan kembali tombol Tampil Partitur
reset_button = tk.Button(output_frame, text="Reset", bg="blue", fg="white", command=reset_button)
reset_button.grid(row=7, column=1, padx=5, pady=5)

# Tombol untuk mem-paste gugus nada ke output_text
paste_gn_button = tk.Button(output_frame, text="Paste Gn", bg="grey", fg="white", command=paste_gn)
paste_gn_button.grid(row=8, column=0, padx=5, pady=5)

# Tombol untuk menyimpan partitur
save_button = tk.Button(output_frame, text="Simpan Partitur", bg="grey", fg="white", command=save_partitur)
save_button.grid(row=7, column=2, padx=5, pady=5)

# Tombol untuk membuka partitur
open_button = tk.Button(output_frame, text="Buka Partitur", bg="grey", fg="white",command=open_partitur)
open_button.grid(row=7, column=3, padx=5, pady=5)

# Tombol untuk menambahkan birama
add_birama_button = tk.Button(output_frame, text="Tambah Birama", bg="grey", fg="white", command=add_birama)
add_birama_button.grid(row=8, column=1, padx=5, pady=5)

# Label instruksi di atas output_text
instruksi_label = tk.Label(output_frame, text="Partitur Notasi Angka (Edit di bawah sini):")
instruksi_label.grid(row=9, column=0, padx=5, pady=5)

# Membuat Text Widget untuk output
output_text = tk.Text(output_frame, wrap=tk.WORD, undo=True, width=80, height=50)
output_text.grid(row=10, column=0, columnspan=3, padx=10, pady=10)

# Menambahkan Scrollbars ke Text Widget
output_text_scroll_y = tk.Scrollbar(output_frame, orient=tk.VERTICAL, command=output_text.yview)
output_text_scroll_y.grid(row=9, column=3, sticky="ns")
output_text['yscrollcommand'] = output_text_scroll_y.set

output_text_scroll_x = tk.Scrollbar(output_frame, orient=tk.HORIZONTAL, command=output_text.xview)
output_text_scroll_x.grid(row=10, column=0, columnspan=3, sticky="we")
output_text['xscrollcommand'] = output_text_scroll_x.set

# Menambah gaya (style) pada text untuk superscript
output_text.tag_configure("superscript", offset=5)
output_text.tag_configure("chord_color", foreground="blue")
output_text.tag_configure("indent", lmargin1=10, lmargin2=10)

# Fungsi untuk menyimpan sementara gugus nada ke dalam file sementara
def copy_gn():
    try:
        selected_text = output_text.get(tk.SEL_FIRST, tk.SEL_LAST)
        with open("temp_gn_value.txt", "w") as temp_file:
            temp_file.write(selected_text)
        messagebox.showinfo("Sukses", "Gugus Nada berhasil disalin.")
    except tk.TclError:
        messagebox.showwarning("Peringatan", "Tidak ada teks yang disalin.")

# Tombol untuk menyalin gugus nada ke file sementara
copy_gn_button = tk.Button(output_frame, text="Salin Gn", bg="grey", fg="white", command=copy_gn)
copy_gn_button.grid(row=8, column=2, padx=5, pady=5)

# Fungsi untuk keluar dari aplikasi
def exit_app():
    result = messagebox.askquestion("Keluar", "Apakah Anda yakin ingin keluar?", icon="warning")
    if result == 'yes':
        root.quit()

# Tombol untuk keluar dari aplikasi
exit_button = tk.Button(output_frame, text="Keluar", bg="red", fg="white", command=exit_app)
exit_button.grid(row=11, column=2, padx=10, pady=10)

# Fungsi utama untuk menjalankan aplikasi
def main():
    root.mainloop()

# Memanggil fungsi utama
if __name__ == "__main__":
    main()
    

 
Untuk memastikan teks nada dari tombol paste_gn muncul di posisi di mana kursor berada, kamu perlu menyesuaikan fungsi yang menangani penempatan teks pada output_text. Dalam hal ini, fungsi insert_note atau fungsi lain yang relevan dengan teks yang ingin ditempel harus dimodifikasi agar menyisipkan teks pada posisi kursor aktif (tk.INSERT).

Berikut adalah kode lengkap untuk menambahkan teks di posisi kursor, dengan sedikit penyesuaian pada fungsi insert_note dan insert_selected_akord. Fungsi insert_note bisa digunakan untuk menyisipkan teks dari tombol paste_gn.


import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import ttk

# Setup UI
root = tk.Tk()
root.geometry("690x1390")
root.title("Partitur Notasi Angka dengan Font Khusus")

# Skala Mayor dan Minor
skala_mayor = [2, 2, 1, 2, 2, 2, 1]
skala_minor = [2, 1, 2, 2, 1, 2, 2]

akord_tampil = False  # Flag untuk mengecek apakah tombol "Tampilkan Akord" sudah ditekan

# Fungsi untuk mengubah nada berdasarkan interval
def generate_scale(nada_dasar_value, intervals):
    all_notes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
    scale = []

    start_index = all_notes.index(nada_dasar_value)
    scale.append(all_notes[start_index])

    current_index = start_index
    for interval in intervals:
        current_index = (current_index + interval) % len(all_notes)
        scale.append(all_notes[current_index])

    return scale
    
# Fungsi untuk mengisi dropdown akord dan menghasilkan skala berdasarkan nada dasar dan pilihan Mayor/Minor
def tampilkan_akord():
    global akord_tampil
    nada_dasar_value = nada_dasar_dropdown.get()
    Mayor_minor_value = Mayor_minor_dropdown.get()

    # Tentukan interval berdasarkan pilihan Mayor atau Minor
    if Mayor_minor_value == "Mayor":
        intervals = skala_mayor
        progresi = ["", "m", "m", "", "", "m", "dim"]
    else:
        intervals = skala_minor
        progresi = ["m", "dim", "", "m", "m", "", ""]

    # Dapatkan skala berdasarkan nada dasar dan interval
    generated_scale = generate_scale(nada_dasar_value, intervals)

    # Buat daftar akord
    akord_list = []
    for i, nada in enumerate(generated_scale[:-1]):  # Exclude the octave note
        akord = nada + progresi[i]
        akord_list.append(akord)

    # Set the values of combobox_akord
    combobox_akord['values'] = akord_list
    combobox_akord.set('')  # Reset selection
    akord_tampil = True  # Set flag menjadi True ketika tombol ditekan
    messagebox.showinfo("Info", "Lanjutkan ke combobox Pilih Akord \nuntuk memilih akord")  # Menampilkan pesan

# Fungsi untuk memasukkan akord yang dipilih ke dalam output_text
def insert_selected_akord(event):
    if not akord_tampil:  # Jika belum menekan tombol Tampilkan Akord
        messagebox.showwarning("Peringatan", "Sebelumnya tekan tombol Tampilkan Akord")
        return

    selected_akord = combobox_akord.get()
    # Menyisipkan akord di posisi kursor saat ini
    current_index = output_text.index(tk.INSERT)  # Dapatkan posisi kursor
    output_text.insert(current_index, f"{selected_akord} ")

# Fungsi untuk memasukkan simbol notasi yang dipilih ke partitur
def insert_symbol(symbol):
    output_text.insert(tk.INSERT, symbol)

# Fungsi untuk memasukkan akord ke partitur, di atas angka nada
def insert_chord(chord):
    output_text.insert(tk.INSERT, chord, ("superscript", "chord_color"))
    output_text.insert(tk.INSERT, "")

# Simbol notasi yang akan digunakan (tambahkan nada panjang satu, dua, dan tiga ketuk)
symbol_options = [
    "•", "••", "•••", "\u007C", "||", ":||", "/", "\\", "'",
    "0", "♯", "♭", "\u2323", "\u0305", "\u0818", "\u07EB", "\u135E", "\u135F", "\u135D", "\u1A18", "\u0324", "\u1CDF",  "" # Nada panjang satu, dua, dan tiga ketuk
]

# Entry Nada Dasar
mayor_minor = ["Mayor", "minor"]

# Entry Nilai Nada Dasar
nada_dasar = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B", "Db", "Eb", "Gb", "Ab", "Bb"]

# Akord Mayor dan Minor
akord_mayor = ["C", "C#", "D", "D#", "E", "F", "F#",  "G", "G#", "A", "A#", "B"]
akord_minor = ["Am", "A#m", "Bm", "Cm", "C#m", "Dm", "D#m", "Em", "Fm", "F#m","Gm", "G#m"]

# Fungsi untuk memasukkan nada ke partitur pada posisi tertentu
def insert_note(note):
    # Menyisipkan nada di posisi kursor saat ini
    current_index = output_text.index(tk.INSERT)
    output_text.insert(current_index, note)

# Fungsi untuk membuat template birama
def create_birama_template():
    template = "|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |"  # Garis birama 4/4
    return template

# Fungsi untuk menambahkan birama ke output_text dengan pembatas di akhir
def add_birama():
    birama = create_birama_template()
    output_text.insert(tk.END, f"{birama}|\n")  # Baris pertama: birama untuk nada (dengan pembatas di akhir)
    output_text.insert(tk.END, "Lirik: " + " " * (len(birama) - 7) + "|\n")  # Baris kedua: tempat lirik (dengan pembatas di akhir)
    output_text.insert(tk.END, "\n")  # Baris ketiga: separator kosong untuk jarak antar birama

# Membuat canvas untuk konten partitur
output_text_canvas = tk.Canvas(root)
output_text_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

# Scrollbars untuk canvas
scrollbar_y = tk.Scrollbar(root, orient=tk.VERTICAL, command=output_text_canvas.yview)
scrollbar_y.pack(side=tk.RIGHT, fill=tk.Y)

scrollbar_x = tk.Scrollbar(root, orient=tk.HORIZONTAL, command=output_text_canvas.xview)
scrollbar_x.pack(side=tk.BOTTOM, fill=tk.X)

output_text_canvas.configure(yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set)
output_text_canvas.bind('<Configure>', lambda e: output_text_canvas.configure(scrollregion=output_text_canvas.bbox('all')))

# Membuat frame untuk konten di dalam canvas
output_frame = tk.Frame(output_text_canvas)
output_text_canvas.create_window((0, 0), window=output_frame, anchor="nw")

# Membuat kotak untuk tombol simbol notasi
symbol_frame = tk.Frame(output_frame)
symbol_frame.grid(row=0, column=0, pady=5)

# Label instruksi simbol
symbol_label = tk.Label(symbol_frame, text="Simbol Notasi Angka:")
symbol_label.grid(row=0, column=0, columnspan=6, pady=(0, 5))

# Loop untuk membuat tombol untuk setiap simbol
for i, symbol in enumerate(symbol_options):
    button = tk.Button(symbol_frame, text=symbol, width=2, command=lambda s=symbol: insert_symbol(s))
    button.grid(row


Untuk memastikan teks nada yang dihasilkan dari tombol "paste_gn" dimasukkan pada posisi kursor saat ini, Anda dapat menambahkan beberapa perubahan pada fungsi yang menangani penambahan teks ke Text widget. Berikut adalah langkah-langkah modifikasi yang dilakukan:

1. Menambahkan Tombol "paste_gn": Jika Anda sudah memiliki tombol untuk paste_gn, pastikan fungsi yang dipanggil oleh tombol tersebut mengambil posisi kursor (tk.INSERT) dan memasukkan teks nada di posisi itu.


2. Menggunakan insert(tk.INSERT): Pada saat menambahkan teks nada, selalu gunakan posisi kursor tk.INSERT agar teks disisipkan di mana pun kursor berada.



Berikut adalah pembaruan pada kode Anda untuk bagian yang terkait dengan penyisipan nada menggunakan tombol "paste_gn":

# Fungsi untuk memasukkan nada ke partitur di posisi kursor
def insert_gn():
    # Nada yang dihasilkan dari tombol paste_gn
    nada_paste = "paste_gn_nada"  # Gantilah sesuai dengan nada yang dihasilkan
    
    # Dapatkan posisi kursor saat ini
    current_index = output_text.index(tk.INSERT)
    
    # Sisipkan nada pada posisi kursor
    output_text.insert(current_index, nada_paste)

# Tombol untuk paste_gn (contoh)
paste_gn_button = tk.Button(root, text="Paste GN", command=insert_gn)
paste_gn_button.pack()

# Misalkan tombol paste_gn ditempatkan di bagian yang relevan
paste_gn_button.grid(row=2, column=2, padx=5, pady=5)

Penjelasan:

insert_gn(): Fungsi ini akan menyisipkan teks nada "paste_gn_nada" di posisi kursor saat ini pada widget Text (output_text).

output_text.index(tk.INSERT): Mendapatkan posisi kursor saat ini.

output_text.insert(current_index, nada_paste): Menyisipkan teks nada di posisi yang diambil dari kursor.

Pastikan Anda mengganti "paste_gn_nada" dengan teks yang sesuai dari nada yang dihasilkan oleh tombol "paste_gn". Dengan ini, teks akan disisipkan tepat di posisi kursor berada saat tombol ditekan.



Tolong perbaiki kode berikut agar supaya teks nada yang dihadilkan dari tombol paste_gn dapat tampil pada outout_text di posisi di mana kursor berada. Berikut kode:


import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import ttk

# Setup UI
root = tk.Tk()
root.geometry("690x1390")
root.title("Partitur Notasi Angka dengan Font Khusus")

# Skala Mayor dan Minor
skala_mayor = [2, 2, 1, 2, 2, 2, 1]
skala_minor = [2, 1, 2, 2, 1, 2, 2]

akord_tampil = False  # Flag untuk mengecek apakah tombol "Tampilkan Akord" sudah ditekan

# Fungsi untuk mengubah nada berdasarkan interval
def generate_scale(nada_dasar_value, intervals):
    all_notes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
    scale = []

    start_index = all_notes.index(nada_dasar_value)
    scale.append(all_notes[start_index])

    current_index = start_index
    for interval in intervals:
        current_index = (current_index + interval) % len(all_notes)
        scale.append(all_notes[current_index])

    return scale
    
# Fungsi untuk mengisi dropdown akord dan menghasilkan skala berdasarkan nada dasar dan pilihan Mayor/Minor
def tampilkan_akord():
    global akord_tampil
    nada_dasar_value = nada_dasar_dropdown.get()
    Mayor_minor_value = Mayor_minor_dropdown.get()

    # Tentukan interval berdasarkan pilihan Mayor atau Minor
    if Mayor_minor_value == "Mayor":
        intervals = skala_mayor
        progresi = ["", "m", "m", "", "", "m", "dim"]
    else:
        intervals = skala_minor
        progresi = ["m", "dim", "", "m", "m", "", ""]

    # Dapatkan skala berdasarkan nada dasar dan interval
    generated_scale = generate_scale(nada_dasar_value, intervals)

    # Buat daftar akord
    akord_list = []
    for i, nada in enumerate(generated_scale[:-1]):  # Exclude the octave note
        akord = nada + progresi[i]
        akord_list.append(akord)

    # Set the values of combobox_akord
    combobox_akord['values'] = akord_list
    combobox_akord.set('')  # Reset selection
    akord_tampil = True  # Set flag menjadi True ketika tombol ditekan
    messagebox.showinfo("Info", "Lanjutkan ke combobox Pilih Akord \nuntuk memilih akord")  # Menampilkan pesan

# Fungsi untuk memasukkan akord yang dipilih ke dalam output_text
def insert_selected_akord(event):
    if not akord_tampil:  # Jika belum menekan tombol Tampilkan Akord
        messagebox.showwarning("Peringatan", "Sebelumnya tekan tombol Tampilkan Akord")
        return

    selected_akord = combobox_akord.get()
    # Menyisipkan akord di posisi kursor saat ini
    current_index = output_text.index(tk.INSERT)  # Dapatkan posisi kursor
    output_text.insert(current_index, f"{selected_akord} ")

# Fungsi untuk memasukkan simbol notasi yang dipilih ke partitur
def insert_symbol(symbol):
    output_text.insert(tk.INSERT, symbol)

# Fungsi untuk memasukkan akord ke partitur, di atas angka nada
def insert_chord(chord):
    output_text.insert(tk.INSERT, chord, ("superscript", "chord_color"))
    output_text.insert(tk.INSERT, "")

# Simbol notasi yang akan digunakan (tambahkan nada panjang satu, dua, dan tiga ketuk)
symbol_options = [
    "•", "••", "•••", "\u007C", "||", ":||", "/", "\\", "'",
    "0", "♯", "♭", "\u2323", "\u0305", "\u0818", "\u07EB", "\u135E", "\u135F", "\u135D", "\u1A18", "\u0324", "\u1CDF",  "" # Nada panjang satu, dua, dan tiga ketuk
]

# Entry Nada Dasar
mayor_minor = ["Mayor", "minor"]

# Entry Nilai Nada Dasar
nada_dasar = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B", "Db", "Eb", "Gb", "Ab", "Bb"]

# Akord Mayor dan Minor
akord_mayor = ["C", "C#", "D", "D#", "E", "F", "F#",  "G", "G#", "A", "A#", "B"]
akord_minor = ["Am", "A#m", "Bm", "Cm", "C#m", "Dm", "D#m", "Em", "Fm", "F#m","Gm", "G#m"]

# Fungsi untuk memasukkan nada ke partitur pada posisi tertentu
def insert_note(note):
    # Menyisipkan nada di posisi kursor saat ini
    current_index = output_text.index(tk.INSERT)
    output_text.insert(current_index, note)
    
# Fungsi untuk membuat template birama
def create_birama_template():
    template = "|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |"  # Garis birama 4/4
    return template

# Fungsi untuk menambahkan birama ke output_text dengan pembatas di akhir
def add_birama():
    birama = create_birama_template()
    output_text.insert(tk.END, f"{birama}|\n")  # Baris pertama: birama untuk nada (dengan pembatas di akhir)
    output_text.insert(tk.END, "Lirik: " + " " * (len(birama) - 7) + "|\n")  # Baris kedua: tempat lirik (dengan pembatas di akhir)
    output_text.insert(tk.END, "\n")  # Baris ketiga: separator kosong untuk jarak antar birama

# Membuat canvas untuk konten partitur
output_text_canvas = tk.Canvas(root)
output_text_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

# Scrollbars untuk canvas
scrollbar_y = tk.Scrollbar(root, orient=tk.VERTICAL, command=output_text_canvas.yview)
scrollbar_y.pack(side=tk.RIGHT, fill=tk.Y)

scrollbar_x = tk.Scrollbar(root, orient=tk.HORIZONTAL, command=output_text_canvas.xview)
scrollbar_x.pack(side=tk.BOTTOM, fill=tk.X)

output_text_canvas.configure(yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set)
output_text_canvas.bind('<Configure>', lambda e: output_text_canvas.configure(scrollregion=output_text_canvas.bbox('all')))

# Membuat frame untuk konten di dalam canvas
output_frame = tk.Frame(output_text_canvas)
output_text_canvas.create_window((0, 0), window=output_frame, anchor="nw")

# Membuat kotak untuk tombol simbol notasi
symbol_frame = tk.Frame(output_frame)
symbol_frame.grid(row=0, column=0, pady=5)

# Label instruksi simbol
symbol_label = tk.Label(symbol_frame, text="Simbol Notasi Angka:")
symbol_label.grid(row=0, column=0, columnspan=6, pady=(0, 5))

# Loop untuk membuat tombol untuk setiap simbol
for i, symbol in enumerate(symbol_options):
    button = tk.Button(symbol_frame, text=symbol, width=2, command=lambda s=symbol: insert_symbol(s))
    button.grid(row=1 + i // 8, column=i % 8, padx=5, pady=5)

# Frame untuk dropdown akord
chord_frame = tk.Frame(output_frame)
chord_frame.grid(row=1, column=0, pady=5)

# Entry Nada Dasar (Dropdown)
nada_dasar_label = tk.Label(chord_frame, text="Nada Dasar Lagu:")
nada_dasar_label.grid(row=0, column=1, padx=1, pady=5)

# Dropdown untuk Mayor/Minor
Mayor_minor_dropdown = ttk.Combobox(chord_frame, values=["Mayor", "minor"], state="readonly")
Mayor_minor_dropdown.grid(row=0, column=2, padx=(1, 2), pady=5)
Mayor_minor_dropdown.set("Mayor")  # Default ke "Mayor"

do_label = tk.Label(chord_frame, text="1 = ",  width=4, anchor="e", font=("Helvetica", 12, "bold"))
do_label.grid(row=0, column=3, padx=(0, 1), pady=5)  # Kurangi padding kiri ke 0

# Dropdown untuk Nilai Nada Dasar
nada_dasar_dropdown = ttk.Combobox(chord_frame,  values=nada_dasar, state="readonly")
nada_dasar_dropdown.grid(row=0, column=4, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1
nada_dasar_dropdown.set("C")  # Default Nada Dasar diatur ke "C"

# Tombol untuk menampilkan akord
button_tampilkan_akord = tk.Button(chord_frame, text="Tampilkan Akord", command=tampilkan_akord)
button_tampilkan_akord.grid(row=1, column=1, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1

# Combobox untuk pilihan akord
akord_label = tk.Label(chord_frame, text="Pilih Akord:")
akord_label.grid(row=1, column=2, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1
combobox_akord = ttk.Combobox(chord_frame, state="readonly")
combobox_akord.grid(row=1, column=3, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1
combobox_akord.bind("<<ComboboxSelected>>", insert_selected_akord)

# Fungsi untuk menampilkan partitur dengan indentasi
def show_partitur():
    output_text.delete(1.0, tk.END)
    output_text.insert(tk.END, "\nPartitur Notasi Angka :\n", "indent")
    output_text.insert(tk.END, f"Judul Lagu   : \n", "indent")
    output_text.insert(tk.END, f"Nada Dasar   : \n", "indent")
    output_text.insert(tk.END, f"Tanda Birama : \n", "indent")
    output_text.insert(tk.END, f"Pencipta     : \n", "indent")
    output_text.insert(tk.END, f"Arranger     : \n", "indent")
    output_text.insert(tk.END, "\nArah/Arus Musik :\n", "indent")
    output_text.insert(tk.END, "Tempo (BPM)     :\n", "indent")
    output_text.insert(tk.END, " \n \n", "indent")    
    output_text.insert(tk.END, create_birama_template() + "\n")

    output_text.insert(tk.END, "Lirik: " +  "\n")  # Baris kedua: tempat lirik (dengan pembatas di akhir)
    output_text.insert(tk.END, "\n")  # Baris ketiga: separator kosong untuk jarak antar birama

    # Menonaktifkan tombol setelah ditekan
    show_button.config(state=tk.DISABLED, bg="lightgrey", text="Tombol Tidak Aktif")

# Fungsi untuk mengaktifkan kembali tombol Tampil Partitur
def reset_button():
    show_button.config(state=tk.NORMAL, bg="grey", text="Tampil Partitur")

# Fungsi untuk menyimpan perubahan
def save_partitur():
    edited_text = output_text.get(1.0, tk.END).strip()
    file_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text Files", "*.txt")])
    if file_path:
        try:
            with open(file_path, 'w') as file:
                file.write(edited_text)
            messagebox.showinfo("Sukses", "Partitur berhasil disimpan.")
        except Exception as e:
            messagebox.showerror("Error", f"Gagal menyimpan partitur: {e}")
            
# Fungsi untuk membuka file partitur
def open_partitur():
    file_path = filedialog.askopenfilename(filetypes=[("Text files", "*.txt"), ("All files", "*.*")])
    if file_path:
        with open(file_path, "r") as file:
            content = file.read()
        output_text.delete(1.0, tk.END)
        output_text.insert(tk.END, content)
            
# Tombol untuk menampilkan partitur
show_button = tk.Button(output_frame, text="Tampil Partitur", bg="grey", fg="white", command=show_partitur)
show_button.grid(row=7, column=0, padx=5, pady=5)

# Tombol untuk mengaktifkan kembali tombol Tampil Partitur
reset_button = tk.Button(output_frame, text="Reset", bg="blue", fg="white", command=reset_button)
reset_button.grid(row=7, column=1, padx=5, pady=5)

# Fungsi untuk memasukkan nada ke partitur di posisi kursor
def paste_gn():
    # Nada yang dihasilkan dari tombol paste_gn
    nada_paste = "paste_gn_nada"  # Gantilah sesuai dengan nada yang dihasilkan
    
    # Dapatkan posisi kursor saat ini
    current_index = output_text.index(tk.INSERT)
    
    # Sisipkan nada pada posisi kursor
    output_text.insert(current_index, nada_paste)

# Tombol untuk mem-paste gugus nada ke output_text
paste_gn_button = tk.Button(output_frame, text="Paste Gn", bg="grey", fg="white", command=paste_gn)
paste_gn_button.grid(row=8, column=0, padx=5, pady=5)

# Tombol untuk menyimpan partitur
save_button = tk.Button(output_frame, text="Simpan Partitur", bg="grey", fg="white", command=save_partitur)
save_button.grid(row=7, column=2, padx=5, pady=5)

# Tombol untuk membuka partitur
open_button = tk.Button(output_frame, text="Buka Partitur", bg="grey", fg="white",command=open_partitur)
open_button.grid(row=7, column=3, padx=5, pady=5)

# Tombol untuk menambahkan birama
add_birama_button = tk.Button(output_frame, text="Tambah Birama", bg="grey", fg="white", command=add_birama)
add_birama_button.grid(row=8, column=1, padx=5, pady=5)

# Label instruksi di atas output_text
instruksi_label = tk.Label(output_frame, text="Partitur Notasi Angka (Edit di bawah sini):")
instruksi_label.grid(row=9, column=0, padx=5, pady=5)

# Membuat Text Widget untuk output
output_text = tk.Text(output_frame, wrap=tk.WORD, undo=True, width=80, height=50)
output_text.grid(row=10, column=0, columnspan=3, padx=10, pady=10)

# Menambahkan Scrollbars ke Text Widget
output_text_scroll_y = tk.Scrollbar(output_frame, orient=tk.VERTICAL, command=output_text.yview)
output_text_scroll_y.grid(row=9, column=3, sticky="ns")
output_text['yscrollcommand'] = output_text_scroll_y.set

output_text_scroll_x = tk.Scrollbar(output_frame, orient=tk.HORIZONTAL, command=output_text.xview)
output_text_scroll_x.grid(row=10, column=0, columnspan=3, sticky="we")
output_text['xscrollcommand'] = output_text_scroll_x.set

# Menambah gaya (style) pada text untuk superscript
output_text.tag_configure("superscript", offset=5)
output_text.tag_configure("chord_color", foreground="blue")
output_text.tag_configure("indent", lmargin1=10, lmargin2=10)

# Fungsi untuk menyimpan sementara gugus nada ke dalam file sementara
def copy_gn():
    try:
        selected_text = output_text.get(tk.SEL_FIRST, tk.SEL_LAST)
        with open("temp_gn_value.txt", "w") as temp_file:
            temp_file.write(selected_text)
        messagebox.showinfo("Sukses", "Gugus Nada berhasil disalin.")
    except tk.TclError:
        messagebox.showwarning("Peringatan", "Tidak ada teks yang disalin.")

# Tombol untuk menyalin gugus nada ke file sementara
copy_gn_button = tk.Button(output_frame, text="Salin Gn", bg="grey", fg="white", command=copy_gn)
copy_gn_button.grid(row=8, column=2, padx=5, pady=5)

# Fungsi untuk keluar dari aplikasi
def exit_app():
    result = messagebox.askquestion("Keluar", "Apakah Anda yakin ingin keluar?", icon="warning")
    if result == 'yes':
        root.quit()

# Tombol untuk keluar dari aplikasi
exit_button = tk.Button(output_frame, text="Keluar", bg="red", fg="white", command=exit_app)
exit_button.grid(row=11, column=2, padx=10, pady=10)

# Fungsi utama untuk menjalankan aplikasi
def main():
    root.mainloop()

# Memanggil fungsi utama
if __name__ == "__main__":
    main()

    
Berikan saya kode selengkapnya yang benar dan tanpa error.



Berikut adalah kode lengkap yang telah diperbaiki sehingga teks nada yang dihasilkan dari tombol Paste Gn akan tampil pada output_text di posisi di mana kursor berada:


import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import ttk

# Setup UI
root = tk.Tk()
root.geometry("690x1390")
root.title("Partitur Notasi Angka dengan Font Khusus")

# Skala Mayor dan Minor
skala_mayor = [2, 2, 1, 2, 2, 2, 1]
skala_minor = [2, 1, 2, 2, 1, 2, 2]

akord_tampil = False  # Flag untuk mengecek apakah tombol "Tampilkan Akord" sudah ditekan

# Fungsi untuk mengubah nada berdasarkan interval
def generate_scale(nada_dasar_value, intervals):
    all_notes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
    scale = []

    start_index = all_notes.index(nada_dasar_value)
    scale.append(all_notes[start_index])

    current_index = start_index
    for interval in intervals:
        current_index = (current_index + interval) % len(all_notes)
        scale.append(all_notes[current_index])

    return scale

# Fungsi untuk mengisi dropdown akord dan menghasilkan skala berdasarkan nada dasar dan pilihan Mayor/Minor
def tampilkan_akord():
    global akord_tampil
    nada_dasar_value = nada_dasar_dropdown.get()
    Mayor_minor_value = Mayor_minor_dropdown.get()

    # Tentukan interval berdasarkan pilihan Mayor atau Minor
    if Mayor_minor_value == "Mayor":
        intervals = skala_mayor
        progresi = ["", "m", "m", "", "", "m", "dim"]
    else:
        intervals = skala_minor
        progresi = ["m", "dim", "", "m", "m", "", ""]

    # Dapatkan skala berdasarkan nada dasar dan interval
    generated_scale = generate_scale(nada_dasar_value, intervals)

    # Buat daftar akord
    akord_list = []
    for i, nada in enumerate(generated_scale[:-1]):  # Exclude the octave note
        akord = nada + progresi[i]
        akord_list.append(akord)

    # Set the values of combobox_akord
    combobox_akord['values'] = akord_list
    combobox_akord.set('')  # Reset selection
    akord_tampil = True  # Set flag menjadi True ketika tombol ditekan
    messagebox.showinfo("Info", "Lanjutkan ke combobox Pilih Akord \nuntuk memilih akord")  # Menampilkan pesan

# Fungsi untuk memasukkan akord yang dipilih ke dalam output_text
def insert_selected_akord(event):
    if not akord_tampil:  # Jika belum menekan tombol Tampilkan Akord
        messagebox.showwarning("Peringatan", "Sebelumnya tekan tombol Tampilkan Akord")
        return

    selected_akord = combobox_akord.get()
    # Menyisipkan akord di posisi kursor saat ini
    current_index = output_text.index(tk.INSERT)  # Dapatkan posisi kursor
    output_text.insert(current_index, f"{selected_akord} ")

# Fungsi untuk memasukkan simbol notasi yang dipilih ke partitur
def insert_symbol(symbol):
    output_text.insert(tk.INSERT, symbol)

# Simbol notasi yang akan digunakan
symbol_options = [
    "•", "••", "•••", "|", "||", ":||", "/", "\\", "'",
    "0", "♯", "♭", "𝄞", "𝄢", "𝄡", "𝄞", "𝄟", "𝄠", "𝄢", "𝄞", "𝄟", ""
]

# Entry Nada Dasar
mayor_minor = ["Mayor", "minor"]

# Entry Nilai Nada Dasar
nada_dasar = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]

# Fungsi untuk membuat template birama
def create_birama_template():
    template = "|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |"  # Garis birama 4/4
    return template

# Fungsi untuk menambahkan birama ke output_text
def add_birama():
    birama = create_birama_template()
    output_text.insert(tk.END, f"{birama}|\n")
    output_text.insert(tk.END, "Lirik: " + " " * (len(birama) - 7) + "|\n")
    output_text.insert(tk.END, "\n")

# Fungsi untuk menampilkan partitur dengan indentasi
def show_partitur():
    output_text.delete(1.0, tk.END)
    output_text.insert(tk.END, "\nPartitur Notasi Angka :\n", "indent")
    output_text.insert(tk.END, f"Judul Lagu   : \n", "indent")
    output_text.insert(tk.END, f"Nada Dasar   : \n", "indent")
    output_text.insert(tk.END, f"Tanda Birama : \n", "indent")
    output_text.insert(tk.END, f"Pencipta     : \n", "indent")
    output_text.insert(tk.END, f"Arranger     : \n", "indent")
    output_text.insert(tk.END, "\nArah/Arus Musik :\n", "indent")
    output_text.insert(tk.END, "Tempo (BPM)     :\n", "indent")
    output_text.insert(tk.END, " \n \n", "indent")    
    output_text.insert(tk.END, create_birama_template() + "\n")
    output_text.insert(tk.END, "Lirik: " +  "\n")
    output_text.insert(tk.END, "\n")
    show_button.config(state=tk.DISABLED, bg="lightgrey", text="Tombol Tidak Aktif")

# Fungsi untuk mengaktifkan kembali tombol Tampil Partitur
def reset_button():
    show_button.config(state=tk.NORMAL, bg="grey", text="Tampil Partitur")

# Fungsi untuk menyimpan perubahan
def save_partitur():
    edited_text = output_text.get(1.0, tk.END).strip()
    file_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text Files", "*.txt")])
    if file_path:
        try:
            with open(file_path, 'w') as file:
                file.write(edited_text)
            messagebox.showinfo("Sukses", "Partitur berhasil disimpan.")
        except Exception as e:
            messagebox.showerror("Error", f"Gagal menyimpan partitur: {e}")

# Fungsi untuk membuka file partitur
def open_partitur():
    file_path = filedialog.askopenfilename(filetypes=[("Text files", "*.txt"), ("All files", "*.*")])
    if file_path:
        with open(file_path, "r") as file:
            content = file.read()
        output_text.delete(1.0, tk.END)
        output_text.insert(tk.END, content)

# Fungsi untuk memasukkan nada ke partitur di posisi kursor
def paste_gn():
    try:
        with open("temp_gn_value.txt", "r") as temp_file:
            gn_value = temp_file.read()
        current_index = output_text.index(tk.INSERT)
        output_text.insert(current_index, gn_value)
    except FileNotFoundError:
        output_text.insert(tk.INSERT, "Tidak ada data yang dicopy.")

# Fungsi untuk menyimpan sementara gugus nada ke dalam file sementara
def copy_gn():
    try:
        selected_text = output_text.get(tk.SEL_FIRST, tk.SEL_LAST)
        with open("temp_gn_value.txt", "w") as temp_file:
            temp_file.write(selected_text)
        messagebox.showinfo("Sukses", "Gugus Nada berhasil disalin.")
    except tk.TclError:
        messagebox.showwarning("Peringatan", "Tidak ada teks yang disalin.")

# Fungsi untuk keluar dari aplikasi
def exit_app():
    result = messagebox.askquestion("Keluar", "Apakah Anda yakin ingin keluar?", icon="warning")
    if result == 'yes':
        root.quit()

# Membuat canvas untuk konten partitur
output_text_canvas = tk.Canvas(root)
output_text_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

# Scrollbars untuk canvas
scrollbar_y = tk.Scrollbar(root, orient=tk.VERTICAL, command=output_text_canvas.yview)
scrollbar_y.pack(side=tk.RIGHT, fill=tk.Y)

scrollbar_x = tk.Scrollbar(root, orient=tk.HORIZONTAL, command=output_text_canvas.xview)
scrollbar_x.pack(side=tk.BOTTOM, fill=tk.X)

output_text_canvas.configure(yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set)
output_text_canvas.bind('<Configure>', lambda e: output_text_canvas.configure(scrollregion=output_text_canvas.bbox('all')))

# Membuat frame untuk konten di dalam canvas
output_frame = tk.Frame(output_text_canvas)
output_text_canvas.create_window((0, 0), window=output_frame, anchor="nw")

# Membuat kotak untuk tombol simbol notasi
symbol_frame = tk.Frame(output_frame)
symbol_frame.grid(row=0, column=0, pady=5)

# Label instruksi simbol
symbol_label = tk.Label(symbol_frame, text="Simbol Notasi Angka:")
symbol_label.grid(row=0, column=0, columnspan=6, pady=(0, 5))

# Loop untuk membuat tombol untuk setiap simbol
for i, symbol in enumerate(symbol_options):
    button = tk.Button(symbol_frame, text=symbol, width=2, command=lambda s=symbol: insert_symbol(s))
    button.grid(row=1 + i // 8, column=i % 8, padx=5, pady=5)

# Frame untuk dropdown akord
chord_frame = tk.Frame(output_frame)
chord_frame.grid(row=1, column=0, pady=5)

# Entry Nada Dasar (Dropdown)
nada_dasar_label = tk.Label(chord_frame, text="Nada Dasar Lagu:")
nada_dasar_label.grid(row=0, column=1, padx=1, pady=5)

# Dropdown untuk Mayor/Minor
Mayor_minor_dropdown = ttk.Combobox(chord_frame, values=["Mayor", "minor"], state="readonly")
Mayor_minor_dropdown.grid(row=0, column=2, padx=(1, 2), pady=5)
Mayor_minor_dropdown.set("Mayor")  # Default ke "Mayor"

do_label = tk.Label(chord_frame, text="1 = ",  width=4, anchor="e", font=("Helvetica", 12, "bold"))
do_label.grid(row=0, column=3, padx=(0, 1), pady=5)

# Dropdown untuk Nilai Nada Dasar
nada_dasar_dropdown = ttk.Combobox(chord_frame,  values=nada_dasar, state="readonly")
nada_dasar_dropdown.grid(row=0, column=4, padx=(1, 2), pady=5)
nada_dasar_dropdown.set("C")  # Default Nada Dasar diatur ke "C"

# Tombol untuk menampilkan akord
button_tampilkan_akord = tk.Button(chord_frame, text="Tampilkan Akord", command=tampilkan_akord)
button_tampilkan_akord.grid(row=1, column=1, padx=(1, 2), pady=5)

# Combobox untuk pilihan akord
akord_label = tk.Label(chord_frame, text="Pilih Akord:")
akord_label.grid(row=1, column=2, padx=(1, 2), pady=5)
combobox_akord = ttk.Combobox(chord_frame, state="readonly")
combobox_akord.grid(row=1, column=3, padx=(1, 2), pady=5)
combobox_akord.bind("<<ComboboxSelected>>", insert_selected_akord)

# Tombol untuk menampilkan partitur
show_button = tk.Button(output_frame, text="Tampil Partitur", bg="grey", fg="white", command=show_partitur)
show_button.grid(row=7, column=0, padx=5, pady=5)

# Tombol untuk mengaktifkan kembali tombol Tampil Partitur
reset_button = tk.Button(output_frame, text="Reset", bg="blue", fg="white", command=reset_button)
reset_button.grid(row=7, column=1, padx=5, pady=5)

# Tombol untuk mem-paste gugus nada ke output_text
paste_gn_button = tk.Button(output_frame, text="Paste Gn", bg="grey", fg="white", command=paste_gn)
paste_gn_button.grid(row=8, column=0, padx=5, pady=5)

# Tombol untuk menyimpan partitur
save_button = tk.Button(output_frame, text="Simpan Partitur", bg="grey", fg="white", command=save_partitur)
save_button.grid(row=7, column=2, padx=5, pady=5)

# Tombol untuk membuka partitur
open_button = tk.Button(output_frame, text="Buka Partitur", bg="grey", fg="white", command=open_partitur)
open_button.grid(row=7, column=3, padx=5, pady=5)

# Tombol untuk menambahkan birama
add_birama_button = tk.Button(output_frame, text="Tambah Birama", bg="grey", fg="white", command=add_birama)
add_birama_button.grid(row=8, column=1, padx=5, pady=5)

# Label instruksi di atas output_text
instruksi_label = tk.Label(output_frame, text="Partitur Notasi Angka (Edit di bawah sini):")
instruksi_label.grid(row=9, column=0, padx=5, pady=5)

# Membuat Text Widget untuk output
output_text = tk.Text(output_frame, wrap=tk.WORD, undo=True, width=80, height=50)
output_text.grid(row=10, column=0, columnspan=3, padx=10, pady=10)

# Menambahkan Scrollbars ke Text Widget
output_text_scroll_y = tk.Scrollbar(output_frame, orient=tk.VERTICAL, command=output_text.yview)
output_text_scroll_y.grid(row=9, column=3, sticky="ns")
output_text['yscrollcommand'] = output_text_scroll_y.set

output_text_scroll_x = tk.Scrollbar(output_frame, orient=tk.HORIZONTAL, command=output_text.xview)
output_text_scroll_x.grid(row=10, column=0, columnspan=3, sticky="we")
output_text['xscrollcommand'] = output_text_scroll_x.set

# Menambah gaya (style) pada text untuk superscript
output_text.tag_configure("superscript", offset=5)
output_text.tag_configure("chord_color", foreground="blue")
output_text.tag_configure("indent", lmargin1=10, lmargin2=10)

# Tombol untuk menyalin gugus nada ke file sementara
copy_gn_button = tk.Button(output_frame, text="Salin Gn", bg="grey", fg="white", command=copy_gn)
copy_gn_button.grid(row=8, column=2, padx=5, pady=5)

# Tombol untuk keluar dari aplikasi
exit_button = tk.Button(output_frame, text="Keluar", bg="red", fg="white", command=exit_app)
exit_button.grid(row=11, column=2, padx=10, pady=10)

# Menjalankan aplikasi
def main():
    root.mainloop()

if __name__ == "__main__":
    main()


Pada kode di atas, fungsi paste_gn telah diperbaiki dengan mengubah posisi penyisipan teks dari tk.END menjadi tk.INSERT sehingga teks akan muncul di posisi kursor berada:

def paste_gn():
    try:
        with open("temp_gn_value.txt", "r") as temp_file:
            gn_value = temp_file.read()
        current_index = output_text.index(tk.INSERT)
        output_text.insert(current_index, gn_value)
    except FileNotFoundError:
        output_text.insert(tk.INSERT, "Tidak ada data yang dicopy.")

Dengan demikian, saat tombol Paste Gn ditekan, teks akan disisipkan tepat di posisi kursor pada widget output_text.



Teks nada yang dihasilkan dari paste_gn belum mau berada di posisi dimana kursor berada (teks nada selalu berada di posisi akhir)


Untuk membuat teks nada yang dihasilkan dari fungsi paste_gn muncul di tempat di mana kursor berada (bukan di akhir), kamu perlu memodifikasi logika penempatan teks di dalam widget teks (misalnya Text atau Entry di tkinter). Berikut langkah-langkah umumnya:

Jika kamu menggunakan Text widget:

1. Dapatkan posisi kursor: Kamu perlu mendapatkan posisi kursor saat ini dalam widget Text. Gunakan metode index("insert") untuk mengetahui posisi kursor.

2. Sisipkan teks pada posisi kursor: Gunakan metode insert() untuk menyisipkan teks pada posisi kursor yang telah didapatkan.

Contoh modifikasi kode untuk Text widget:

def paste_gn():
    # Teks nada yang akan dimasukkan
    teks_nada = "C D E F G A B"
    
    # Dapatkan posisi kursor saat ini
    posisi_kursor = text_widget.index("insert")
    
    # Sisipkan teks pada posisi kursor
    text_widget.insert(posisi_kursor, teks_nada)

Jika kamu menggunakan Entry widget:

1. Dapatkan posisi kursor: Gunakan metode index() pada widget Entry untuk mengetahui posisi kursor saat ini.

2. Dapatkan teks yang ada: Gunakan metode get() untuk mengambil teks yang ada di Entry.

3. Sisipkan teks: Setelah itu, lakukan modifikasi pada teks dengan menyisipkan teks baru di posisi kursor.


Contoh modifikasi kode untuk Entry widget:

def paste_gn():
    # Teks nada yang akan dimasukkan
    teks_nada = "C D E F G A B"
    
    # Dapatkan posisi kursor saat ini
    posisi_kursor = entry_widget.index(INSERT)
    
    # Dapatkan teks saat ini dari Entry
    teks_saat_ini = entry_widget.get()
    
    # Sisipkan teks pada posisi kursor
    teks_baru = teks_saat_ini[:posisi_kursor] + teks_nada + teks_saat_ini[posisi_kursor:]
    
    # Ganti teks di Entry dengan teks baru
    entry_widget.delete(0, END)
    entry_widget.insert(0, teks_baru)
    
    # Tempatkan kursor di posisi setelah teks yang disisipkan
    entry_widget.icursor(posisi_kursor + len(teks_nada))

Dengan perubahan ini, teks nada akan disisipkan pada posisi kursor saat ini, bukan di akhir teks.



Untuk membuat teks nada yang dihasilkan dari fungsi paste_gn muncul di tempat di mana kursor berada (bukan di akhir), kamu perlu memodifikasi logika penempatan teks di dalam widget teks (misalnya Text atau Entry di tkinter). Berikut langkah-langkah umumnya:

Jika kamu menggunakan Text widget:

1. Dapatkan posisi kursor: Kamu perlu mendapatkan posisi kursor saat ini dalam widget Text. Gunakan metode index("insert") untuk mengetahui posisi kursor.

2. Sisipkan teks pada posisi kursor: Gunakan metode insert() untuk menyisipkan teks pada posisi kursor yang telah didapatkan.



Contoh modifikasi kode untuk Text widget:

def paste_gn():
    # Teks nada yang akan dimasukkan
    teks_nada = "C D E F G A B"
    
    # Dapatkan posisi kursor saat ini
    posisi_kursor = text_widget.index("insert")
    
    # Sisipkan teks pada posisi kursor
    text_widget.insert(posisi_kursor, teks_nada)

Jika kamu menggunakan Entry widget:

1. Dapatkan posisi kursor: Gunakan metode index() pada widget Entry untuk mengetahui posisi kursor saat ini.

2. Dapatkan teks yang ada: Gunakan metode get() untuk mengambil teks yang ada di Entry.

3. Sisipkan teks: Setelah itu, lakukan modifikasi pada teks dengan menyisipkan teks baru di posisi kursor.



Contoh modifikasi kode untuk Entry widget:

def paste_gn():
    # Teks nada yang akan dimasukkan
    teks_nada = "C D E F G A B"
    
    # Dapatkan posisi kursor saat ini
    posisi_kursor = entry_widget.index(INSERT)
    
    # Dapatkan teks saat ini dari Entry
    teks_saat_ini = entry_widget.get()
    
    # Sisipkan teks pada posisi kursor
    teks_baru = teks_saat_ini[:posisi_kursor] + teks_nada + teks_saat_ini[posisi_kursor:]
    
    # Ganti teks di Entry dengan teks baru
    entry_widget.delete(0, END)
    entry_widget.insert(0, teks_baru)
    
    # Tempatkan kursor di posisi setelah teks yang disisipkan
    entry_widget.icursor(posisi_kursor + len(teks_nada))

Dengan perubahan ini, teks nada akan disisipkan pada posisi kursor saat ini, bukan di akhir teks.



Teks nada yang dihasilkan dari paste_gn sudah bisa dan berhasil ditempatkan di posisi di mana kursor berada. Kode selengkapnya untuk file partitur_notasi_angka.py adalah berikut ini:


import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import ttk

# Setup UI
root = tk.Tk()
root.geometry("690x1390")
root.title("Partitur Notasi Angka dengan Font Khusus")

# Skala Mayor dan Minor
skala_mayor = [2, 2, 1, 2, 2, 2, 1]
skala_minor = [2, 1, 2, 2, 1, 2, 2]

akord_tampil = False  # Flag untuk mengecek apakah tombol "Tampilkan Akord" sudah ditekan

# Fungsi untuk mengubah nada berdasarkan interval
def generate_scale(nada_dasar_value, intervals):
    all_notes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
    scale = []

    start_index = all_notes.index(nada_dasar_value)
    scale.append(all_notes[start_index])

    current_index = start_index
    for interval in intervals:
        current_index = (current_index + interval) % len(all_notes)
        scale.append(all_notes[current_index])

    return scale
    
# Fungsi untuk mengisi dropdown akord dan menghasilkan skala berdasarkan nada dasar dan pilihan Mayor/Minor
def tampilkan_akord():
    global akord_tampil
    nada_dasar_value = nada_dasar_dropdown.get()
    Mayor_minor_value = Mayor_minor_dropdown.get()

    # Tentukan interval berdasarkan pilihan Mayor atau Minor
    if Mayor_minor_value == "Mayor":
        intervals = skala_mayor
        progresi = ["", "m", "m", "", "", "m", "dim"]
    else:
        intervals = skala_minor
        progresi = ["m", "dim", "", "m", "m", "", ""]

    # Dapatkan skala berdasarkan nada dasar dan interval
    generated_scale = generate_scale(nada_dasar_value, intervals)

    # Buat daftar akord
    akord_list = []
    for i, nada in enumerate(generated_scale[:-1]):  # Exclude the octave note
        akord = nada + progresi[i]
        akord_list.append(akord)

    # Set the values of combobox_akord
    combobox_akord['values'] = akord_list
    combobox_akord.set('')  # Reset selection
    akord_tampil = True  # Set flag menjadi True ketika tombol ditekan
    messagebox.showinfo("Info", "Lanjutkan ke combobox Pilih Akord \nuntuk memilih akord")  # Menampilkan pesan

# Fungsi untuk memasukkan akord yang dipilih ke dalam output_text
def insert_selected_akord(event):
    if not akord_tampil:  # Jika belum menekan tombol Tampilkan Akord
        messagebox.showwarning("Peringatan", "Sebelumnya tekan tombol Tampilkan Akord")
        return

    selected_akord = combobox_akord.get()
    # Menyisipkan akord di posisi kursor saat ini
    current_index = output_text.index(tk.INSERT)  # Dapatkan posisi kursor
    output_text.insert(current_index, f"{selected_akord} ")
           
# Fungsi untuk memasukkan simbol notasi yang dipilih ke partitur
def insert_symbol(symbol):
    output_text.insert(tk.INSERT, symbol)

# Fungsi untuk memasukkan akord ke partitur, di atas angka nada
def insert_chord(chord):
    output_text.insert(tk.INSERT, chord, ("superscript", "chord_color"))
    output_text.insert(tk.INSERT, "")

# Simbol notasi yang akan digunakan (tambahkan nada panjang satu, dua, dan tiga ketuk)
symbol_options = [
    "•", "••", "•••", "\u007C", "||", ":||", "/", "\\", "'",
    "0", "♯", "♭", "\u2323", "\u0305", "\u0818", "\u07EB", "\u135E", "\u135F", "\u135D", "\u1A18", "\u0324", "\u1CDF",  "" # Nada panjang satu, dua, dan tiga ketuk
]

# Entry Nada Dasar
mayor_minor = ["Mayor", "minor"]

# Entry Nilai Nada Dasar
nada_dasar = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B", "Db", "Eb", "Gb", "Ab", "Bb"]

# Akord Mayor dan Minor
akord_mayor = ["C", "C#", "D", "D#", "E", "F", "F#",  "G", "G#", "A", "A#", "B"]
akord_minor = ["Am", "A#m", "Bm", "Cm", "C#m", "Dm", "D#m", "Em", "Fm", "F#m","Gm", "G#m"]

# Fungsi untuk memasukkan nada ke partitur pada posisi tertentu
def insert_note(note):
    current_content = output_text.get("1.0", tk.INSERT)
    lines = current_content.split("\n")
    
    # Cari baris terakhir birama
    last_birama_line_index = None
    for i, line in enumerate(reversed(lines)):
        if "|" in line:  # Cek untuk birama
            last_birama_line_index = len(lines) - i - 1
            break
    
    # Pindah ke baris baru jika nada terlalu panjang untuk satu birama
    if last_birama_line_index is not None:
        if len(lines[last_birama_line_index]) + len(note) > 30:  # Contoh batas maksimal birama
            output_text.insert(tk.INSERT, f"\n{create_birama_template()}|\nLirik: \n\n")
    output_text.insert(tk.INSERT, note)
    
# Fungsi untuk membuat template birama
def create_birama_template():
    template = "|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |"  # Garis birama 4/4
    return template

# Fungsi untuk menambahkan birama ke output_text dengan pembatas di akhir
def add_birama():
    birama = create_birama_template()
    output_text.insert(tk.END, f"{birama}|\n")  # Baris pertama: birama untuk nada (dengan pembatas di akhir)
    output_text.insert(tk.END, "Lirik: " + " " * (len(birama) - 7) + "|\n")  # Baris kedua: tempat lirik (dengan pembatas di akhir)
    output_text.insert(tk.END, "\n")  # Baris ketiga: separator kosong untuk jarak antar birama

# Membuat canvas untuk konten partitur
output_text_canvas = tk.Canvas(root)
output_text_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

# Scrollbars untuk canvas
scrollbar_y = tk.Scrollbar(root, orient=tk.VERTICAL, command=output_text_canvas.yview)
scrollbar_y.pack(side=tk.RIGHT, fill=tk.Y)

scrollbar_x = tk.Scrollbar(root, orient=tk.HORIZONTAL, command=output_text_canvas.xview)
scrollbar_x.pack(side=tk.BOTTOM, fill=tk.X)

output_text_canvas.configure(yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set)
output_text_canvas.bind('<Configure>', lambda e: output_text_canvas.configure(scrollregion=output_text_canvas.bbox('all')))

# Membuat frame untuk konten di dalam canvas
output_frame = tk.Frame(output_text_canvas)
output_text_canvas.create_window((0, 0), window=output_frame, anchor="nw")

# Membuat kotak untuk tombol simbol notasi
symbol_frame = tk.Frame(output_frame)
symbol_frame.grid(row=0, column=0, pady=5)

# Label instruksi simbol
symbol_label = tk.Label(symbol_frame, text="Simbol Notasi Angka:")
symbol_label.grid(row=0, column=0, columnspan=6, pady=(0, 5))

# Loop untuk membuat tombol untuk setiap simbol
for i, symbol in enumerate(symbol_options):
    button = tk.Button(symbol_frame, text=symbol, width=2, command=lambda s=symbol: insert_symbol(s))
    button.grid(row=1 + i // 8, column=i % 8, padx=5, pady=5)

# Frame untuk dropdown akord
chord_frame = tk.Frame(output_frame)
chord_frame.grid(row=1, column=0, pady=5)

# Entry Nada Dasar (Dropdown)
nada_dasar_label = tk.Label(chord_frame, text="Nada Dasar Lagu:")
nada_dasar_label.grid(row=0, column=1, padx=1, pady=5)

# Dropdown untuk Mayor/Minor
Mayor_minor_dropdown = ttk.Combobox(chord_frame, values=["Mayor", "minor"], state="readonly")
Mayor_minor_dropdown.grid(row=0, column=2, padx=(1, 2), pady=5)
Mayor_minor_dropdown.set("Mayor")  # Default ke "Mayor"

do_label = tk.Label(chord_frame, text="1 = ",  width=4, anchor="e", font=("Helvetica", 12, "bold"))
do_label.grid(row=0, column=3, padx=(0, 1), pady=5)  # Kurangi padding kiri ke 0

# Dropdown untuk Nilai Nada Dasar
nada_dasar_dropdown = ttk.Combobox(chord_frame,  values=nada_dasar, state="readonly")
nada_dasar_dropdown.grid(row=0, column=4, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1
nada_dasar_dropdown.set("C")  # Default Nada Dasar diatur ke "C"

# Tombol untuk menampilkan akord
button_tampilkan_akord = tk.Button(chord_frame, text="Tampilkan Akord", command=tampilkan_akord)
button_tampilkan_akord.grid(row=1, column=1, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1

# Combobox untuk pilihan akord
akord_label = tk.Label(chord_frame, text="Pilih Akord:")
akord_label.grid(row=1, column=2, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1
combobox_akord = ttk.Combobox(chord_frame, state="readonly")
combobox_akord.grid(row=1, column=3, padx=(1, 2), pady=5)  # Kurangi padding kanan ke 1
combobox_akord.bind("<<ComboboxSelected>>", insert_selected_akord)

# Fungsi untuk menampilkan partitur dengan indentasi
def show_partitur():
    output_text.delete(1.0, tk.END)
    output_text.insert(tk.END, "\nPartitur Notasi Angka :\n", "indent")
    output_text.insert(tk.END, f"Judul Lagu   : \n", "indent")
    output_text.insert(tk.END, f"Nada Dasar   : \n", "indent")
    output_text.insert(tk.END, f"Tanda Birama : \n", "indent")
    output_text.insert(tk.END, f"Pencipta     : \n", "indent")
    output_text.insert(tk.END, f"Arranger     : \n", "indent")
    output_text.insert(tk.END, "\nArah/Arus Musik :\n", "indent")
    output_text.insert(tk.END, "Tempo (BPM)     :\n", "indent")
    output_text.insert(tk.END, " \n \n", "indent")    
    output_text.insert(tk.END, create_birama_template() + "\n")

    output_text.insert(tk.END, "Lirik: " +  "\n")  # Baris kedua: tempat lirik (dengan pembatas di akhir)
    output_text.insert(tk.END, "\n")  # Baris ketiga: separator kosong untuk jarak antar birama

    # Menonaktifkan tombol setelah ditekan
    show_button.config(state=tk.DISABLED, bg="lightgrey", text="Tombol Tidak Aktif")

# Fungsi untuk mengaktifkan kembali tombol Tampil Partitur
def reset_button():
    show_button.config(state=tk.NORMAL, bg="grey", text="Tampil Partitur")

# Fungsi untuk menyimpan perubahan
def save_partitur():
    edited_text = output_text.get(1.0, tk.END).strip()
    file_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text Files", "*.txt")])
    if file_path:
        try:
            with open(file_path, 'w') as file:
                file.write(edited_text)
            messagebox.showinfo("Sukses", "Partitur berhasil disimpan.")
        except Exception as e:
            messagebox.showerror("Error", f"Gagal menyimpan partitur: {e}")
            
# Fungsi untuk membuka file partitur
def open_partitur():
    file_path = filedialog.askopenfilename(filetypes=[("Text files", "*.txt"), ("All files", "*.*")])
    if file_path:
        with open(file_path, "r") as file:
            content = file.read()
        output_text.delete(1.0, tk.END)
        output_text.insert(tk.END, content)
            
# Tombol untuk menampilkan partitur
show_button = tk.Button(output_frame, text="Tampil Partitur", bg="grey", fg="white", command=show_partitur)
show_button.grid(row=7, column=0, padx=5, pady=5)

# Tombol untuk mengaktifkan kembali tombol Tampil Partitur
reset_button = tk.Button(output_frame, text="Reset", bg="blue", fg="white", command=reset_button)
reset_button.grid(row=7, column=1, padx=5, pady=5)

# Fungsi untuk memasukkan nada ke partitur di posisi kursor
def paste_gn():
    try:
        with open("temp_gn_value.txt", "r") as temp_file:
            gn_value = temp_file.read()
        current_index = output_text.index(tk.INSERT)
        output_text.insert(current_index, gn_value)
    except FileNotFoundError:
        output_text.insert(tk.INSERT, "Tidak ada data yang dicopy.")

# Tombol untuk mem-paste gugus nada ke output_text
paste_gn_button = tk.Button(output_frame, text="Paste Gn", bg="grey", fg="white", command=paste_gn)
paste_gn_button.grid(row=8, column=0, padx=5, pady=5)

# Tombol untuk menyimpan partitur
save_button = tk.Button(output_frame, text="Simpan Partitur", bg="grey", fg="white", command=save_partitur)
save_button.grid(row=7, column=2, padx=5, pady=5)

# Tombol untuk membuka partitur
open_button = tk.Button(output_frame, text="Buka Partitur", bg="grey", fg="white",command=open_partitur)
open_button.grid(row=7, column=3, padx=5, pady=5)

# Tombol untuk menambahkan birama
add_birama_button = tk.Button(output_frame, text="Tambah Birama", bg="grey", fg="white", command=add_birama)
add_birama_button.grid(row=8, column=1, padx=5, pady=5)

# Label instruksi di atas output_text
instruksi_label = tk.Label(output_frame, text="Partitur Notasi Angka (Edit di bawah sini):")
instruksi_label.grid(row=9, column=0, padx=5, pady=5)

# Membuat Text Widget untuk output
output_text = tk.Text(output_frame, wrap=tk.WORD, undo=True, width=80, height=50)
output_text.grid(row=10, column=0, columnspan=3, padx=10, pady=10)

# Menambahkan Scrollbars ke Text Widget
output_text_scroll_y = tk.Scrollbar(output_frame, orient=tk.VERTICAL, command=output_text.yview)
output_text_scroll_y.grid(row=9, column=3, sticky="ns")
output_text['yscrollcommand'] = output_text_scroll_y.set

output_text_scroll_x = tk.Scrollbar(output_frame, orient=tk.HORIZONTAL, command=output_text.xview)
output_text_scroll_x.grid(row=10, column=0, columnspan=3, sticky="we")
output_text['xscrollcommand'] = output_text_scroll_x.set

# Menambah gaya (style) pada text untuk superscript
output_text.tag_configure("superscript", offset=5)
output_text.tag_configure("chord_color", foreground="blue")
output_text.tag_configure("indent", lmargin1=10, lmargin2=10)

# Fungsi untuk menyimpan sementara gugus nada ke dalam file sementara
def copy_gn():
    try:
        selected_text = output_text.get(tk.SEL_FIRST, tk.SEL_LAST)
        with open("temp_gn_value.txt", "w") as temp_file:
            temp_file.write(selected_text)
        messagebox.showinfo("Sukses", "Gugus Nada berhasil disalin.")
    except tk.TclError:
        messagebox.showwarning("Peringatan", "Tidak ada teks yang disalin.")

# Tombol untuk menyalin gugus nada ke file sementara
copy_gn_button = tk.Button(output_frame, text="Salin Gn", bg="grey", fg="white", command=copy_gn)
copy_gn_button.grid(row=8, column=2, padx=5, pady=5)

# Fungsi untuk keluar dari aplikasi
def exit_app():
    result = messagebox.askquestion("Keluar", "Apakah Anda yakin ingin keluar?", icon="warning")
    if result == 'yes':
        root.quit()

# Tombol untuk keluar dari aplikasi
exit_button = tk.Button(output_frame, text="Keluar", bg="red", fg="white", command=exit_app)
exit_button.grid(row=11, column=2, padx=10, pady=10)

# Fungsi utama untuk menjalankan aplikasi
def main():
    root.mainloop()

# Memanggil fungsi utama
if __name__ == "__main__":
    main()
    


Kode file partitur_notasi_angka.py terpotong pada bagian akhir. Berikut adalah penjelasan dan bagian yang hilang agar fungsionalitas partitur dapat ditampilkan dengan baik.

Melanjutkan dari bagian sebelumnya:

# Fungsi untuk menampilkan partitur dengan indentasi
def show_partitur():
    output_text.delete(1.0, tk.END)  # Hapus konten sebelumnya
    output_text.insert(tk.END, "Berikut adalah template partitur dengan birama 4/4:\n\n")
    output_text.insert(tk.END, create_birama_template() + "\n")
    output_text.insert(tk.END, "Lirik: " + " " * (len(create_birama_template()) - 7) + "|\n\n")

# Kotak teks untuk output partitur
output_text = tk.Text(output_frame, wrap="none", width=80, height=40, undo=True, font=("Courier", 12))
output_text.grid(row=2, column=0, padx=10, pady=5)

# Tombol untuk menambah birama baru
button_add_birama = tk.Button(chord_frame, text="Tambah Birama", command=add_birama)
button_add_birama.grid(row=1, column=4, padx=(1, 2), pady=5)

# Tombol untuk menampilkan template partitur
button_show_partitur = tk.Button(chord_frame, text="Tampilkan Partitur", command=show_partitur)
button_show_partitur.grid(row=1, column=5, padx=(1, 2), pady=5)

# Configure tags for text styling
output_text.tag_configure("superscript", offset=8)  # Superscript untuk chord
output_text.tag_configure("chord_color", foreground="blue")  # Warna biru untuk chord

# Menambahkan scrollbar ke Text Widget
output_text_scrollbar_y = tk.Scrollbar(output_frame, orient=tk.VERTICAL, command=output_text.yview)
output_text_scrollbar_y.grid(row=2, column=1, sticky='ns')
output_text.configure(yscrollcommand=output_text_scrollbar_y.set)

output_text_scrollbar_x = tk.Scrollbar(output_frame, orient=tk.HORIZONTAL, command=output_text.xview)
output_text_scrollbar_x.grid(row=3, column=0, sticky='ew')
output_text.configure(xscrollcommand=output_text_scrollbar_x.set)

# Run the Tkinter main loop
root.mainloop()


Penjelasan kode:

1. show_partitur(): Fungsi ini digunakan untuk menampilkan template dasar partitur dengan birama 4/4, yang mencakup garis-garis untuk nada dan lirik.

2. output_text: Merupakan Text widget yang digunakan untuk menampilkan dan menyunting partitur. Ukurannya adalah 80x40 dengan font Courier untuk menyerupai gaya penulisan partitur.

3. add_birama(): Tombol ini menambahkan birama baru ke output_text.

4. Tampilan Akord dan Birama: Akord yang dipilih melalui dropdown akan ditampilkan di posisi kursor dengan gaya superskrip dan warna biru. Tombol "Tampilkan Partitur" berfungsi untuk memulai partitur dengan template kosong.

5. Scrollbars: Scrollbars vertikal dan horizontal ditambahkan untuk memungkinkan scrolling jika partitur melebihi ukuran layar.

Dengan struktur ini, aplikasi dapat digunakan untuk membuat partitur sederhana, menambahkan simbol notasi angka, memasukkan akord, dan menyusun birama dengan lirik.



Komentar

Postingan populer dari blog ini

Cara Download Aplikasi (.apk) Playstore Berbayar Jadi Gratis

  Langsung ke isi Menu Alutekno  »  Android  »  Cara Download Aplikasi (.apk) Playstore Berbayar Jadi Gratis Cara Download Aplikasi (.apk) Playstore Berbayar Jadi Gratis Download Aplikasi (Apk) Berbayar jadi Gratis di Playstore  – Pengguna smartphone Android semakin tahun semakin berkembang pesat begitu juga jumlah aplikasi yang telah di publish di playstore semakin meningkat pula. ADVERTISEMENT Daftar Isi Cara Download Aplikasi Playstore Berbayar Jadi Gratis 1. Download Aplikasi Blackmart Alpha 2. Menggunakan Lucky Patcher 3. Mencari File .apk Berbayar dari Situs File Sharing ADVERTISEMENT Aplikasi yang ada di playstore terbagi menjadi dua kategory yaitu yang gratis dan berbayar, aplikasi gratis biasanya terdapat iklan di dalamnya sehingga developer bisa mendapatkan uang untuk mengembangkan aplikasi yang telah di buatnya. Sedangkan Aplikasi berbayar atau premium biasanya tidak terdapat iklan dan mempunyai fitur yang lebih lengkap dibandingkan dengan aplika...

Cara Membuat Form Login Menggunakan HTML&CSS

  Upgrade Responses (2) Sukma Riadi Pakpahan What are your thoughts?  Cancel Respond Agustinus Giri Hartono 3 months ago Aku dah coba, tapi bagian bawah kotak login masih putih. Bagaimana supaya background sama dengan gradasi hijau? di >> body { background: -webkit-linear-gradient(bottom, #2dbd6e, #a6f77b); background-repeat: no-repeat; } 1 1 Arif Firmansyah 3 months ago terima kasih banyak boss cara menjelaskan sangat detail banget….saya berhasil membuat halaman login yang di jelaskan tadi, saya ingin penjelasannya lagi bagaimana cara masuk ke login dan membuat halaman baru karena saya masih pemula Welcome back. You are signed in as  srpakpahansst@gmail.com .  Not you? Tutorial Mendesain Form Login Menggunakan HTML&CSS Kimiyuki Yukawa Follow Mar 25, 2019  · 9 min read Tentu kita tidak asing lagi dengan istilah  login  dalam dunia  website . Halaman  login  sendiri dibuat untuk memberikan akses kepada  user...

PANDUAN CARA INSTALL WORDPRESS DI PC LOCALHOST [OFFLINE]

READY..! START BLOGGING WITH WORDPRESS..? Trending: 15+ Tema WordPress untuk... 15 Sumber Backlink Grati... Jual Tema WordPress Prem... Panduan Lengkap Cara Men... 5 Tema WordPress Terbaik... ALL ABOUT All About WORDPRESS Tutorial DESIGN All About THEMES Download LINUX Tutorial FOREX Forex DEALS Must See HOW TO START A BLOG? Panduan Membuat Blog Hanya 30 Menit Home  »  CMS  »  Panduan Cara Install WordPress di PC Localhost [Offline] PANDUAN CARA INSTALL WORDPRESS DI PC LOCALHOST [OFFLINE] Centerklik  |  CMS ,  WordPress Panduan Cara Install WordPress di PC Localhost [Offline]  – Jika Anda ingin memiliki blog gratis bisa membuat blog pada layanan gratis seperti blogger atau  membuat blog di WordPress.com . Keduanya memang gratis baik dari penggunaan domain maupun hosting, tapi tentunya sesuatu yang gratis tidak akan pernah di beri akses penuh dan masih banyak batasan, Dengan...