TCL登录程序不起作用

时间:2016-04-14 02:04:54

标签: tcl tk

我正在TCL中创建一个登录程序。我有以下代码:

package require Tk
set usr [open "$env(HOME)\\AppData\\Roaming\\basicfile\\USR.txt" r]
set pwd [open "$env(HOME)\\AppData\\Roaming\\basicfile\\PWD.txt" r]
set numtries [expr 3.0]
proc log {} {
  if {$::numtries > 0.0} {
    if {[.e get] == [read $::usr]} {
      if {[.e1 get] == [read $::pwd]} {
        close $::usr
        close $::pwd
        pack forget .l
        pack forget .e
        pack forget .l1
        pack forget .e1
        pack forget .b
        .l configure -text "Login Successful!"
        pack .l
      } else {
        set ::numtries [expr $::numtries - 1.0]
        if {$::numtries <= 0.0} {
          .b configure -state disabled
        }
      }
    } else {
      set ::numtries [expr $::numtries - 1.0]
      if {$::numtries <= 0.0} {
        .b configure -state disabled
      }
    }
  } else {
    .b configure -state disabled
  }
  if {$::numtries <= 0.0} {
    .b configure -state disabled
  }
}
ttk::label .l -text "Enter your name:"
ttk::entry .e
ttk::label .l1 -text "Enter your password:"
ttk::entry .e1 -show "*"
ttk::button .b -text "Login" -command log
pack .l
pack .e
pack .l1
pack .e1
pack .b

此程序打开一个文件夹basicfile,位于Windows的AppData文件夹中。当它运行时,应用程序工作正常,除了一件事。看似错误的一行是set numtries [expr 3.0]。程序是这样的,如果用户名和密码不正确,则从该变量中减去,如果变量达到0,则禁用该按钮。但是,当我运行程序并在输入框中使用错误的用户名和密码按三次按钮时,它会转到行.l configure -text "Login Successful!"并绕过登录部分。我的问题是,为什么它忽略了登录代码并仍然进入?我还应该提一下,如果我将行set numtries [expr 3.0]更改为set numtries [expr 2.0],程序运行正常。谢谢!

2 个答案:

答案 0 :(得分:2)

问题可能是这个。 read命令一次读取整个文件,因此下次从文件中读取时会得到空字符串。如果您的名称和密码字段为空,则它们将等于从您的文件中读取的空字符串,并且登录将成功。

这样的事情应该有效:

set dir $env(HOME)/AppData/Roaming/basicfile

set uf [open [file join $dir USR.txt]]
set pf [open [file join $dir PWD.txt]]

set usr [read -nonewline $uf]
set pwd [read -nonewline $pf]

close $uf
close $pf

set numtries 3

ttk::label .nl -text "Enter your name:"
ttk::entry .ne
ttk::label .pl -text "Enter your password:"
ttk::entry .pe -show "*"
ttk::button .b -text "Login" -command log
pack {*}[winfo children .]

proc log {} {
    global numtries usr pwd

    if {[incr numtries -1] > 0} {
        if {([.ne get] eq $usr) && ([.pe get] eq $pwd)} {
            destroy {*}[winfo children .]
            ttk::label .l -text "Login successful"
            pack .l
        } else {
            .ne delete 0 end
            .pe delete 0 end
        }
    } else {
        destroy {*}[winfo children .]
        ttk::label .l -text "Too many tries"
        pack .l
    }
}

如果你有一个旧的,过时的Tcl版本,pack {*}[winfo children .]eq运营商不会工作:尝试eval pack [winfo children .](同样使用destroy)和而是==。或者更好的是,升级。

文档:closedestroyfileglobalifincropen,{{3 }},packprocreadsetttk::buttonttk::entryttk::label

答案 1 :(得分:0)

您的计划似乎不完整。无论如何,试试这个(更新usr.txt和pwd.txt的路径):

package require Tk
set usr [open "usr.txt" r]
set pwd [open "pwd.txt" r]
set numtries 3 
proc log {} {
    puts "Attempt # $::numtries"
    if {$::numtries <= 0} {
        close $::usr
        close $::pwd
        .l configure -text "Max retries exceeded..."
        .b configure -state disabled
        pack forget .e
        pack forget .e1
        return
    }

    if {([.e get] != [gets $::usr]) || \
        ([.e1 get] != [gets $::pwd])} {
        incr ::numtries -1
        return
    }

    .l configure -text "Login Successful!"
    pack forget .e
    pack forget .e1
    pack forget .b
    close $::usr
    close $::pwd
}
ttk::label .l -text "Enter your name:"
pack .l
ttk::entry .e
ttk::entry .e1
pack .e
pack .e1
button .b -text submit -command log
.b configure -state active 
pack .b