Set_window can't run

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?

Hi Pen! Is it OK to call you Pen? I’m not sure if that
is your name :wink:

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

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 8080,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?

Hi Peng! I’m impressed with your progress :slight_smile:
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

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 T. [email protected]

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?

Le mardi 08 juin 2010 à 15:06 +0200, Pen T. 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.

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!

:slight_smile:

   MikeC

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