Storing Information in Stack/Flow Objects - ruby

Say I have the following sort of app:
Shoes.app do
#i = 0
def add_button
button ("#{#i += 1}")
end
button("0") {add_button}
end
So that each time you click the button it adds a new button with a higher number. Is there any way to code it so that clicking one of the new buttons displays its number? Since self always points to the app, the obvious approach
button ("#{#i += 1}") {alert #i}
Doesn't work, since then clicking any button just displays the current value of #i.

Shoes.app do
#i = 0
def add_button
n = #i+1
button ("#{#i += 1}") {alert n}
end
button("0") {add_button}
end

Related

Strange behaviour with ScrolledWindow

I have written the program below. It displays an image within a hbox inside a scrolledwindow. The image moves forward when space key is pressed, backwards when backspace is pressed. Whenever an image is changed, I set the scrolledwindow adjustments value to 0.0 so that it will always display from the start. But this is not working correctly, for example when I use the mouse wheel to scroll the image up or down, press space or backspace, it will sometimes show the next/previous image from the top or stay at that position. I want it to always show the next/prev image from the top. Have I messed up somewhere? I'm using ruby-gtk 4.0.8.
require 'gtk3'
class Window < Gtk::ApplicationWindow
def initialize(app)
super(app)
set_default_size(800, 600)
path = File.expand_path('~/Manga/Deadman Wonderland')
#images = Dir.children(path).map { |file| "#{path}/#{file}" }
#sc_win = Gtk::ScrolledWindow.new
#box = Gtk::Box.new(:horizontal)
#box.halign = :center
#box.valign = :center
#image = Gtk::Image.new
#image_index = -1
signal_connect('key-press-event') do |_widg, event|
case event.keyval
when Gdk::Keyval::KEY_space
reset_viewport
next_image
when Gdk::Keyval::KEY_BackSpace
reset_viewport
prev_image
end
end
next_image
#box.add(#image)
#sc_win.add(#box)
add(#sc_win)
end
def next_image
if #image_index < #images.length - 1
#image.pixbuf.unref if #image.pixbuf
#image_index += 1
#image.set_pixbuf(GdkPixbuf::Pixbuf.new(:file => #images[#image_index]))
end
end
def prev_image
if #image_index > 0
#image.pixbuf.unref if #image.pixbuf
#image_index -= 1
#image.set_pixbuf(GdkPixbuf::Pixbuf.new(:file => #images[#image_index]))
end
end
def reset_viewport
#sc_win.hadjustment.set_value(0.0)
#sc_win.vadjustment.set_value(0.0)
end
end
app = Gtk::Application.new(nil, :flags_none)
app.signal_connect('activate') { Window.new(app).show_all }
app.run
I tried printing out the value of vertical adjustment whenever it changed. I noticed that at some point after calling reset_viewport, its value reset from 0.0 to the previous one.
#sc_win.vadjustment.signal_connect('value-changed') do
p #sc_win.vadjustment.value
end
494.0 #at bottom of image
0.0 #after pressing space key
494.0 #jumps back!

Dropdown Menu and its action

I have a dropdown menu with around 5-6 items in it.
require 'Qt'
class Auth < Qt::Widget
entryIndex = $entryIndex
slots 'slotFunctionChanged(int)'
def initialize(parent=nil)
super(parent)
setWindowTitle("Action");
setFixedSize 750,530
entry_ui
show
end
def entry_ui
#entryLabel = Qt::Label.new "Entry: ", self
#entryLabel.setFont Qt::Font.new("Times New Roman", 14)
combo = Qt::ComboBox.new self
combo.setFont Qt::Font.new("Times New Roman", 12 )
combo.addItem "1- Standard"
combo.addItem "2- Custom"
combo.addItem "3- Non-custom"
combo.addItem "4- Non-Standard"
connect combo, SIGNAL('activated(int)'), self, SLOT('slotEntryChanged(int)')
combo.resize 170,20
combo.move 170,100
#funLabel.move 95,100
end
def slotEntryChanged(entryIndex)
case entryIndex
when 0
#acc.show
when 1
#acc.hide
when 2
#acc.show
end
end
Now there is a button called Submit , which is connected to slot 'on_clicked_submit()'.
I want a dialog box to pop up only when entryIndex item to be either custom or non- custom. I tried the following code:
def on_clicked_submit
if $entryIndex == 1 || $entryIndex == 8
text = Qt::InputDialog.getText self, "Swipe", "Thank you"
end
end
But the if statement to check entryIndex was not working fine. Suggestions are welcome

Refreshing a view in Gtk3-Ruby

I'm having a problem changing a view in my feed reader. When a button in the feed list is clicked, the feed window is supposed to update. Instead, the feed window stays empty. How do you remove and replace a widget in gtk3-ruby?
The problem method:
def feed=(feed)
#feed.destroy()
#title, #count = feed.channel.title, feed.items.size
#label.set_markup "<b>#{#title} (#{#count} articles)</b>"
#feed = FeedItems.new(feed.items, #parent)
self.pack_end(#feed)
#feed.show()
end
The full source is on pastebin:
http://pastebin.com/KPKAfCmx
I should have used show_all and the widget updates.
def feed=(feed)
self.remove(#feed)
#title, #count = feed.channel.title, feed.items.size
#label.set_markup "<b>#{#title} (#{#count} articles)</b>"
#feed = FeedItems.new(feed.items, #parent)
self.pack_end(#feed)
self.show_all
end

Ruby Shoes: using .click on an image cannot tell left from right click

I was trying to make an image that raises a number by one when left clicked and lowers it when right clicked.
I was able to make shoes detect which button is clicked with the below code:
Shoes.app do
#info = para "No button pressed."
click do |button|
#info.replace "#{button} was PRESSED."
end
end
And this works just fine. LMB is 1, RMB is 2, and MMB is 3.
But when I try and detect a clicked image
Shoes.app do
number = 0
#image = image "image.png"
#info = para "No button pressed."
#image.click do |button|
#info.replace "#{button} was PRESSED."
end
end
It seems to only be passing self. The result, regardless of button, is "(Shoes::Image) was pressed." I cannot find any way to get around this problem.
What happens if you try this?
Shoes.app do
number = 0
#image = image "image.png"
#info = para "No button pressed."
#image.click do |button|
#info.replace "#{button.inspect} was PRESSED."
end
end
I think the click method of an element is designed to pass self as the block.
As far as I can see, the only way around it is to use the main click event and use the mouse position blocks to determine whether the mouse is over the image at the time of the click.
Shoes.app do
number = 0
#info = para "No button pressed."
#image = image "image.png"
click {|button, x, y|
if (x > #image.left) && (x < (#image.left + #image.width)) && (y > #image.top) && (y < (#image.top + #image.height))
#info.replace "#{button} was PRESSED."
end
}
end

Getting 'Gtk:ERROR' trying to run WxRuby

I'm using Ubuntu 10.04 and I'm trying to run a WxRuby example which I copy-pasted from this site WxRubyWiki. I've been looking for help over the net but I couldn't find anything similar...
I'm getting this error...
Gtk:ERROR:/build/buildd/gtk+2.0-2.20.1/gtk/gtkwindow.c:6789:IA__gtk_window_present_with_time: assertion failed: (widget->window != NULL)
Aborted
These are the versions I'm using...
ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [i486-linux]
gem list
...
wxruby (2.0.1 x86-linux)
...
And this is the code I'm trying to run...
require 'rubygems' if RUBY_VERSION < '1.9'
require 'wx'
class EventFrame < Wx::Frame
def initialize()
super(nil, -1, "Event Frame")
#idleCounter = 0
evt_close {|event| on_close(event)}
evt_idle {|event| on_idle(event)}
evt_size {|event| on_size(event)}
evt_key_down {|event| on_key(event)}
evt_left_down {|event| on_left_down(event)}
# You can still process these events, you just need to define a separate callback for middle_down and right_down
# to process them as separate events
evt_middle_down {|event| on_middle_down(event)}
evt_right_down {|event| on_right_down(event)}
button = Wx::Button.new(self, -1, "Push me")
evt_button(button.get_id()) {|event| on_button(event)}
show()
end
def message(text, title)
m = Wx::MessageDialog.new(self, text, title, Wx::OK | Wx::ICON_INFORMATION)
m.show_modal()
end
def on_close(event)
message("This frame will be closed after you push ok", "Close event")
#close(true) - Don't call this - it will call on_close again, and your application will be caught in an infinite loop
# Either call event.skip() to allow the Frame to close, or call destroy(), as follows
destroy()
end
def on_idle(event)
#idleCounter += 1
if #idleCounter > 15 # Without the counter to slow this down, Idle events would be firing every second
message("The system is idle right now", "Idle event")
#idleCounter = 0
end
event.request_more() # You must include this, otherwise the Idle event won't occur again
end
def on_size(event)
size = event.get_size()
x = size.x
y = size.y
message("X = " + x.to_s + ", Y = " + y.to_s, "Size event")
end
def on_key(event)
message("Key pressed", "Key Event")
end
def on_left_down(event)
button = ""
if event.left_down()
button = "Left"
end
message(button + " button was clicked", "Mouse event")
end
def on_middle_down(event)
# This method hasn't been implemented yet...
#if event.middle_down()
#button = "Middle"
#end
message("Middle button was clicked", "Mouse event")
end
def on_right_down(event)
# This method hasn't been implemented yet...
#if event.right_down()
#button = "Right"
#end
message("Right button was clicked", "Mouse event")
end
def on_button(event)
message("Button was clicked", "Button event")
end
end
class MyApp < Wx::App
def on_init
EventFrame.new()
end
end
MyApp.new.main_loop
Thanks in advance!
It is more of an understanding of how GTK+2/wx/wxRuby works. As is, the code above does not work on your configuration in a Virtual Box machine I set to test this nor my development machine's Ubuntu 11.10 x86_64 with 1000Hz kernel compile option and ruby 1.9.3 p21.
The GTK+2 error occurs when the on_size event fires during frame creation. The creation is not yet complete so the message box does not have a parent at that time. You can test this by commenting out (in def on_size(event):
message("X = " + x.to_s + ", Y = " + y.to_s, "Size event")
and trying:
puts "Size event: X = #{x}, Y = #{y}"
to see the event details on standard out. You will notice there are two events fired during creation; an initial size event and a resize event
Another caveat is the idle loop which locks Unity o my system. You can test that the idle event is happening without a lock up by changing the code as below:
in def initialize add this before show():
create_status_bar(2)
self.status_text = "Welcome to wxRuby!"
then in idle_event:
def on_idle(event)
#idleCounter += 1
#if #idleCounter > 15 # Without the counter to slow this down, Idle events would be firing every second
# message("The system is idle right now", "Idle event")
# #idleCounter = 0
#end
set_status_text #idleCounter.to_s, 1
event.request_more() # You must include this, otherwise the Idle event won't occur again
end
A last caveat about the code is you may notice you don't see the key or mouse down events creating their message box. That is because the button control fills the client area and traps the frame events for keys and buttons. If you resize the frame while the app is running the button will not resize with it by default (GTK+2 platform). If you then click inside the frame client area but not on the button you will see mouse events.
Good Luck !
this fixed and works in ubuntu 11.10 :)

Resources