Search code examples
rubymultithreadingshoes

Ruby Shoes GUI set port don't work with thread


If I don't use a thread, I can normally use @which_port.text.to_i in port declaration. If I use a thread, it looks like this statement @which_port.text.to_i don't work. I can only write port manually, e.g. 6000 and then my program works good. I have to use thread because my program freezes otherwise. Is any way able to use @which_port.text.to_i despite the use thread?

require 'socket'
require 'thread'

Shoes.app do

def write
    @t = TCPSocket.new("xx.xx.xx.xx", @which_port.text.to_i)
    loop do
        msg = @t.recv(4096)
        @pa1.text = @pa1.text + msg
    end
end 

@btn = button("button", width: 80, height: 50) do
    window(left: 300, top: 300) do
    @pa1 = para ""
    @th1 = Thread.new { write }
   end
end

@e_ln = edit_line(width: 320, height: 25, margin_top: 5)

@which_port = list_box :items => ["5000", "6000", "7000"],
    :width => 120,
    :choose => "5000" do |list| 
    end
end
end

Solution

  • Every time you launch a window you are launching a totally new app so variables in that new app are unknown to the other app, and those in the first app, the one that fired the window method are unknown to the new app ! Fortunately there is a owner method available in every Shoes app, in your case owner called inside the new app gives you a reference to the first app, the one that owns the new app ! One way to do what you want (Threading or not):

    Shoes.app title: "Main Shoes app" do
        def write(paragr)
            msg = "#{self.inspect} === #{@which_port.text}"
            paragr.text = paragr.text + msg
        end
    
        @btn = button("button", width: 80, height: 50) do
            window(left: 300, top: 300, title: "Another Shoes app") do
                @pa1 = para ""
                Thread.new { owner.write(@pa1) }
            end
        end
    
    
        @which_port = list_box :items => ["5000", "6000", "7000"],
                               :width => 120,
                               :choose => "5000" do |list|
        end
    end
    

    You can also investigate the Shoes.APPS method which gives you back an array containing all opened app.