Q about tk buttons

Hi guys, I have a little problem with the buttons in tk. I want to add 1 to
a variable when pushing a button but tk won't let me.
Here some of my code:

require "tk"
var = TkVariable.new(0) #defining variable
var += 1 #making it a fixnum and adding 1

root = TkRoot.new()

label = TkLabel.new(:text=> var).pack()

button = TkButton.new(:text=> "Button", :command=>proc{var += 1}).pack()

Tk.mainloop

Why can I use var += 1 outside of the button, when I can't use it inside it.

Please help me :S

Thanks in advance.

···

--
"winners never quit, quitters never win"

Message-ID: <99b4ad3b0604111441p38d22688q14e03516af13db40@mail.gmail.com>

Why can I use var += 1 outside of the button, when I can't use it inside it.

It means "var = var + 1".
"var + 1" returns 4, because TkVariable#+(obj) method expects
"numerical plus" when the arguemnt 'obj' is kind of Numeric.
And by setting the numeric value 4 to var, var losts the link
to the TkVariable object.

Therefore, for example,

var = TkVariable.new(0) #defining variable
var += 1 #making it a fixnum and adding 1

var.value = var + 1
  or
var.numeric += 1

root = TkRoot.new()

label = TkLabel.new(:text=> var).pack()

label = TkLabel.new(:textvariable=>var).pack()

button = TkButton.new(:text=> "Button", :command=>proc{var += 1}).pack()

button = TkButton.new(:text=> "Button", :command=>proc{var.value = var + 1}).pack()
   or
button = TkButton.new(:text=> "Button", :command=>proc{var.numeric += 1}).pack()

···

From: "Jeppe Jakobsen" <jeppe88@gmail.com>
Subject: Q about tk buttons
Date: Wed, 12 Apr 2006 06:41:39 +0900

--
Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)

I'm probably misunderstanding the question, but after reading this post
I wrote a quick ruby test script to see if I could increment a variable
using a tkbutton and it seemed to work for me. Here is the code I used.
(I don't know if this is what you are trying to do though)

require 'tk'

class Hi
  @var = 1;

  @b1 = TkButton.new(:text => "Click me", :command => proc {puts @var;
@var += 1}).pack

  def initialize
    Tk.mainloop
  end
end

h = Hi.new()

############the first batch of code I wrote didn't have a class
definition, I changed it so I could see what it would look like inside
of a class, here is the original code

require 'tk'

var = 1;

b1 = TkButton.new(:text => "Click me", :command => proc {puts var; var
+= 1}).pack

Tk.mainloop

···

--
Posted via http://www.ruby-forum.com/.

Thanks that kind of worked, but how come that the variable still returns 0,
when I add

puts var.value

to my code, just before Tk.mainloop?

···

2006/4/12, Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>:

From: "Jeppe Jakobsen" <jeppe88@gmail.com>
Subject: Q about tk buttons
Date: Wed, 12 Apr 2006 06:41:39 +0900
Message-ID: <99b4ad3b0604111441p38d22688q14e03516af13db40@mail.gmail.com>
> Why can I use var += 1 outside of the button, when I can't use it inside
it.

It means "var = var + 1".
"var + 1" returns 4, because TkVariable#+(obj) method expects
"numerical plus" when the arguemnt 'obj' is kind of Numeric.
And by setting the numeric value 4 to var, var losts the link
to the TkVariable object.

Therefore, for example,

> var = TkVariable.new(0) #defining variable
> var += 1 #making it a fixnum and adding 1

var.value = var + 1
  or
var.numeric += 1

> root = TkRoot.new()
>
> label = TkLabel.new(:text=> var).pack()

label = TkLabel.new(:textvariable=>var).pack()

> button = TkButton.new(:text=> "Button", :command=>proc{var += 1}).pack()

button = TkButton.new(:text=> "Button", :command=>proc{var.value = var +
1}).pack()
   or
button = TkButton.new(:text=> "Button", :command=>proc{var.numeric +=
1}).pack()

--
Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)

--
"winners never quit, quitters never win"

Message-ID: <99b4ad3b0604120141ha09eaacoa4b3a30bf18f9285@mail.gmail.com>

Thanks that kind of worked, but how come that the variable still returns 0,
when I add

puts var.value

to my code, just before Tk.mainloop?

???

---< var-test1.rb >----------------------------------------
require "tk"
var = TkVariable.new(0) #defining variable
var += 1 #making it a fixnum and adding 1

root = TkRoot.new()

label = TkLabel.new(:text=> var).pack()

button = TkButton.new(:text=> "Button", :command=>proc{var += 1}).pack()

puts var.value

Tk.mainloop

···

From: "Jeppe Jakobsen" <jeppe88@gmail.com>
Subject: Re: Q about tk buttons
Date: Wed, 12 Apr 2006 17:41:38 +0900
-----------------------------------------------------------

$ /usr/local/bin/ruby -v
ruby 1.8.4 (2006-04-06) [i686-linux]
$ /usr/local/bin/ruby var-test1.rb
var-test1.rb:11: undefined method `value' for 1:Fixnum (NoMethodError)

---< var-test2.rb >----------------------------------------
require "tk"
var = TkVariable.new(0)
var.numeric += 1
label = TkLabel.new(:textvariable=>var).pack()
button = TkButton.new(:text=> "Button", :command=>proc{var.numeric += 1}).pack()
puts var.value
Tk.mainloop
-----------------------------------------------------------

$ /usr/local/bin/ruby -v
ruby 1.8.4 (2006-04-06) [i686-linux]
$ /usr/local/bin/ruby var-test2.rb
1
$

--
Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)

Oh sorry I meant to say that it returns 1. If I click the button 29 times,
the label shows 30, but the value that was puts'ed is still 1.

···

2006/4/12, Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>:

From: "Jeppe Jakobsen" <jeppe88@gmail.com>
Subject: Re: Q about tk buttons
Date: Wed, 12 Apr 2006 17:41:38 +0900
Message-ID: <99b4ad3b0604120141ha09eaacoa4b3a30bf18f9285@mail.gmail.com>
> Thanks that kind of worked, but how come that the variable still returns
0,
> when I add
>
> puts var.value
>
> to my code, just before Tk.mainloop?

???

---< var-test1.rb >----------------------------------------
require "tk"
var = TkVariable.new(0) #defining variable
var += 1 #making it a fixnum and adding 1

root = TkRoot.new()

label = TkLabel.new(:text=> var).pack()

button = TkButton.new(:text=> "Button", :command=>proc{var += 1}).pack()

puts var.value

Tk.mainloop
-----------------------------------------------------------

$ /usr/local/bin/ruby -v
ruby 1.8.4 (2006-04-06) [i686-linux]
$ /usr/local/bin/ruby var-test1.rb
var-test1.rb:11: undefined method `value' for 1:Fixnum (NoMethodError)

---< var-test2.rb >----------------------------------------
require "tk"
var = TkVariable.new(0)
var.numeric += 1
label = TkLabel.new(:textvariable=>var).pack()
button = TkButton.new(:text=> "Button", :command=>proc{var.numeric +=
1}).pack()
puts var.value
Tk.mainloop
-----------------------------------------------------------

$ /usr/local/bin/ruby -v
ruby 1.8.4 (2006-04-06) [i686-linux]
$ /usr/local/bin/ruby var-test2.rb
1
$

--
Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)

--
"winners never quit, quitters never win"

Message-ID: <99b4ad3b0604120930hf71a5f0r69cb9c84632b02d7@mail.gmail.com>

Oh sorry I meant to say that it returns 1. If I click the button 29 times,
the label shows 30, but the value that was puts'ed is still 1.

Because, callbacks are called in the event loop (Tk.mainloop).
If you need some help and tell me what you want,
I may be able to help you.

···

From: "Jeppe Jakobsen" <jeppe88@gmail.com>
Subject: Re: Q about tk buttons
Date: Thu, 13 Apr 2006 01:31:03 +0900
--
Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)

Thanks. I want to write a Ruby/Tk version of my first program ever (at that
time I wrote in Delphi). It's basically a program that takes a random number
between 0-20 and tells the user to guess it by writing the guess in an entry
and then press the button.

require "tk"
#methods
def guess
    if (guess.value == right_guess.value)
        status.value = "Correct!"
    else
        number_of_guess.numeric += 1
        status.value = "Sorry, no luck"
    end
end
#variables
right_guess = TkVariable.new(rand(21))
number_of_guess = TkVariable.new(0)
guess = TkVariable.new()
status = TkVariable.new("Entry your guess and press the button")
#windows
root = TkRoot.new(:title=>"Number guess")
#labels
lbl_guess = TkLabel.new(:textvariable=>number_of_guess).pack(:side=>"top",
:pady=>10)
lbl_status = TkLabel.new(:textvariable=>status).pack(:side=>"bottom",
:pady=>10)
#entries
entry = TkEntry.new(:textvariable=>guess).pack(:side=>"top", :pady=>10)
#buttons
button = TkButton.new(:text=>"Guess",
:command=>proc{guess}).pack(:side=>"top", :pady=>10)
root = Tk.mainloop

I think the only problem with my code now is that my button won't run my
method guess. But I don't know why right now, because it seems to me that
the methods from the Pigbox example in the pickaxe are run this way. I'm
probably missing something.

···

2006/4/13, Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>:

From: "Jeppe Jakobsen" <jeppe88@gmail.com>
Subject: Re: Q about tk buttons
Date: Thu, 13 Apr 2006 01:31:03 +0900
Message-ID: <99b4ad3b0604120930hf71a5f0r69cb9c84632b02d7@mail.gmail.com>
> Oh sorry I meant to say that it returns 1. If I click the button 29
times,
> the label shows 30, but the value that was puts'ed is still 1.

Because, callbacks are called in the event loop (Tk.mainloop).
If you need some help and tell me what you want,
I may be able to help you.
--
Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)

--
"winners never quit, quitters never win"

Hmmm... There are some problems.

···

From: "Jeppe Jakobsen" <jeppe88@gmail.com>
Subject: Re: Q about tk buttons
Date: Thu, 13 Apr 2006 22:33:18 +0900
Message-ID: <99b4ad3b0604130633t48adb432n4417c3fd27f3b8f4@mail.gmail.com>

require "tk"
#methods
def guess
    if (guess.value == right_guess.value)
        status.value = "Correct!"
    else
        number_of_guess.numeric += 1
        status.value = "Sorry, no luck"
    end
end

Probably, you'll want to refer local variables on main.
But those variables are out of scope in the method.
If arguments bothers you, you can use a Proc object instead of a method.

Next, please see here.

def guess

      ^^^^^

guess = TkVariable.new()

  ^^^^^

There is conflict of names.
So, "proc{guess}" refers the local variable.
If you want to call "guess" method, you must use "proc{guess()}".

root = Tk.mainloop

Probably, the return value is not useful.

If I were you, I may write such like as the following.
----------------------------------------------------
require 'tk'

right_guess = rand(21)
number_of_guess = TkVariable.new(0)

Tk.root.title('Number guess')

TkLabel.new(:textvariable=>number_of_guess).pack(:side=>:top,
:pady=>10)

status = TkLabel.new(:text=>"Entry your guess and press the button",
                     :width=>37).pack(:side=>:bottom, :pady=>10)

entry = TkEntry.new.pack(:side=>:top, :pady=>10)

guess_cmd = proc{
  value = entry.value
  if value.empty? || value.to_i != right_guess
    number_of_guess.numeric += 1
    status.text('Sorry, no luck')
  else
    status.text('Correct!')
  end
}

button = TkButton.new(:text=>'Guess',
:command=>guess_cmd).pack(:side=>:top, :p\ady=>10)

entry.bind('Return', proc{button.invoke})

Tk.mainloop
----------------------------------------------------
--
Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)

Thank you that really cleared things up :slight_smile:

But I don't understand this line though

entry.bind('Return', proc{button.invoke})

It doesn't seem to make any difference whether I include it in the program
or not. I tried to read about it in the documentation, but I only understood
that it had something to do with invoking the command of the button.

···

2006/4/14, Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>:

Hmmm... There are some problems.

From: "Jeppe Jakobsen" <jeppe88@gmail.com>
Subject: Re: Q about tk buttons
Date: Thu, 13 Apr 2006 22:33:18 +0900
Message-ID: <99b4ad3b0604130633t48adb432n4417c3fd27f3b8f4@mail.gmail.com>

> require "tk"
> #methods
> def guess
> if (guess.value == right_guess.value)
> status.value = "Correct!"
> else
> number_of_guess.numeric += 1
> status.value = "Sorry, no luck"
> end
> end

Probably, you'll want to refer local variables on main.
But those variables are out of scope in the method.
If arguments bothers you, you can use a Proc object instead of a method.

Next, please see here.

> def guess
      ^^^^^
> guess = TkVariable.new()
  ^^^^^

There is conflict of names.
So, "proc{guess}" refers the local variable.
If you want to call "guess" method, you must use "proc{guess()}".

> root = Tk.mainloop

Probably, the return value is not useful.

If I were you, I may write such like as the following.
----------------------------------------------------
require 'tk'

right_guess = rand(21)
number_of_guess = TkVariable.new(0)

Tk.root.title('Number guess')

TkLabel.new(:textvariable=>number_of_guess).pack(:side=>:top,
:pady=>10)

status = TkLabel.new(:text=>"Entry your guess and press the button",
                     :width=>37).pack(:side=>:bottom, :pady=>10)

entry = TkEntry.new.pack(:side=>:top, :pady=>10)

guess_cmd = proc{
  value = entry.value
  if value.empty? || value.to_i != right_guess
    number_of_guess.numeric += 1
    status.text('Sorry, no luck')
  else
    status.text('Correct!')
  end
}

button = TkButton.new(:text=>'Guess',
:command=>guess_cmd).pack(:side=>:top, :p\ady=>10)

entry.bind('Return', proc{button.invoke})

Tk.mainloop
----------------------------------------------------
--
Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)

--
"winners never quit, quitters never win"

Message-ID: <99b4ad3b0604140616j345b9266jf8cad5e4b862dad3@mail.gmail.com>

But I don't understand this line though
>entry.bind('Return', proc{button.invoke})

It is an additional binding for 'Return' key press on the entry widget.
When input a number and hit 'Return', you'll get the same result
as clicking the button.

···

From: "Jeppe Jakobsen" <jeppe88@gmail.com>
Subject: Re: Q about tk buttons
Date: Fri, 14 Apr 2006 22:16:49 +0900
--
Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)

Ah ok, thanks.

Gary:

That is because the variable you use is a Ruby variable, but mine is a Tk
variable.

···

2006/4/15, Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>:

From: "Jeppe Jakobsen" <jeppe88@gmail.com>
Subject: Re: Q about tk buttons
Date: Fri, 14 Apr 2006 22:16:49 +0900
Message-ID: <99b4ad3b0604140616j345b9266jf8cad5e4b862dad3@mail.gmail.com>
> But I don't understand this line though
> >entry.bind('Return', proc{button.invoke})

It is an additional binding for 'Return' key press on the entry widget.
When input a number and hit 'Return', you'll get the same result
as clicking the button.
--
Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)

--
"winners never quit, quitters never win"