Forum: Ruby Q about tk buttons

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Jeppe J. (Guest)
on 2006-04-12 01:43
(Received via mailing list)
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.
Hidetoshi NAGAI (Guest)
on 2006-04-12 06:29
(Received via mailing list)
From: "Jeppe J." <removed_email_address@domain.invalid>
Subject: Q about tk buttons
Date: Wed, 12 Apr 2006 06:41:39 +0900
Message-ID:
<removed_email_address@domain.invalid>
> 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()
Jeppe J. (Guest)
on 2006-04-12 12:43
(Received via mailing list)
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 <removed_email_address@domain.invalid>:
Hidetoshi NAGAI (Guest)
on 2006-04-12 16:50
(Received via mailing list)
From: "Jeppe J." <removed_email_address@domain.invalid>
Subject: Re: Q about tk buttons
Date: Wed, 12 Apr 2006 17:41:38 +0900
Message-ID: <removed_email_address@domain.invalid>
> 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
$
Jeppe J. (Guest)
on 2006-04-12 20:32
(Received via mailing list)
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 <removed_email_address@domain.invalid>:
Hidetoshi NAGAI (Guest)
on 2006-04-13 06:59
(Received via mailing list)
From: "Jeppe J." <removed_email_address@domain.invalid>
Subject: Re: Q about tk buttons
Date: Thu, 13 Apr 2006 01:31:03 +0900
Message-ID: <removed_email_address@domain.invalid>
> 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.
Jeppe J. (Guest)
on 2006-04-13 17:34
(Received via mailing list)
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 <removed_email_address@domain.invalid>:
Hidetoshi NAGAI (Guest)
on 2006-04-14 06:53
(Received via mailing list)
Hmmm... There are some problems.

From: "Jeppe J." <removed_email_address@domain.invalid>
Subject: Re: Q about tk buttons
Date: Thu, 13 Apr 2006 22:33:18 +0900
Message-ID:
<removed_email_address@domain.invalid>

> 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
Jeppe J. (Guest)
on 2006-04-14 17:17
(Received via mailing list)
Thank you that really cleared things up :)

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 <removed_email_address@domain.invalid>:
Gary W. (Guest)
on 2006-04-15 02:21
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
Gary W. (Guest)
on 2006-04-15 02:23
I apologize, the original message I wrote wrapped some of the code
Hidetoshi NAGAI (Guest)
on 2006-04-15 08:39
(Received via mailing list)
From: "Jeppe J." <removed_email_address@domain.invalid>
Subject: Re: Q about tk buttons
Date: Fri, 14 Apr 2006 22:16:49 +0900
Message-ID:
<removed_email_address@domain.invalid>
> 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.
Jeppe J. (Guest)
on 2006-04-16 00:24
(Received via mailing list)
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 <removed_email_address@domain.invalid>:
This topic is locked and can not be replied to.