代码之家  ›  专栏  ›  技术社区  ›  njamescouk

tcl返回用户选择的文件名

  •  0
  • njamescouk  · 技术社区  · 8 年前

    这让我想起了20多年前学习MFC的情景:-(

    我希望用户选择一个文件名。选择它之后,我希望能够在程序的其他部分使用该文件名。迄今为止,我的努力以以下内容结束:

    package require Tk
    
    wm title . "get user specified file name (how hard can it be?)"
    
    labelframe .lfInput -text "user specified file name goes here"
    
    set userChoice "userChoice is bound to this field"
    # note not $userChoice in next line
    entry .lfInput.ent -width 40 -textvariable userChoice
    button .lfInput.but -text "Kindly press this button and choose a file.\nNot only will I write the file name\nin the the field to the left, I'll make\nit available to anyone who cares\n to press the button below."\
     -command "fileDialog .lfInput .lfInput.ent"
    
    pack .lfInput.ent -side left -padx 10 -expand yes -fill x
    pack .lfInput.but -side left -padx 10 -pady 3
    pack .lfInput -fill x -padx 2c -pady 3
    focus .lfInput.ent
    
    button .b -text "Press this button to write\nuserChoice to the console\nthereby demonstrating\nthe ability to get a file\nname from the user."\
        -command "writeTheArg {$userChoice}"
    pack .b
    
    
    proc fileDialog {w ent} {
        set types { {"All files"       *} }
    
        set userFile [tk_getOpenFile -multiple false -filetypes $types -parent $w -typevariable "All files"]
    
        if {[string compare $userFile ""]} {
            $ent delete 0 end
            $ent insert 0 $userFile
            $ent xview end
        }
    
        puts "line 34: local userFile is $userFile"
    }
    
    proc writeTheArg {s} {
        puts "line 38: puts $s"
    }
    
    puts "line 41: user choice is {$userChoice}"
    puts "when pressing second button, the file chosen by the user should show up here\n\
          by virtue of the textvariable option at line 9\n...\n"
    

    就其所述目的而言,这太过分了,我们在这里所做的任何事情都可以在proc fileDialog中完成。但是如果有更多的用户选择要收集 大概我们可以在过程更新文件(proceupdateduserfile)中对它们进行排序,然后继续。

    proc fileDialog应该返回一个本地$userFile,这是关于记住$$$

    2 回复  |  直到 8 年前
        1
  •  0
  •   Donal Fellows    8 年前

    最简单的方法是使用全局变量。

    proc fileDialog {w ent} {
        global userFile
        set types { {"All files"       *} }
    
        set file [tk_getOpenFile -filetypes $types -parent $w]
    
        if {[string compare $file ""]} {
    
            # Only update the global if the user didn't cancel
            set userFile $file
    
            $ent delete 0 end
            $ent insert 0 $userFile
            $ent xview end
        }
    
        puts "line 34: local userFile is $userFile"
    }
    

    然后,其余代码可以读取该全局文件以获取该文件。最棘手的一点是,当用户在对话框中接受文件时,全局将发生变化;通过设置 写入跟踪 userFile 全局变量,并在更改时更新UI。当然,您可以使用 -textvariable a选项 label :为您在幕后设置跟踪,以便始终显示变量的当前内容:

    pack [label .showTheUserFile -textvariable userFile]
    

    您只需直接设置跟踪(使用 trace )对于更复杂的交互:

    trace add variable userFile write UpdatedUserFile
    proc UpdatedUserFile {args} {
        # Note that we're ignoring the arguments to the callback here; we only ever apply
        # this trace to one event on one variable so we know what's going on without
        # being told explicitly
    
        # Here's a very simple version; for more complicated versions, see your imagination!
    
        global userFile
        puts "The user has selected the file $userFile"
    }
    
        2
  •  0
  •   njamescouk    8 年前

    我曾经(现在仍然)遇到的问题是忘记使用$引用变量。这会导致在尝试传递参数时出现奇怪的错误,并会导致没有经验的人开始做奇怪而奇妙的事情,就像原来的问题一样。谢谢你的帮助,否则我会完全放弃的!

    正确版本如下:

    package require Tk
    
    wm title . "get user specified file name"
    
    labelframe .fileSelectorGroup -text "press the button to choose your file"
    
    set userFileChoice "userFileChoice is bound to this field"
    # note not $userFileChoice in next line
    entry .fileSelectorGroup.ent -width 40 -textvariable userFileChoice
    button .fileSelectorGroup.but -text "Kindly press this button and choose a file.\nNot only will I write the file name\nin the the field to the left, I'll make\nit appear in the console."\
     -command "getUserFileAndProceed .fileSelectorGroup .fileSelectorGroup.ent"
    
    pack .fileSelectorGroup.ent -side left -padx 10 -expand yes -fill x
    pack .fileSelectorGroup.but -side left -padx 10 -pady 3
    pack .fileSelectorGroup -fill x -padx 2c -pady 3
    focus .fileSelectorGroup.ent
    
    proc getUserFileAndProceed {w ent} {
        set userChoice [fileDialog $w $ent]
        puts "line 21: userChoice is $userChoice"
        puts "have a nice day"
    }
    
    proc fileDialog {w ent} {
        set types { {"All files"       *} }
    
        set userFile [tk_getOpenFile -multiple false -filetypes $types -parent $w -typevariable "All files"]
    
        if {[string compare $userFile ""]} {
            $ent delete 0 end
            $ent insert 0 $userFile
            $ent xview end
        }
    
        return $userFile
    }
    
    推荐文章