I am trying to use green shoes to create a GUI app to send people messages over LAN using Ruby and the Green Shoes(green_shoes) GUI library, but I am running into the issue of the .style function not working. I've worked with the original Shoes(red shoes) before and it has no issues. Here is the code for creation and style of the GUI:
Shoes.app(title: "Messenger", height: 150, width: 370, resizable: false) {
#creation
alert startMessage
#user_msg = para "Enter User"
#msgbox = para "Enter Message"
#user = edit_line
#msg = edit_line
#submit = button "Send"
#help = button "Send to PC"
#info = button "PC info"
#styles
#msg.style(:right => 5, :top => 57)
#user.style(:right => 5, :top => 25)
#user_msg.style(:left => 10, :top => 25)
#msgbox.style(:left => 10, :top => 57)
#submit.style(:left => 10, :bottom => 10)
#help.style(:left => 150, :bottom => 10)
#info.style(:right => 15, :bottom => 20)
#...
It is not that the styles "aren't working" but rather they are unsupported.
I see reference to right and bottom in shoes Source but not in green_shoes seems that positioning in green_shoes is from top and left always.
Green Shoes style:right
Note: Green Shoes doesn't support :right style.
Green Shoes style:bottom
Note: Green Shoes doesn't support :bottom style.
This is why Shoes3 works and green shoes doesn't.
You will have to alter all your locations to be :top and :left which isn't that uncommon in layout designers.
Can't Wait for Shoes4 to be a full release (even if it does require jruby)
Shoes4 does support bottom and right Source
Related
I am using ruby 2.6.3, installed by compiling the source.
When using Gtk::FontChooserDialog.new, the default font size given is 10.
Is it possible to call Gtk::FontChooserDialog.new with a different size, such
as 24, so that I can avoid having to change the size each time I select a font.
Here is how I am doing things:
dialog = Gtk::FontChooserDialog.new(:title => "Select font",
:parent => self,
:action => Gtk::FileChooserAction::OPEN,
:buttons => [[Gtk::Stock::OPEN, Gtk::ResponseType::ACCEPT], [Gtk::Stock::CANCEL, Gtk::ResponseType::CANCEL]])
I have tried (in the argument list) :size => 24, :default_size => 24, etc. This does not work. I'm just guessing here. I have searched a lot, with no luck. I also looked in the gem sample dirs at test-gtk-font-chooser-dialog.rb and other files but no luck.
I am using Linux Mint Mate 19.1, installed a couple of weeks ago.
You need to set the size through a Pango.FontDescription. A short example in Python would be:
font_chooser = Gtk.FontChooserDialog.new(title = "Select font", parent = self)
font_description = Pango.FontDescription.new()
font_description.set_size(24 * Pango.SCALE)
font_chooser.set_font_desc(font_description)
EDIT
And here is a complete example in Ruby:
#!/usr/bin/ruby
'''
ZetCode Ruby GTK tutorial
This program runs a font dialog with a default (settable) font size.
Author: Jan Bodnar
Website: www.zetcode.com
Last modified: May 2014
'''
require 'gtk3'
require 'pango'
class RubyApp < Gtk::Window
def initialize
super
init_ui
end
def init_ui
set_title "Center"
signal_connect "destroy" do
Gtk.main_quit
end
button = Gtk::Button.new
button.set_label "Font"
button.signal_connect "clicked" do
dialog = Gtk::FontChooserDialog.new(:title => "Select font", :parent => self, :action => Gtk::FileChooserAction::OPEN, :buttons => [[Gtk::Stock::OPEN, Gtk::ResponseType::ACCEPT], [Gtk::Stock::CANCEL, Gtk::ResponseType::CANCEL]])
font_description = Pango::FontDescription.new
font_description.set_size 24 * Pango::SCALE
dialog.set_font_desc font_description
dialog.run
end
add button
set_default_size 300, 200
set_window_position Gtk::WindowPosition::CENTER
show_all
end
end
window = RubyApp.new
Gtk.main
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
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.
If this is Shoes 4 then it is very likely that the thread doesn't have access to the UI (only the main thread has access to the UI). You could try extracting the value beforehand and then passing it to write as an argument:
def write(port)
#...
end
port = #which_port.text.to_i
#th1 = Thread.new { write(port) }
I've been trying to set a background image to the stack but I can't get it to work, am I doing something wrong? Here's my code
Shoes.app(:width => 550,
:height => 450) do
#Main container so I don't have to deal with scroll
stack(:width => 550,
:height => 450,
:scroll => false) do
background(image("img/intro_bg.jpg"))
end
end
I'm trying to avoid the scroll bar to appear since the re-size property doesn't work at all :/
Assuming img/intro_bg.jpg exists, please change
background(image("img/intro_bg.jpg"))
to
background('img/intro_bg.jpg')
I'm trying to make a small program to mung some data into usable form. One thing I'd like it to do is to be able to select some files and perform actions on them, so I thought i'd use the listbox object in Tk to do that. I want to be able to open a file and see its filename displayed in the listbox. As far as I've read this is precisely what using listvariable in the listbox is for. Yet when I run my code the listbox is never updated (although items already in the listvariable variable are displayed fine).
So here's a close to MWE for this. What am I doing wrong, and what fundamental idea have I misunderstood?
require 'tk'
require 'tkextlib/tile'
$path_list = []
$populate_list = TkVariable.new( $path_list )
def get_file
file = Tk.getOpenFile
file = open(file) unless file.empty?
path = File.basename(file, ".out")
if $path_list.include?(path)
Tk.messageBox(
'type' => "ok",
'icon' => "warning",
'title' => " - Minimum Working Example - ",
'message' => "This file has already been added! Nothing was added to the list"
)
else
$path_list.push(path)
end
end
root = TkRoot.new {title "- Minimum Working Example -"}
frame = Tk::Tile::Frame.new(root) {padding "3 3 12 12"}.grid( :sticky => 'nsew') # 'north south east west'
TkGrid.columnconfigure root, 0, :weight => 1; TkGrid.rowconfigure root, 0, :weight => 1
$file_listbox = Tk::Listbox.new(frame) {
listvariable $populate_list}.grid( :column => 1, :row => 0, :rowspan => 6)
Tk::Tile::Button.new(frame) {
width 15; text 'Open file...'; command {get_file}}.grid( :column => 0, :row => 1)
Tk.mainloop
Do I maybe have to write it in some other order?
Just add one line of code:
$populate_list.value = $path_list
under this one:
$path_list.push(path)
It works for me, although looks weird.
TkVariable create a proxy for you ruby variable, thus bridge your ruby var references with Tk widgets. But i don't know why changes in proxy var don't affect the var it points to. I'm not sure whether it should do that automatically.
Can I center the contents of a flow in Shoes?
I know that a paragraph can be centred like:
para 'Centred paragrpah', :align=>'center'
However, this does not work with flows:
flow(:align=>'center') do
…
end
No errors are brought up, but the contents remain left justified.
Not completely sure. What is it in your flow you are trying to centre? You can try a margin left trick as per HTML and CSS.
This gives a flow with left, centre and right justified text that remains centred in the window as it is resized:
Shoes.app do
flow do
style(:margin_left => '50%', :left => '-25%')
border blue
para "Some left justified text\n", :align => 'left'
para "Some centred text\n", :align => 'center'
para "some right justified text\n", :align => 'right'
end
end