为什么 "Click row ndx . . ." 语句在此 Applescript 中无效?
Why does the "Click row ndx . . ." statement have no effect in this Applescript?
"on switchDir" 例程旨在定位作为 "directory" 传递的路径的每个元素并单击它,以便目录路径进入所需的最终输出目录。
用鼠标激活所需的行时。正常情况下,必须双击才能select!
这是"on switchDir"单独的代码:
on switchDir(directory, appName, selectDefault, createIt)
local compname, bootvolume
set compname to get computer name of (system info)
set bootvolume to get boot volume of (system info)
if directory is equal to "~" then set directory to system attribute ("HOME")
if directory starts with "~/" then set directory to (system attribute ("HOME")) & text 2 through -1 of (get directory)
if not checkPathExists(directory) then
if createIt then
do shell script ("mkdir -p " & (POSIX path of directory))
else
return false
end if
end if
if directory begins with "/" then
set directory to bootvolume & (get directory)
end if
tell application "System Events" to tell (process "iTunes"'s front window)
delay 1
click pop up button 1 of group 1 -- selects the drop-down box above the directory listing
set max to the count of menu items of menu 1 of pop up button 1 of group 1 -- number of items in the drop-down menu
set ndx to 1
repeat while ndx ≤ max
if the title of group 1's pop up button 1's menu 1's menu item ndx as string is equal to compname then -- found the absolute top-level directory
click group 1's pop up button 1's menu 1's menu item ndx - so choose it and go to next part of navigation
exit repeat
else -- keep looking
set ndx to (get ndx) + 1
end if
end repeat
if ndx > max then error "Never found " & compname
set thePath to every item of my splitString(directory, "/") -- thePath equals every individual folder in the path's name in order
repeat with dir in thePath
set max to the (count of rows in outline 1 of scroll area 1 of splitter group 1 of group 1) -- max equals the number of rows in the "directory contents" list box
log max
set ndx to 2 -- row 1 is just the colum titles
repeat while ndx ≤ max
log the value of text field 1 of UI element 1 of row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 as string
log the value of text field 1 of UI element 1 of row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 as string is equal to dir as string
if the value of text field 1 of UI element 1 of row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 as string is equal to dir as string then -- this is the row we want!
log "found " & dir & " at row " & ndx as string
select row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 -- included to make sure the reference in the "click" statement is correct
click row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 -- supposed to "click" the desired folder name to choose it and dive deeper, BUT IT DOESN'T ACTUALLY DO THAT!
exit repeat -- apparently never executed because the loop keeps going past finding the desired directory's name and crashes at the first blank row!
else
set ndx to (get ndx) + 1
end if
if ndx > max then error "Never found " & dir
end repeat
end repeat
end tell
error "success"
return true
end switchDir
错误发生在"on switchDir",剩下的代码只包含在内,以便代码在"Script Editor"下执行。 "Click row ndx . . . ." 语句和它之后的 "exit repeat" 语句显然都没有被执行,因为循环继续 运行 超过了 "found " 的记录。 . . .并因此在列表框中的第一个空白行崩溃。 found(带有引号)可用作查找代码的搜索词。
完整的、运行可用的应用程序代码如下:
on splitString(theString, theDelimiter)
set oldDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to theDelimiter
set theArray to every text item of theString
set AppleScript's text item delimiters to oldDelimiters
return theArray
end splitString
on checkPathExists(thePath)
if thePath is equal to "~" then set thePath to system attribute ("HOME")
if thePath starts with "~/" then set thePath to (system attribute ("HOME")) & text 2 through -1 of (get thePath)
try
POSIX file thePath as alias
return true
on error
return false
end try
end checkPathExists
on switchDir(directory, appName, selectDefault, createIt)
local compname, bootvolume
set compname to get computer name of (system info)
set bootvolume to get boot volume of (system info)
if directory is equal to "~" then set directory to system attribute ("HOME")
if directory starts with "~/" then set directory to (system attribute ("HOME")) & text 2 through -1 of (get directory)
if not checkPathExists(directory) then
if createIt then
do shell script ("mkdir -p " & (POSIX path of directory))
else
return false
end if
end if
if directory begins with "/" then
set directory to bootvolume & (get directory)
end if
tell application "System Events" to tell (process "iTunes"'s front window)
delay 1
click pop up button 1 of group 1 -- selects the drop-down box above the directory listing
set max to the count of menu items of menu 1 of pop up button 1 of group 1 -- number of items in the drop-down menu
set ndx to 1
repeat while ndx ≤ max
if the title of group 1's pop up button 1's menu 1's menu item ndx as string is equal to compname then -- found the absolute top-level directory
click group 1's pop up button 1's menu 1's menu item ndx - so choose it and go to next part of navigation
exit repeat
else -- keep looking
set ndx to (get ndx) + 1
end if
end repeat
if ndx > max then error "Never found " & compname
set thePath to every item of my splitString(directory, "/") -- thePath equals every individual folder in the path's name in order
repeat with dir in thePath
set max to the (count of rows in outline 1 of scroll area 1 of splitter group 1 of group 1) -- max equals the number of rows in the "directory contents" list box
log max
set ndx to 2 -- row 1 is just the colum titles
repeat while ndx ≤ max
log the value of text field 1 of UI element 1 of row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 as string
log the value of text field 1 of UI element 1 of row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 as string is equal to dir as string
if the value of text field 1 of UI element 1 of row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 as string is equal to dir as string then -- this is the row we want!
log "found " & dir & " at row " & ndx as string
select row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 -- included to make sure the reference in the "click" statement is correct
click row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 -- supposed to "click" the desired folder name to choose it and dive deeper, BUT IT DOESN'T ACTUALLY DO THAT!
exit repeat -- apparently never executed because the loop keeps going past finding the desired directory's name and crashes at the first blank row!
else
set ndx to (get ndx) + 1
end if
if ndx > max then error "Never found " & dir
end repeat
end repeat
end tell
error "success"
return true
end switchDir
set directory to "/Users/bryandunphy/Music"
try
tell application "iTunes" to quit
end try
tell application "System Events"
key down option
tell application "iTunes" to activate
key up option
repeat until process "iTunes" exists
delay 0.5
end repeat
click process "iTunes"'s window 1's button 2
my switchDir(directory, "iTunes", false, true)
delay 2
set libraryName to value of text field "Save As:" of window "New iTunes Library" of process "iTunes"
delay 2
click process "iTunes"'s window "New iTunes Library"'s button "Save"
end tell
return libraryName
任何关于错误原因和/或如何解决错误的想法都将不胜感激。
我重构了您的 onSwitchDir 函数,使其在我的机器上运行,并使其更具可读性。
我还添加了大量日志记录以帮助解决问题,请随时删除。
on switchDir(directory, appName, selectDefault, createIt)
local compname, bootvolume
set sysInfo to (system info) -- cache value to reduce processing time
set compname to get computer name of sysInfo
log "compname: " & compname
set bootvolume to get boot volume of sysInfo
log "bootvolume: " & bootvolume
if directory is equal to "~" then set directory to system attribute ("HOME")
if directory starts with "~/" then set directory to (system attribute ("HOME")) & text 2 through -1 of (get directory)
if not checkPathExists(directory) then
if createIt then
do shell script ("mkdir -p " & (POSIX path of directory))
else
return false
end if
end if
if directory begins with "/" then
set directory to bootvolume & (get directory)
end if
tell application "System Events" to tell (process "iTunes"'s front window)
-- ensure view is set to expanded view
try
click pop up button 1 of group 1
on error
key code 81 using {command down} -- expand view
delay 2 -- esnure it finishes expanding before continuing
end try
-- name the item, making the code more readable
set dropDownMenuBtn to menu 1 of pop up button 1 of group 1
click dropDownMenuBtn -- selects the drop-down box above the directory listing
-- Set drop-down menu to go to system's root folder
-- Variation of solution from
tell pop up button 1 of group 1
if value of it is not equal to compname then
set menuItemTitles to name of menu items of menu 1
--check if the menu item exists
if compname is in menuItemTitles then
--menu item exists; click on it
click menu item compname of menu 1
log "yay! found it! setting menu to item " & compname
else
--the menu item to select doesn't exist; hide the menu
log "bummer! " & compname & " doesn't exist"
key code 53
end if
else
log "yay! menu already set to " & compname
end if
end tell
-- Make iTunes dialog navigate to root folder
set thePath to every item of my splitString(directory, "/") -- thePath equals every individual folder in the path's name in order
log "thePath: " & thePath
set isFound to false -- so we can exit the repeat loop when needed
repeat with dir in thePath
if isFound is false then
-- set reference to UI element for readability
set theOutline to outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1
set max to the (count of rows in theOutline) -- max equals the number of rows in the "directory contents" list box
log "max for " & dir & ": " & max
set ndx to 2 -- row 1 is just the column titles
repeat while ndx ≤ max
-- set reference to item for readability
set theRow to row ndx of theOutline
-- set reference to item for readability
set theElement to text field 1 of UI element 1 of theRow
-- if we have found the appropriate item
if the value of theElement is equal to dir as string then
-- set focus so we can use keyboard commands on it
set value of attribute "AXFocused" of theOutline to true
-- select the item in the list
select theRow
-- set boolean so we can avoid re-running the repeat loop
set isFound to true
-- exit inner repeat
exit repeat
else
set ndx to (get ndx) + 1
end if
if ndx > max then error "Never found " & dir
end repeat
else
-- exit outer repeat
exit repeat
end if
end repeat
-- CMD-o to open the selected directory
keystroke "o" using {command down}
end tell
end switchDir
set directory to "/Users/username/Music"
try
tell application "iTunes" to quit
end try
tell application "System Events"
key down option
tell application "iTunes" to activate
key up option
repeat until process "iTunes" exists
delay 0.5
end repeat
click process "iTunes"'s window 1's button 2
my switchDir(directory, "iTunes", false, true)
delay 0.5
set libraryName to value of text field "Save As:" of window "New iTunes Library" of process "iTunes"
delay 0.5
click process "iTunes"'s window "New iTunes Library"'s button "Save"
end tell
return libraryName
值得注意的变化:
- 我更改了退出重复循环的处理方式;您的代码有一个缺陷,即使在发出
exit repeat
之后,该缺陷也会导致重复循环继续退出
- 我减少了对系统信息的调用次数,从而加快了脚本速度
- 我创建了变量作为对
menu 1 of pop up button 1 of group 1
等项目的引用,使脚本不那么密集且更易于阅读
- 我更改了选择下拉菜单项的方法(我觉得这段代码更容易理解)
- 我添加了
keystroke "o"
命令,但将它放在了重复循环之后(由于某种原因它在循环中不起作用)
- 我添加了一些错误处理以使脚本在我的系统上运行;例如,如果新库 window 已打开但处于紧凑模式,则
group 1
引用将导致错误。通过确保扩展 window,group 1
解决,我不再收到错误。
请注意此脚本的结果是 iTunes 警告它无法在请求的位置创建新库。我相信这是因为我只有整个脚本的片段。我想您有代码的另一端,可以解决问题。如果是这样,您应该能够毫不费力地将这些更改合并到您的项目中。
"on switchDir" 例程旨在定位作为 "directory" 传递的路径的每个元素并单击它,以便目录路径进入所需的最终输出目录。
用鼠标激活所需的行时。正常情况下,必须双击才能select!
这是"on switchDir"单独的代码:
on switchDir(directory, appName, selectDefault, createIt)
local compname, bootvolume
set compname to get computer name of (system info)
set bootvolume to get boot volume of (system info)
if directory is equal to "~" then set directory to system attribute ("HOME")
if directory starts with "~/" then set directory to (system attribute ("HOME")) & text 2 through -1 of (get directory)
if not checkPathExists(directory) then
if createIt then
do shell script ("mkdir -p " & (POSIX path of directory))
else
return false
end if
end if
if directory begins with "/" then
set directory to bootvolume & (get directory)
end if
tell application "System Events" to tell (process "iTunes"'s front window)
delay 1
click pop up button 1 of group 1 -- selects the drop-down box above the directory listing
set max to the count of menu items of menu 1 of pop up button 1 of group 1 -- number of items in the drop-down menu
set ndx to 1
repeat while ndx ≤ max
if the title of group 1's pop up button 1's menu 1's menu item ndx as string is equal to compname then -- found the absolute top-level directory
click group 1's pop up button 1's menu 1's menu item ndx - so choose it and go to next part of navigation
exit repeat
else -- keep looking
set ndx to (get ndx) + 1
end if
end repeat
if ndx > max then error "Never found " & compname
set thePath to every item of my splitString(directory, "/") -- thePath equals every individual folder in the path's name in order
repeat with dir in thePath
set max to the (count of rows in outline 1 of scroll area 1 of splitter group 1 of group 1) -- max equals the number of rows in the "directory contents" list box
log max
set ndx to 2 -- row 1 is just the colum titles
repeat while ndx ≤ max
log the value of text field 1 of UI element 1 of row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 as string
log the value of text field 1 of UI element 1 of row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 as string is equal to dir as string
if the value of text field 1 of UI element 1 of row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 as string is equal to dir as string then -- this is the row we want!
log "found " & dir & " at row " & ndx as string
select row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 -- included to make sure the reference in the "click" statement is correct
click row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 -- supposed to "click" the desired folder name to choose it and dive deeper, BUT IT DOESN'T ACTUALLY DO THAT!
exit repeat -- apparently never executed because the loop keeps going past finding the desired directory's name and crashes at the first blank row!
else
set ndx to (get ndx) + 1
end if
if ndx > max then error "Never found " & dir
end repeat
end repeat
end tell
error "success"
return true
end switchDir
错误发生在"on switchDir",剩下的代码只包含在内,以便代码在"Script Editor"下执行。 "Click row ndx . . . ." 语句和它之后的 "exit repeat" 语句显然都没有被执行,因为循环继续 运行 超过了 "found " 的记录。 . . .并因此在列表框中的第一个空白行崩溃。 found(带有引号)可用作查找代码的搜索词。
完整的、运行可用的应用程序代码如下:
on splitString(theString, theDelimiter)
set oldDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to theDelimiter
set theArray to every text item of theString
set AppleScript's text item delimiters to oldDelimiters
return theArray
end splitString
on checkPathExists(thePath)
if thePath is equal to "~" then set thePath to system attribute ("HOME")
if thePath starts with "~/" then set thePath to (system attribute ("HOME")) & text 2 through -1 of (get thePath)
try
POSIX file thePath as alias
return true
on error
return false
end try
end checkPathExists
on switchDir(directory, appName, selectDefault, createIt)
local compname, bootvolume
set compname to get computer name of (system info)
set bootvolume to get boot volume of (system info)
if directory is equal to "~" then set directory to system attribute ("HOME")
if directory starts with "~/" then set directory to (system attribute ("HOME")) & text 2 through -1 of (get directory)
if not checkPathExists(directory) then
if createIt then
do shell script ("mkdir -p " & (POSIX path of directory))
else
return false
end if
end if
if directory begins with "/" then
set directory to bootvolume & (get directory)
end if
tell application "System Events" to tell (process "iTunes"'s front window)
delay 1
click pop up button 1 of group 1 -- selects the drop-down box above the directory listing
set max to the count of menu items of menu 1 of pop up button 1 of group 1 -- number of items in the drop-down menu
set ndx to 1
repeat while ndx ≤ max
if the title of group 1's pop up button 1's menu 1's menu item ndx as string is equal to compname then -- found the absolute top-level directory
click group 1's pop up button 1's menu 1's menu item ndx - so choose it and go to next part of navigation
exit repeat
else -- keep looking
set ndx to (get ndx) + 1
end if
end repeat
if ndx > max then error "Never found " & compname
set thePath to every item of my splitString(directory, "/") -- thePath equals every individual folder in the path's name in order
repeat with dir in thePath
set max to the (count of rows in outline 1 of scroll area 1 of splitter group 1 of group 1) -- max equals the number of rows in the "directory contents" list box
log max
set ndx to 2 -- row 1 is just the colum titles
repeat while ndx ≤ max
log the value of text field 1 of UI element 1 of row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 as string
log the value of text field 1 of UI element 1 of row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 as string is equal to dir as string
if the value of text field 1 of UI element 1 of row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 as string is equal to dir as string then -- this is the row we want!
log "found " & dir & " at row " & ndx as string
select row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 -- included to make sure the reference in the "click" statement is correct
click row ndx of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1 -- supposed to "click" the desired folder name to choose it and dive deeper, BUT IT DOESN'T ACTUALLY DO THAT!
exit repeat -- apparently never executed because the loop keeps going past finding the desired directory's name and crashes at the first blank row!
else
set ndx to (get ndx) + 1
end if
if ndx > max then error "Never found " & dir
end repeat
end repeat
end tell
error "success"
return true
end switchDir
set directory to "/Users/bryandunphy/Music"
try
tell application "iTunes" to quit
end try
tell application "System Events"
key down option
tell application "iTunes" to activate
key up option
repeat until process "iTunes" exists
delay 0.5
end repeat
click process "iTunes"'s window 1's button 2
my switchDir(directory, "iTunes", false, true)
delay 2
set libraryName to value of text field "Save As:" of window "New iTunes Library" of process "iTunes"
delay 2
click process "iTunes"'s window "New iTunes Library"'s button "Save"
end tell
return libraryName
任何关于错误原因和/或如何解决错误的想法都将不胜感激。
我重构了您的 onSwitchDir 函数,使其在我的机器上运行,并使其更具可读性。
我还添加了大量日志记录以帮助解决问题,请随时删除。
on switchDir(directory, appName, selectDefault, createIt)
local compname, bootvolume
set sysInfo to (system info) -- cache value to reduce processing time
set compname to get computer name of sysInfo
log "compname: " & compname
set bootvolume to get boot volume of sysInfo
log "bootvolume: " & bootvolume
if directory is equal to "~" then set directory to system attribute ("HOME")
if directory starts with "~/" then set directory to (system attribute ("HOME")) & text 2 through -1 of (get directory)
if not checkPathExists(directory) then
if createIt then
do shell script ("mkdir -p " & (POSIX path of directory))
else
return false
end if
end if
if directory begins with "/" then
set directory to bootvolume & (get directory)
end if
tell application "System Events" to tell (process "iTunes"'s front window)
-- ensure view is set to expanded view
try
click pop up button 1 of group 1
on error
key code 81 using {command down} -- expand view
delay 2 -- esnure it finishes expanding before continuing
end try
-- name the item, making the code more readable
set dropDownMenuBtn to menu 1 of pop up button 1 of group 1
click dropDownMenuBtn -- selects the drop-down box above the directory listing
-- Set drop-down menu to go to system's root folder
-- Variation of solution from
tell pop up button 1 of group 1
if value of it is not equal to compname then
set menuItemTitles to name of menu items of menu 1
--check if the menu item exists
if compname is in menuItemTitles then
--menu item exists; click on it
click menu item compname of menu 1
log "yay! found it! setting menu to item " & compname
else
--the menu item to select doesn't exist; hide the menu
log "bummer! " & compname & " doesn't exist"
key code 53
end if
else
log "yay! menu already set to " & compname
end if
end tell
-- Make iTunes dialog navigate to root folder
set thePath to every item of my splitString(directory, "/") -- thePath equals every individual folder in the path's name in order
log "thePath: " & thePath
set isFound to false -- so we can exit the repeat loop when needed
repeat with dir in thePath
if isFound is false then
-- set reference to UI element for readability
set theOutline to outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of group 1
set max to the (count of rows in theOutline) -- max equals the number of rows in the "directory contents" list box
log "max for " & dir & ": " & max
set ndx to 2 -- row 1 is just the column titles
repeat while ndx ≤ max
-- set reference to item for readability
set theRow to row ndx of theOutline
-- set reference to item for readability
set theElement to text field 1 of UI element 1 of theRow
-- if we have found the appropriate item
if the value of theElement is equal to dir as string then
-- set focus so we can use keyboard commands on it
set value of attribute "AXFocused" of theOutline to true
-- select the item in the list
select theRow
-- set boolean so we can avoid re-running the repeat loop
set isFound to true
-- exit inner repeat
exit repeat
else
set ndx to (get ndx) + 1
end if
if ndx > max then error "Never found " & dir
end repeat
else
-- exit outer repeat
exit repeat
end if
end repeat
-- CMD-o to open the selected directory
keystroke "o" using {command down}
end tell
end switchDir
set directory to "/Users/username/Music"
try
tell application "iTunes" to quit
end try
tell application "System Events"
key down option
tell application "iTunes" to activate
key up option
repeat until process "iTunes" exists
delay 0.5
end repeat
click process "iTunes"'s window 1's button 2
my switchDir(directory, "iTunes", false, true)
delay 0.5
set libraryName to value of text field "Save As:" of window "New iTunes Library" of process "iTunes"
delay 0.5
click process "iTunes"'s window "New iTunes Library"'s button "Save"
end tell
return libraryName
值得注意的变化:
- 我更改了退出重复循环的处理方式;您的代码有一个缺陷,即使在发出
exit repeat
之后,该缺陷也会导致重复循环继续退出
- 我减少了对系统信息的调用次数,从而加快了脚本速度
- 我创建了变量作为对
menu 1 of pop up button 1 of group 1
等项目的引用,使脚本不那么密集且更易于阅读 - 我更改了选择下拉菜单项的方法(我觉得这段代码更容易理解)
- 我添加了
keystroke "o"
命令,但将它放在了重复循环之后(由于某种原因它在循环中不起作用) - 我添加了一些错误处理以使脚本在我的系统上运行;例如,如果新库 window 已打开但处于紧凑模式,则
group 1
引用将导致错误。通过确保扩展 window,group 1
解决,我不再收到错误。
请注意此脚本的结果是 iTunes 警告它无法在请求的位置创建新库。我相信这是因为我只有整个脚本的片段。我想您有代码的另一端,可以解决问题。如果是这样,您应该能够毫不费力地将这些更改合并到您的项目中。