Tcl/Tk Notes (3)

本文介绍了Tcl编程语言的基础知识,包括变量定义与操作、列表构造与解析、环境变量使用及变量跟踪等。通过实例展示了如何利用Tcl进行高效的数据结构处理。

Part IIITclDataStructures

1 MoreaboutVariables

  • The set command
The set command is used to define variables of any type. In addition, the set command will return the value of a variable if it is only passed a single argument. It treats that argument as a variable name and returns the current value of the variable.
File?id=dd6nw3mt_126frfnfccm_b
In thelastcommand,$namegetssubstitutedwithvar.Thenthesetcommandreturnsthevalueofvar,whichisthevalueofvar.Anotherwaytoachievealevelofindirectionlikethisiswithnestedsetcommands.Thelastsetcommandabovecanbewrittenasfollows:
set[setname]
=>thevalueofvar
  • The unset command
You candeleteavariablewiththeunsetcommand:
unset varName varName2 ...
  • Using info to find out about variables
The existenceofavariablecanbetestedwiththeinfoexistscommand.
e.g.
if ![infoexistsfoobar]{
setfoobar0
}else{
incrfoobar }

2 Tcl Lists

The Tcl list has the same structure as a Tcl command. That is, a list is simply a string with list elements separated by white space.Braces or quotes can be used to group words with whitespace into a single list element.
File?id=dd6nw3mt_1272k4p4qgs_b

3 Constructing Lists: list, lappend and concat

The list command constructs a list out of its arguments such that there is one list element for each argument. if any of the arguments contain special characters, the list command adds some quoting to ensure they are parsed as a single element of the resulting list.
e.g. Constructing a list with the list command
set x {1 2}
=> 1 2
set x
=> 1 2
list $x /$ foo
=> {1 2} {$} foo
[Note]: The braces used to group the list value into one argument to the set command are not part of the list value.

The lappend command is used to append elements to the end of a list. You can call lappend with the name of an undefined variable and the variable will be created.
e.g.
lappend new 1 2
=> 1 2
lappend new 3 "4 5"
=> 1 2 3 {4 5}
set new
=> 1 2 3 {4 5}

The concat command is useful for splicing together lists. It works by concatenating its arguments together, separating them with spaces. This multiple lists into one where the top-level list elements in each input list are also top-level list elements in the resulting list.
e.g. Using concat to splice together lists.
concat 1 {2 3} {4 5 6}
=> 1 2 3 4 5 6
It turns out that double quotes behave much like the concat command.
e.g. Double quotes compared to the list command.
set x {1 2}
=> 1 2
set y "$x 3"
=> 1 2 3
set y [concat $x 3]
=> 1 2 3
set z [list $x 3]
=>{1 2} 3
The basic rule is that list and lappend preserve preserve list structure, while concat(or double-quotes)eliminate one level of list structure.

4 Getting List Elements: llength, lindex, and lrange

The llength command returns the number of elements in a list.
The lindex command returns a particular element of a list. It takes an index. List indices count from zero. The keyword end means the last element, and it can be used with lindex, linsert, lrange and lreplace.
e.g.
lindex {1 2 3} 0
=> 1
lindex {1 2 3} 2
=> 3

The lrange command returns a range of list elements. It takes a list and two indices as arguments.
e.g.
lrange {1 2 3 {4 5}} 2 end
=> 3 {4 5}

5 Modifying Lists: linsert and lreplace

The linsert command inserts elements into a list value at a specified index. If the index is 0 or less, then elements are added to the front. If the index is equal to or greater than the length of the list, then the elements are appended to the end. Otherwise, the elements are inserted before the element that is currentl as position index.
lreplace is used to replace a range of list elements with new elements. If you don't specify any new elements, you effectively delete elements from a list.
e.g.
linsert {1 2} 0 new stuff
=> new stuff 1 2
set x [list a {b c} e d]
=> a {b c} e d
lreplace $x 1 2 B C
=> a B C d
lreplace $x 0 0
=> {b c} e d

6 Searching Lists: lsearch

lsearch returns the index of a value in the list, or -1 if it is not present. lsearch supports pattern matching in its search. Glob-style pattern matching is default, and this canbe disabled with the -exact flag.
The example below uses lreplace to delete elements by not specifying any replacement list elements.
e.g.
proc delete {list value} {
set ix [lsearch -exact $list $value]
if {$ix>=0} {
return [lreplace $list $ix $ix]
} else {
return $list
}
}

7 Sorting List: lsort

The three basic types of sorts are specified with the -ascii, -integer, or -real options. The -increasing or -decreasing option indicate the sirting order. The default option set is -ascii -increasing.
File?id=dd6nw3mt_12843xpw3gx_b

8 The split And join Commands

The split command takes a string and turns it into a list by breaking it at specified characters. Stray double-quotes or curly braces in the input can result in invalid list structures and errors in your script. However, the split command provides a robust way to turn input lines into proper Tcl lists.
File?id=dd6nw3mt_129dnrj74dp_b
File?id=dd6nw3mt_130f2ksvcpn_b
The default split character is white space. If there are multiple separator characters in a row, these result in empty list elements- the separators are not collapsed. The following command splits on commas, periods, spaces and tabs:
File?id=dd6nw3mt_131fm4hj3gx_b
The join command is the inverse of split. It takes a list value and reformats it with specified characters separating the list elements. In doing so, it will remove any curly braces from the string representation of the list that are used to group the top-level elements.
File?id=dd6nw3mt_132gxv9m5gb_b

9 Arrays

The index of an array is delimited by parentheses. The index can have any string value, and it canbe the result of variable or command substitution.
e.g. set arra(index) value
The value of an array element is obtained with $ substitution:
e.g. set foo $arr(index)
File?id=dd6nw3mt_133dvtqdmcr_b
If you have complex indices, use a comma to separate different parts of the index. Avoid putting a pace after the comma. It is legal, but a space in an index value will cause problems because parenthesis are not used as a grouping mechanism. The space in the index needs to be quoted with a backslash, or hte whole variable reference needs to be grouped:
e.g. set {arr(I'm asking for trouble)} {I told you so.}
If the array index is stored in a variable, then there is no problem with spaces in the variable's value. The following works fine:
e.g.
set index {I'm asking for trouble}
set arr($index) {I told you so.}
The name of the array can be the result of a substitution. If the name of the array is stored in another variable, then you must use set as shown in the last command below to reference the array elements.
File?id=dd6nw3mt_134ckqvbpf3_b

10 The Array Command

File?id=dd6nw3mt_135g7rtd4rd_b
File?id=dd6nw3mt_137gkb3k889_b
The array names command is perhaps the most useful because it allows easy iteration through an array with a foreach loop:
foreach index [array names arr] {command body}
The order of the names returned by array names is arbitrary. It is essentially determined by the hash table implementation of the array.
The array get and array set operations are used to convert between an array and a list. The list returned by array get has an even number of elements.The first element is an index, and the next is the corresponding array value. The ordering of the indexes is arbitrary. The list argument to array set must have the same structure.
File?id=dd6nw3mt_138fgwktmcn_b

11 Environment Variables

In UNIX, the process environment variables are available through the global array env. The name of the environment variable is the index,e.g. env(PATH), and the array element contains the current value of the environment variable.

12 Tracing Variable Values

The trace command lets you register a command to be called whenever a variable is accessed, modified or unset. The form is:
trace variable name ops command
The name is a Tcl variable name, which can be a simple variable, an array or a element.If a whole array is traced, then the trace is invoked when any element is used according to ops. The ops argument is one or more of the letters: r for read traces, w for write traces, and u for unset traces. The command is executed when one of these events occurs. It is invoked as:
command name1 name2 op
File?id=dd6nw3mt_139f4brdcdj_b
File?id=dd6nw3mt_140c4szdzcj_b
Information about traces on a varible is returned with the vinfo option.
trace vinfo dynamic
=> {r FixDynamic}
A trace is deleted with the vdelete trace option, which has the same form as the varible option.
SUBDIR git-gui SUBDIR gitk-git SUBDIR templates install -d -m 755 '/usr/local/bin' install -d -m 755 '/usr/local/libexec/git-core' install git-daemon git-http-backend git-imap-send git-sh-i18n--envsubst git-shell git-http-fetch git-http-push git-remote-http git-remote-https git-remote-ftp git-remote-ftps git-bisect git-difftool--helper git-filter-branch git-merge-octopus git-merge-one-file git-merge-resolve git-mergetool git-quiltimport git-request-pull git-submodule git-web--browse git-add--interactive git-archimport git-cvsexportcommit git-cvsimport git-cvsserver git-send-email git-svn git-p4 git-instaweb '/usr/local/libexec/git-core' install -m 644 git-mergetool--lib git-rebase--preserve-merges git-sh-i18n git-sh-setup '/usr/local/libexec/git-core' install git git-receive-pack git-shell git-upload-archive git-upload-pack git-cvsserver '/usr/local/bin' make -C templates DESTDIR='' install make[1]: Entering directory `/usr/local/src/git-2.30.0/templates' install -d -m 755 '/usr/local/share/git-core/templates' (cd blt && tar cf - .) | \ (cd '/usr/local/share/git-core/templates' && umask 022 && tar xof -) make[1]: Leaving directory `/usr/local/src/git-2.30.0/templates' install -d -m 755 '/usr/local/libexec/git-core/mergetools' install -m 644 mergetools/* '/usr/local/libexec/git-core/mergetools' install -d -m 755 '/usr/local/share/locale' (cd po/build/locale && tar cf - .) | \ (cd '/usr/local/share/locale' && umask 022 && tar xof -) install -d -m 755 '/usr/local/share/perl5' (cd perl/build/lib && tar cf - .) | \ (cd '/usr/local/share/perl5' && umask 022 && tar xof -) make -C gitweb install make[1]: Entering directory `/usr/local/src/git-2.30.0/gitweb' make[2]: Entering directory `/usr/local/src/git-2.30.0' make[2]: `GIT-VERSION-FILE' is up to date. make[2]: Leaving directory `/usr/local/src/git-2.30.0' install -d -m 755 '/usr/local/share/gitweb' install -m 755 gitweb.cgi '/usr/local/share/gitweb' install -d -m 755 '/usr/local/share/gitweb/static' install -m 644 static/gitweb.js static/gitweb.css static/git-logo.png static/git-favicon.png '/usr/local/share/gitweb/static' make[1]: Leaving directory `/usr/local/src/git-2.30.0/gitweb' make -C gitk-git install make[1]: Entering directory `/usr/local/src/git-2.30.0/gitk-git' install -d -m 755 '/usr/local/bin' install -m 755 gitk-wish '/usr/local/bin'/gitk install -d -m 755 '/usr/local/share/gitk/lib/msgs' install -m 644 po/pt_br.msg '/usr/local/share/gitk/lib/msgs' && install -m 644 po/bg.msg '/usr/local/share/gitk/lib/msgs' && install -m 644 po/zh_cn.msg '/usr/local/share/gitk/lib/msgs' && install -m 644 po/ja.msg '/usr/local/share/gitk/lib/msgs' && install -m 644 po/ca.msg '/usr/local/share/gitk/lib/msgs' && install -m 644 po/sv.msg '/usr/local/share/gitk/lib/msgs' && install -m 644 po/it.msg '/usr/local/share/gitk/lib/msgs' && install -m 644 po/de.msg '/usr/local/share/gitk/lib/msgs' && install -m 644 po/pt_pt.msg '/usr/local/share/gitk/lib/msgs' && install -m 644 po/fr.msg '/usr/local/share/gitk/lib/msgs' && install -m 644 po/ru.msg '/usr/local/share/gitk/lib/msgs' && install -m 644 po/vi.msg '/usr/local/share/gitk/lib/msgs' && install -m 644 po/hu.msg '/usr/local/share/gitk/lib/msgs' && install -m 644 po/es.msg '/usr/local/share/gitk/lib/msgs' && true make[1]: Leaving directory `/usr/local/src/git-2.30.0/gitk-git' make -C git-gui gitexecdir='/usr/local/libexec/git-core' install make[1]: Entering directory `/usr/local/src/git-2.30.0/git-gui' DEST /usr/local/libexec/git-core INSTALL 755 git-gui INSTALL 755 git-gui--askpass LINK git-citool -> git-gui DEST /usr/local/share/git-gui/lib INSTALL 644 tclIndex INSTALL 644 themed.tcl INSTALL 644 spellcheck.tcl INSTALL 644 branch_create.tcl INSTALL 644 line.tcl INSTALL 644 console.tcl INSTALL 644 checkout_op.tcl INSTALL 644 remote_add.tcl INSTALL 644 browser.tcl INSTALL 644 option.tcl INSTALL 644 merge.tcl INSTALL 644 index.tcl INSTALL 644 branch_checkout.tcl INSTALL 644 branch.tcl INSTALL 644 chord.tcl INSTALL 644 diff.tcl INSTALL 644 remote.tcl INSTALL 644 sshkey.tcl INSTALL 644 logo.tcl INSTALL 644 choose_font.tcl INSTALL 644 transport.tcl INSTALL 644 encoding.tcl INSTALL 644 mergetool.tcl INSTALL 644 tools.tcl INSTALL 644 tools_dlg.tcl INSTALL 644 status_bar.tcl INSTALL 644 search.tcl INSTALL 644 shortcut.tcl INSTALL 644 branch_rename.tcl INSTALL 644 class.tcl INSTALL 644 remote_branch_delete.tcl INSTALL 644 choose_repository.tcl INSTALL 644 about.tcl INSTALL 644 blame.tcl INSTALL 644 win32.tcl INSTALL 644 choose_rev.tcl INSTALL 644 commit.tcl INSTALL 644 branch_delete.tcl INSTALL 644 date.tcl INSTALL 644 database.tcl INSTALL 644 error.tcl INSTALL 644 git-gui.ico INSTALL 644 win32_shortcut.js DEST /usr/local/share/git-gui/lib/msgs INSTALL 644 nb.msg INSTALL 644 pt_br.msg INSTALL 644 bg.msg INSTALL 644 zh_cn.msg INSTALL 644 ja.msg INSTALL 644 it.msg INSTALL 644 de.msg INSTALL 644 pt_pt.msg INSTALL 644 fr.msg INSTALL 644 ru.msg INSTALL 644 el.msg INSTALL 644 hu.msg INSTALL 644 vi.msg INSTALL 644 sv.msg make[1]: Leaving directory `/usr/local/src/git-2.30.0/git-gui' bindir=$(cd '/usr/local/bin' && pwd) && \ execdir=$(cd '/usr/local/libexec/git-core' && pwd) && \ destdir_from_execdir_SQ=$(echo 'libexec/git-core' | sed -e 's|[^/][^/]*|..|g') && \ { test "$bindir/" = "$execdir/" || \ for p in git git-shell git-cvsserver; do \ rm -f "$execdir/$p" && \ test -n "" && \ ln -s "$destdir_from_execdir_SQ/bin/$p" "$execdir/$p" || \ { test -z "" && \ ln "$bindir/$p" "$execdir/$p" 2>/dev/null || \ cp "$bindir/$p" "$execdir/$p" || exit; } \ done; \ } && \ for p in git-receive-pack git-upload-archive git-upload-pack; do \ rm -f "$bindir/$p" && \ test -n "" && \ ln -s "git" "$bindir/$p" || \ { test -z "" && \ ln "$bindir/git" "$bindir/$p" 2>/dev/null || \ ln -s "git" "$bindir/$p" 2>/dev/null || \ cp "$bindir/git" "$bindir/$p" || exit; }; \ done && \ for p in git-add git-am git-annotate git-apply git-archive git-bisect--helper git-blame git-branch git-bugreport git-bundle git-cat-file git-check-attr git-check-ignore git-check-mailmap git-check-ref-format git-checkout-index git-checkout git-clean git-clone git-column git-commit-graph git-commit-tree git-commit git-config git-count-objects git-credential-cache--daemon git-credential-cache git-credential-store git-credential git-describe git-diff-files git-diff-index git-diff-tree git-diff git-difftool git-env--helper git-fast-export git-fast-import git-fetch-pack git-fetch git-fmt-merge-msg git-for-each-ref git-for-each-repo git-fsck git-gc git-get-tar-commit-id git-grep git-hash-object git-help git-index-pack git-init-db git-interpret-trailers git-log git-ls-files git-ls-remote git-ls-tree git-mailinfo git-mailsplit git-merge-base git-merge-file git-merge-index git-merge-ours git-merge-recursive git-merge-tree git-merge git-mktag git-mktree git-multi-pack-index git-mv git-name-rev git-notes git-pack-objects git-pack-redundant git-pack-refs git-patch-id git-prune-packed git-prune git-pull git-push git-range-diff git-read-tree git-rebase git-receive-pack git-reflog git-remote-ext git-remote-fd git-remote git-repack git-replace git-rerere git-reset git-rev-list git-rev-parse git-revert git-rm git-send-pack git-shortlog git-show-branch git-show-index git-show-ref git-sparse-checkout git-stash git-stripspace git-submodule--helper git-symbolic-ref git-tag git-unpack-file git-unpack-objects git-update-index git-update-ref git-update-server-info git-upload-archive git-upload-pack git-var git-verify-commit git-verify-pack git-verify-tag git-worktree git-write-tree git-cherry git-cherry-pick git-format-patch git-fsck-objects git-init git-maintenance git-merge-subtree git-restore git-show git-stage git-status git-switch git-whatchanged; do \ rm -f "$execdir/$p" && \ if test -z ""; \ then \ test -n "" && \ ln -s "$destdir_from_execdir_SQ/bin/git" "$execdir/$p" || \ { test -z "" && \ ln "$execdir/git" "$execdir/$p" 2>/dev/null || \ ln -s "git" "$execdir/$p" 2>/dev/null || \ cp "$execdir/git" "$execdir/$p" || exit; }; \ fi \ done && \ remote_curl_aliases="git-remote-https git-remote-ftp git-remote-ftps" && \ for p in $remote_curl_aliases; do \ rm -f "$execdir/$p" && \ test -n "" && \ ln -s "git-remote-http" "$execdir/$p" || \ { test -z "" && \ ln "$execdir/git-remote-http" "$execdir/$p" 2>/dev/null || \ ln -s "git-remote-http" "$execdir/$p" 2>/dev/null || \ cp "$execdir/git-remote-http" "$execdir/$p" || exit; } \ done && \ ./check_bindir "z$bindir" "z$execdir" "$bindir/git-add"
07-15
import tkinter as tk from tkinter import messagebox, Menu, filedialog import mido import os # 音符映射(MIDI音符到简谱) note_map = { 24: &#39;1...&#39;, 26: &#39;2...&#39;, 28: &#39;3...&#39;, 29: &#39;4...&#39;, 31: &#39;5...&#39;, 33: &#39;6...&#39;, 35: &#39;7...&#39;, 36: &#39;1..&#39;, 38: &#39;2..&#39;, 40: &#39;3..&#39;, 41: &#39;4..&#39;, 43: &#39;5..&#39;, 45: &#39;6..&#39;, 47: &#39;7..&#39;, 48: &#39;1.&#39;, 50: &#39;2.&#39;, 52: &#39;3.&#39;, 53: &#39;4.&#39;, 55: &#39;5.&#39;, 57: &#39;6.&#39;, 59: &#39;7.&#39;, 60: &#39;1&#39;, 62: &#39;2&#39;, 64: &#39;3&#39;, 65: &#39;4&#39;, 67: &#39;5&#39;, 69: &#39;6&#39;, 71: &#39;7&#39;, 72: &#39;1*&#39;, 74: &#39;2*&#39;, 76: &#39;3*&#39;, 77: &#39;4*&#39;, 79: &#39;5*&#39;, 81: &#39;6*&#39;, 83: &#39;7*&#39;, 84: &#39;1**&#39;, 86: &#39;2**&#39;, 88: &#39;3**&#39;, 89: &#39;4**&#39;, 91: &#39;5**&#39;, 93: &#39;6**&#39;, 95: &#39;7**&#39;, 96: &#39;1***&#39;, 98: &#39;2***&#39;, 100: &#39;3***&#39;, 101: &#39;4***&#39;, 103: &#39;5***&#39;, 105: &#39;6***&#39;, 107: &#39;7***&#39; } def convert_midi_to_txt(): try: # 打开文件对话框选择MIDI文件 midi_file = filedialog.askopenfilename( title="选择MIDI文件", filetypes=[("MIDI文件", "*.mid;*.midi"), ("所有文件", "*.*")] ) if not midi_file: return # 创建保存文件对话框 txt_file = filedialog.asksaveasfilename( title="保存简谱文件", defaultextension=".txt", filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")] ) if not txt_file: return # 读取MIDI文件 mid = mido.MidiFile(midi_file) # 初始化变量 ticks_per_beat = mid.ticks_per_beat current_tempo = 500000 # 默认tempo(120 BPM) active_notes = {} note_events = [] time_signature = "4/4" # 默认拍号 key_signature = "C" # 默认调号 # 解析所有轨道 for i, track in enumerate(mid.tracks): abs_time = 0 # 绝对时间(tick) for msg in track: abs_time += msg.time # 处理元信息 if msg.is_meta: if msg.type == &#39;set_tempo&#39;: current_tempo = msg.tempo elif msg.type == &#39;time_signature&#39;: time_signature = f"{msg.numerator}/{msg.denominator}" elif msg.type == &#39;key_signature&#39;: key_signature = msg.key continue # 处理音符事件 if msg.type == &#39;note_on&#39; and msg.velocity > 0: # 记录音符开始 active_notes[msg.note] = abs_time elif msg.type == &#39;note_off&#39; or (msg.type == &#39;note_on&#39; and msg.velocity == 0): # 记录音符结束 if msg.note in active_notes: start_time = active_notes[msg.note] duration = abs_time - start_time note_events.append((start_time, duration, msg.note)) del active_notes[msg.note] # 如果没有找到音符事件 if not note_events: messagebox.showwarning("警告", "MIDI文件中未找到音符事件") return # 按开始时间排序 note_events.sort(key=lambda x: x[0]) # 计算最小时间单位(基于16分音符) min_duration = ticks_per_beat // 4 # 生成简谱 score = "" last_end_time = 0 for start_time, duration, note in note_events: # 获取简谱表示 note_str = note_map.get(note, &#39;?&#39;) # 计算音符时值(以最小时间单位计) beats = max(1, round(duration / min_duration)) # 添加音符和时值 score += note_str if beats > 1: score += &#39;-&#39; * (beats - 1) last_end_time = start_time + duration # 添加文件头信息 bpm = int(mido.tempo2bpm(current_tempo)) header = ( f"// 从 {os.path.basename(midi_file)} 转换的简谱\n" f"// 速度: {bpm} BPM\n" f"// 拍号: {time_signature}\n" f"// 调号: {key_signature}\n" f"// 说明: 使用&#39;-&#39;表示音符时值\n\n" ) # 写入文件 with open(txt_file, &#39;w&#39;, encoding=&#39;utf-8&#39;) as f: f.write(header) # 格式化输出(每40个字符换行) line_length = 40 for i in range(0, len(score), line_length): line = score[i:i+line_length] f.write(line + &#39;\n&#39;) messagebox.showinfo("成功", f"简谱文件已保存至:\n{txt_file}") except Exception as e: messagebox.showerror("错误", f"转换失败: {str(e)}") def create_textbox_menu(textbox): """创建文本框右键菜单""" menu = Menu(textbox, tearoff=0) def select_all(event=None): textbox.tag_add(tk.SEL, "1.0", tk.END) textbox.icursor(tk.END) return "break" def copy_text(event=None): textbox.event_generate("<<Copy>>") return "break" def paste_text(event=None): textbox.event_generate("<<Paste>>") return "break" def show_menu(event): try: menu.tk_popup(event.x_root, event.y_root) finally: menu.grab_release() menu.add_command(label="全选", command=select_all) menu.add_separator() menu.add_command(label="复制", command=copy_text) menu.add_command(label="粘贴", command=paste_text) textbox.bind("<Button-3>", show_menu) textbox.bind("<Control-a>", select_all) textbox.bind("<Control-c>", copy_text) textbox.bind("<Control-v>", paste_text) def create_ui(): """创建用户界面""" root = tk.Tk() root.title("MIDI转简谱工具(使用-表示时值)") root.geometry("600x500") root.resizable(True, True) # 设置应用图标 try: root.iconbitmap("midi_icon.ico") except: pass # 创建主框架 main_frame = tk.Frame(root, padx=20, pady=20) main_frame.pack(fill=tk.BOTH, expand=True) # 标题 title_label = tk.Label(main_frame, text="MIDI转简谱工具", font=("Arial", 16, "bold")) title_label.pack(pady=(0, 15)) # 说明文本 description = ( "此工具可将MIDI文件转换为简谱文本文件。\n" "简谱使用数字表示音符,点(.)表示低音,星号(*)表示高音,\n" "使用&#39;-&#39;表示音符时值(不表示休止符)。\n" "例如:&#39;5---&#39;表示一个四分音符的5和三个延长符" ) desc_label = tk.Label(main_frame, text=description, justify=tk.LEFT) desc_label.pack(pady=(0, 20)) # 转换按钮 convert_btn = tk.Button( main_frame, text="选择MIDI文件并转换", command=convert_midi_to_txt, bg="#4CAF50", fg="white", font=("Arial", 12), padx=20, pady=10 ) convert_btn.pack(pady=20) # 简谱示例 example_frame = tk.LabelFrame(main_frame, text="简谱示例", padx=10, pady=10) example_frame.pack(fill=tk.BOTH, expand=True, pady=(20, 0)) example_text = ( "5---3-5-1*---7-6-1*--5----5-1-2-3-2-1-2---\n" "5---3-5-1*---7-6-1*--5----5-2-3-4-7-.1---\n" "6---1*--1*---7---6-7-1*---6-7-1*--6-6-5-3-1-2---" ) example_label = tk.Label(example_frame, text=example_text, font=("Courier", 12), justify=tk.LEFT) example_label.pack(padx=10, pady=10) # 状态栏 status_bar = tk.Label(root, text="就绪", bd=1, relief=tk.SUNKEN, anchor=tk.W) status_bar.pack(side=tk.BOTTOM, fill=tk.X) # 版权信息 copyright_label = tk.Label(root, text="© 2023 MIDI转简谱工具", fg="gray") copyright_label.pack(side=tk.BOTTOM, pady=5) return root if __name__ == "__main__": app = create_ui() app.mainloop()
07-09
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值