Hi I'm trying to follow the tutorial on xrcise at http://wxruby.rubyforge.org/wiki/wiki.pl?UsingXRCise But I keep getting the following error when I try to run the example; tutorial.rb:21:in `initialize': undefined method 'upper_bt' for #<CaseChangeFrame:0x2d610f8> (NoMethodError) from tutorial.rb:28:in `new' from tutorial.rb:28:in `on_init' from c:/ruby/lib/ruby/gems/1.8/gems/wxruby-1.9.2-i386-mswin32/lib/wx/classes/app.rb:16:in `main_loop' from c:/ruby/lib/ruby/gems/1.8/gems/wxruby-1.9.2-i386-mswin32/lib/wx/classes/app.rb:16:in `run' from tutorial.rb:27 The relevant ruby code looks like. # Inherit from the generated base class and set up event handlers class CaseChangeFrame < TextFrameBase def initialize super evt_button(upper_bt) { text_box.upcase! } evt_button(lower_bt) { text_box.downcase! } end end I have triple checked that I have given the button widget an Id name of upper_bt in DialogBlocks Has anyone come across this before? Thanks Tim
on 02.11.2007 08:53
on 02.11.2007 12:19
Hi Tim Tim Field wrote: > `main_loop' > from > c:/ruby/lib/ruby/gems/1.8/gems/wxruby-1.9.2-i386-mswin32/lib/wx/classes/app.rb:16:in > `run' > from tutorial.rb:27 Thanks for the report. Hard to say what's going on here - could you post the my_frame.xrc that you're running XRCise against, and also the my_frame.rb that's been generated? alex
on 02.11.2007 22:03
To my eyes, this looks like a simple syntax slip. The argument to
evt_button is being interpreted as a method call, not a symbol as
intended.
Note the colons:
evt_button(:upper_bt) { text_box.upcase! }
evt_button(:lower_bt) { text_box.downcase! }
- Ash
on 02.11.2007 22:21
Ash Wilson wrote: > To my eyes, this looks like a simple syntax slip. The argument to > evt_button is being interpreted as a method call, not a symbol as > intended. Note the colons: > > evt_button(:upper_bt) { text_box.upcase! } > evt_button(:lower_bt) { text_box.downcase! } The first argument to evt_button, as to the other event handlers that capture commands from Controls, is a Window or a Window id that is the source of the vents So these should be methods which return a Wx::Button alex
on 03.11.2007 01:42
Hi Alex Thanks for taking a look, Here are the files, I also tried the syntax changes mentioned by Ash but this didn't work either, resulted in this error. Must specify Wx::Window event source or its Wx id, not ':upper_bt' (ArgumentError) I'm fairly new to ruby syntax so it wouldn't be beyond me to have such a problem but seems its something else Tim
on 03.11.2007 02:26
Hey Tim and Alex,
Tim Field wrote:
> Tim
Wow, must be one of the first fast ones I've actually debugged here.
I've done my own debugging, and it looks like, your trying to setup the
ID for your objects, and they haven't even been defined yet. And for
you Alex, in order to access "finder" You should proabbly store that as
a Method Call, or store it as a Class Variable, so that it can be
accessed, in this sistuation.
Anyways, the core problem, is first, for the method at which your
generating the code, and adding to it, you need to change the "finder"
variable in my_frame.rb in TestFrameBase#initialize() to a class
variable, so it can be accessed by sub-classed versions of the
TestFrameBase. You can do this easily by just adding an '@' symbol to
it. Nothing to it really.
Next, in your sub-classed version in tutorial.rb, I made a few changes.
Basically, I added the three calls to
@finder.call("id_we_are_looking_for") for upper_bt, lower_bt, and
text_box, then changed the upcase and downcase to the following:
text_box.value = text_box.value.upcase/downcase As you can modify the
string with upcase!/downcase!, but it doesn't modify it in the wxRuby
Buffer, so you need to re-assign it to the buffer, so that it will
convert over properly for you, and display the changes. The New code
goes as follows:
======================my_frame.rb=======================
# This class was automatically generated from XRC source. It is not
# recommended that this file is edited directly; instead, inherit from
# this class and extend its behaviour there.
#
# Source file: tutorial.xrc
# Generated at: Sat Nov 03 13:22:37 +1300 2007
class TextFrameBase < Wx::Frame
def initialize(parent = nil)
super()
xml = Wx::XmlResource.get
xml.flags = 2 # Wx::XRC_NO_SUBCLASSING
xml.init_all_handlers
xml.load("tutorial.xrc")
xml.load_frame_subclass(self, parent, "ID_WXFRAME")
@finder = lambda do | x |
int_id = Wx::xrcid(x)
begin
Wx::Window.find_window_by_id(int_id, self) || int_id
# Temporary hack to work around regression in 1.9.2; remove
# begin/rescue clause in later versions
rescue RuntimeError
int_id
end
end
end
end
=====================tutorial.rb===========================
require 'wx'
# load in the generated code
require 'my_frame'
# Mix-in for a Wx::TextCtrl
module CaseChangeTextCtrl
# convert all the text in the control to upper case
def upcase!
self.value = self.value.upcase
end
# convert all the text in the control to lower case
def downcase!
self.value = self.value.downcase
end
end
# Inherit from the generated base class and set up event handlers
class CaseChangeFrame < TextFrameBase
def initialize
super
upper_bt = @finder.call("upper_bt")
lower_bt = @finder.call("lower_bt")
text_box = @finder.call("text_box")
evt_button(upper_bt) { text_box.value = text_box.value.upcase }
evt_button(lower_bt) { text_box.value = text_box.value.downcase }
end
end
# Run the class
Wx::App.run do
CaseChangeFrame.new.show
end
============================================================
Enjoy the new code, and Alex, you should look into this, incase someone
decides they want to do something similar to this. This would exactly
be the way that I would want to do it.
L8ers,
Mario Steele
on 03.11.2007 09:07
Hi Mario Wow thanks for that sure enough it works! Do you think the tutorial at http://wxruby.rubyforge.org/wiki/wiki.pl?UsingXRCise should be updated, I'm surprised this hasn't been an issue for someone else? Also I was thinking in php (i work with php for a living) there are special get and set methods you can define which are only triggered when your object or inherited object doesn't contain the member or method you're trying to access. (http://nz.php.net/manual/en/language.oop5.overloading.php ) so in this example in php I would write something like. function __get($name){ if($element = $this->finder($name)) return $element; trigger_error("undefined property $name"); } Maybe such a function would be useful in the base class in the tutorial example to look up the form elements thus preventing the need for the "upper_bt = @finder.call("upper_bt")" lines. Anyway I had a good look at the ruby manual I have and couldn't find a way to do this, I'm sure there is? or perhaps you guys can think of a more elegant solution? Thanks again for helping me though that issue guys! Tim
on 03.11.2007 16:47
Hi Tim Tim Field wrote: > > Thanks for taking a look, Here are the files, I also tried the syntax > changes mentioned by Ash but this didn't work either, As Mario says, it's the missing finder calls that are the problem, but these should be in the autogenerated base class, not the user class you're writing. Finder is meant to be a private implementation detail. There is something strange going on because when I run xrcise over the xrc file you sent, it does generate the missing lines in my_frame.rb attr_reader :text_box, :upper_bt, :lower_bt ... @text_box = finder.call("text_box") @text_box.extend(CaseChangeTextCtrl) @upper_bt = finder.call("upper_bt") @lower_bt = finder.call("lower_bt") Please could you double-check you're running xrcise over the latest saved version of your xrc file, as you posted it here. If those lines are still not showing up, could you say what ruby version and platform you're on. thanks alex thanks alex
on 03.11.2007 16:57
Tim Field wrote: > Also I was thinking in php (i work with php for a living) there are > special get and set methods you can define which are only triggered > when your object or inherited object doesn't contain the member or > method you're trying to access. ( > http://nz.php.net/manual/en/language.oop5.overloading.php) Object#method_missing is what you're looking for. class Foo def method_missing(meth, *args) puts "Called non-existing method '#{meth}' with arguments '#{args.join(',')}'" end end It's best used with discretion, because it breaks reflection on an object's supported methods eg, Foo.new.respond_to?(:blah) => false Even if 'blah' would be a valid method call. cheers alex
on 04.11.2007 09:49
Hi Alex, Those lines definitely aren't showing up. (when using that xrc file or another one I have) I'm running ruby 1.8.6 on winxp -Tim
on 05.11.2007 18:59
Tim Tim Field wrote: > Those lines definitely aren't showing up. (when using that xrc file or > another one I have) > > I'm running ruby 1.8.6 on winxp I couldn't reproduce the bug with XP/1.8.4, but I tried installing the latest 1.8.6 and now can. It's due to some incompatible change in REXML shipped with ruby 1.8.4 (version 3.1.3) and 1.8.6 (version 3.1.6), somewhere in it's XPath parsing, but exactly what's needed is eluding me right now. Anyway, thanks again for the report. We should be able to pin down what's up and put out a version of wxSugar inc XRCise that works on 1.8.6 in the next week or so. alex
on 03.05.2008 15:03
Alex Fenton wrote: > I couldn't reproduce the bug with XP/1.8.4, but I tried installing the > latest 1.8.6 and now can. > > It's due to some incompatible change in REXML shipped with ruby 1.8.4 > (version 3.1.3) and 1.8.6 (version 3.1.6), somewhere in it's XPath > parsing, but exactly what's needed is eluding me right now. > > Anyway, thanks again for the report. We should be able to pin down > what's up and put out a version of wxSugar inc XRCise that works on > 1.8.6 in the next week or so. > > alex Hey I get the same thing... running 1.8.6 on Mac OS X 10.5.2. Got a gem of the latest wxSugar 0.1.20 but this still seems to be an issue in this version. Anyone know? Thx!