Forum: Ruby-Gnome 2 set_window can't run

Posted by Pen Ttt (luofeiyu)
on 2010-06-04 05:23
there is a program  which i get in  the web,it can run.

require 'gtk2'
class RubyApp < Gtk::Window
def initialize
super
set_title "Center"
signal_connect "destroy" do
Gtk.main_quit
end
set_default_size 250, 200
set_window_position Gtk::Window::POS_CENTER
show
end
end
Gtk.init
window = RubyApp.new
Gtk.main

i want to learn from it :
set_default_size 250, 200
set_window_position Gtk::Window::POS_CENTER
i write my program  such as following:

#!/usr/bin/ruby
require 'gtk2'
button = Gtk::Button.new("Hello World")
button.signal_connect("clicked") {
  puts "Hello World"
}
window = Gtk::Window.new
set_default_size 250, 200
set_window_position Gtk::Window::POS_CENTER
window.signal_connect("delete_event") {
  puts "delete event occurred"
  #true
  false
}
window.signal_connect("destroy") {
  puts "destroy event occurred"
  Gtk.main_quit
}
window.add(button)
window.show_all
Gtk.main

the outout is :   undefined method `set_default_size' for main:Object
(NoMethodError)
would you mind telling  me  why  the  program can't run?
Posted by Mike Charlton (Guest)
on 2010-06-04 13:05
(Received via mailing list)
Hi Pen! Is it OK to call you Pen?  I'm not sure if that
is your name ;-)

Anyway, in the original program they are making a class
called RubyApp.  In the class, the initialize method
runs set_default_size.  When you run a method like this
it runs it on the current object.
Since it is the initialize method, that means ruby
will run it on the new RubyApp object
when it is created.  Running like that is the same
as saying:

self.set_default_size

"self" is the object that is created (a RubyApp)
RubyApp is a Gtk::Window and Gtk::Window has the
method in it, so everything works OK.

In your program, you are calling set_default_size
from the main script.  Ruby is looking for a method
in the Object class to run, but it can't find it.  The
method you want to run exists on objects that are
Gtk::Windows.  Luckily you have one!    It is called
window and you made it when you wrote

window = Gtk::Window.new()

You must run the set_default_size from that object.
You can do it like this:

window.set_default_size 250,200

Maybe this will make it easier to understand.
You want to set the default size to 250,200.
But *what* should be set?  Maybe you have
3 different window.  Which one do you want to
set the size?  You tell Ruby which object you
are talking about by writing

object_name.method_name

Object oriented programming is a bit difficult to
understand at first, but eventually it will be easy for
you.  Don't give up!!!  Some basic Ruby tutorials
might help you understand some things better.

Hope that helps :^)

          MikeC
Posted by Pen Ttt (luofeiyu)
on 2010-06-06 14:24
dear:MikeC
as  you  guess ,my name is peng, i have bought a book on ruby  to  learn 
object,class,variable and so  on.
i want to draw two buttons in window,one is bigger 80*80,the other is 
smaller 40*40,here is my program

require 'gtk2'
window = Gtk::Window.new
window.title = "Hello Buttons"
window.  set_default_size 400, 400
window.signal_connect('delete_event') do
  Gtk.main_quit
  false
end
box1 = Gtk::HBox.new(false, 0)
window.add(box1)
button1 = Gtk::Button.new("Button 1")
button1.set_size_request 80, 80
box1.pack_start(button1, false, false, 1)
button2 = Gtk::Button.new("Button 2")
button2.set_size_request 40, 40
box1.pack_start(button2, false, false, 1)
window.show_all
Gtk.main

the output :
button1 (80) is  as  high  as  button2 (40)        # not  wanted
button1 (80)is  more  wider  than  button2 (40)  # wanted

how to revise to get what i want?
Posted by Mike Charlton (Guest)
on 2010-06-06 17:05
(Received via mailing list)
Hi Peng!  I'm impressed with your progress :-)
You will be able to do a lot very soon.

You ask a good question.  The layout for
GTK takes some time to understand.  Once
you understand it, though, it's pretty easy
to use.

The most important thing to understand is that
the layout is designed so that the window can
be resized and still look good.  Usually people
think, "I want a button that is 80 pixels wide,
40 pixels high and located at 100,200".  But
if you resize the window that button may
be too big or small.  Or it might not be in the
window any more.

You *can* lay out widgets like that in GTK,
but it isn't the usual way.  Usually you say
that you want 3 buttons in a row and you
put them in an HBox.  The HBox will lay
the buttons out in a row.  But what the buttons
look like depends on the parameters that
you send to pack_start (or pack_end).  There
are 3 of them.


You can see in your program that you
said:

box1.pack_start(button1, false, false, 1)

The false, false, 1 part is the one that controls
the shape of the button in the container
(HBox).

Before I explain what they mean, I'll talk a bit about
how the layout works.  When you put a widget in
a container (in this case you are putting a button
widget in an HBox container), the container reserves
space for the widget.  At first it reserves the amount
of space that you request.  But if the window is
bigger than you need, there will be space left over.

This extra space can be used to put between
the widgets.  If you want to use some of that extra
space between your widgets, you can do it by
setting the first of the values to true.

With box1, try it and see what happens.  Change
the line that packs box1 to

box1.pack_start(button1, true, false,1)

The extra space is turned into blank space between
the widgets.  You can also tell it to grow the
widget to use up the extra space.  You do this by
changing the second one to true:

box1.pack_start(button1, true, true,1)

Now the button will grow to use up the extra room.

Finally, you might want to have a minimum amount
of blank space between your widgets.  That's what the
last number is for.  It's the number of black pixels
between the widgets.  In this case it is one.  But
if you change it to 10, then the buttons will always
have at least 10 pixels of space between them.

Maybe you noticed that everything we did only
changed the width of the buttons.  Nothing changed
the height of the buttons.  That's because this is
an HBox.  All of the widgets in an HBox are the
same height.

In a VBox, the widgets are packed vertically (one on
top of the other).  All of the widgets are the same width.
To do what you want, you must wrap each of your
buttons in a VBox and then pack the VBoxes in the
HBox.  Here is an example:

require 'gtk2'
window = Gtk::Window.new
window.title = "Hello Buttons"
window.  set_default_size 400, 400
window.signal_connect('delete_event') do
 Gtk.main_quit
 false
end
box1 = Gtk::HBox.new(false, 0)
window.add(box1)
button1 = Gtk::Button.new("Button 1")
button1.set_size_request 80, 80
boxb1 = Gtk::VBox.new(false, 0)
boxb1.pack_start(button1, false, false, 1)
box1.pack_start(boxb1, false, false, 0)
button2 = Gtk::Button.new("Button 2")
button2.set_size_request 40, 40
boxb2 = Gtk::VBox.new(false, 0)
boxb2.pack_start(button2, false, false, 1)
box1.pack_start(boxb2, false, false, 0)
window.show_all
Gtk.main

What is happening?  When we put the
button in the VBox, we use

pack_start(false, false, 0)

This means that we don't want to use
the extra space.  The button won't grow
up or down even if there is more space.
The VBox will grow up and down, but the
button will remain the same size and in
the same position (with no space around it).

We do the same with the second button
and the two are put into the HBox.  We now
have the desired result!

I'm sorry this is a very long explanation.  I guess
English isn't your first language (even though your
posts are almost perfect!)  If you need a better
explanation, please ask.

Anyway, it might seem like a lot of work to lay
things out like this.  But actually, if you give up
the idea of controlling exactly how big each
item is and exactly where it is on the screen, then
it becomes much easier.  Also, your program will
work better since it will automatically resize properly.

I hope that helps!

              MikeC
Posted by Pen Ttt (luofeiyu)
on 2010-06-08 15:06
i'm confused by object programming.
p1 can run:
#p1
require 'gtk2'
window = Gtk::Window.new("mywindow")
window.signal_connect("destroy") {
  puts "destroy event occurred"
  Gtk.main_quit
}
window.show_all
Gtk.main

when i close mywindow , i can see  "destroy event occurred" in 
shell,everything is ok.

p2 can run:
#p2
require 'gtk2'
Gtk::Window.new("mywindow").signal_connect("destroy") {
  puts "destroy event occurred"
  Gtk.main_quit
}
Gtk::Window.new("mywindow").show_all
Gtk.main

when i close mywindow , i can't see " destroy event occurred" in shell

what's the reason?
Posted by Alex Shearn (Guest)
on 2010-06-08 15:12
(Received via mailing list)
I believe it because you're creating the window twice: on the second
call to Gtk::Window.new, you don't bind anything to the destroy event.

I think that's what's happening...

Shearn89

On 8 Jun 2010, at 14:06, Pen Ttt <ruby-forum-incoming@andreas-s.net>
Posted by Pascal Terjan (Guest)
on 2010-06-08 16:46
(Received via mailing list)
Le mardi 08 juin 2010 à 15:06 +0200, Pen Ttt a écrit :
> Gtk.main
> }
> Gtk::Window.new("mywindow").show_all
> Gtk.main
> 
> when i close mywindow , i can't see " destroy event occurred" in shell
> 
> what's the reason?

You create 2 different windows
You connect the signal of one and you show the other

Gtk::Window.new creates a new window. You need to keep a way of
accessing it later, not to create new ones.
Posted by Pen Ttt (luofeiyu)
on 2010-06-09 06:59
i rewrite my program,it can run , there two windows ,one is 
mywindow1,the other is mywindow2,when i close any one (mywindow1 or 
mywindow2), the other window close too (mywindow2 or mywindow1),
now , can i close one of them , the other window will still open? when i 
close two of them , the  program is over.
how to revise my program to achieve my goals?

require 'gtk2'
window1 = Gtk::Window.new("mywindow1")
window1.signal_connect("destroy") {
  puts "destroy event1 occurred"
  Gtk.main_quit
}
window1.show_all
window2 = Gtk::Window.new("mywindow2")
window2.signal_connect("destroy") {
  puts "destroy event2 occurred"
  Gtk.main_quit
}
window2.show_all
Gtk.main
Posted by Mike Charlton (Guest)
on 2010-06-09 12:17
(Received via mailing list)
Here is a simple fix for your problem:

require 'gtk2'

num_windows = 2
window1 = Gtk::Window.new("mywindow1")
window1.signal_connect("destroy") {
 puts "destroy event1 occurred"
 window1.hide_all
 num_windows = num_windows - 1
 if num_windows < 1
   Gtk.main_quit
 end
}
window1.show_all
window2 = Gtk::Window.new("mywindow2")
window2.signal_connect("destroy") {
 puts "destroy event2 occurred"
 window2.hide_all
 num_windows = num_windows - 1
 if num_windows < 1
   Gtk.main_quit
 end
}
window2.show_all
Gtk.main

Gtk.main runs a loop to process the events in the UI.  When
you call Gtk.main_quit it exits the loop, and closes all the
windows.  Then it starts running the code after the Gtk.main.
Since you don't have any, the program ends.

I mad a variable that keeps track of the number of windows.
In stead of quitting the main loop, I hide the window when it
is closed.  I decrease the number of windows by one.  When
I get to 0 I exit the main loop.

My code is not the best.  But it is simple. Keep working on it!

:-)

       MikeC
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.