Let Ruby support TCL/TK under Mac OS x

Source: Internet
Author: User



I remember that when I used ruby1.9.x in OS X10.8, I just had to download and install ActiveTcl8.5, and run TK well without any configuration. But recently want to re-execute the TK code, found in require ' TK ' when the error bird! The ruby2.1.3 version is now in use. Search the Internet, the version after 1.9.x no longer TCL/TK support compiled into Ruby, so if you want to use it must be recompiled ruby! I'll take a walk! Can't you make a gem? But in the case of a variety of peripheral attempts fruitless, there is only one way, is to recompile ruby ...



To the Ruby official website to download the latest ruby2.1.5 source code of about 15MB, after decompression 257mb,console into the Extract directory, enter:





./configure-prefix=/users/apple/src/ruby_src/ruby2.1.5_installed--with-arch=x86_64,i386-- Enable-pthread--enable-shared--WITH-TK--WITH-TCL



Note that the-prefix must have an absolute path, otherwise it will not be allowed; This is the path you want to install ruby2.1.5, and once it is fixed, it cannot be moved again. Because I later used RVM also installed ruby2.1.5 version, so here to change a temporary location, just for testing. You can then enter the make command to compile Ruby, presumably for a while, and finally execute make install to install the ruby2.1.5 in the position I set earlier. Here's a test of how support for TK is:





[Email protected]: Bin$ls



Erb gem IRB rake rdoc ri ruby TESTRB



[Email protected]: bin$./ruby-e "require ' TK '"



You can see that it is OK, and then run my tk.rb to see the effect (code excerpt):

require 'dbm'
#require 'tempfile'
#require 'zip / zip'
#require 'win32api'

#PATH = '/Users/apple/src/c_src/ruby-1.9.3-p362/ext/tk/lib/'

require 'tk'
#require PATH + 'tk'
require 'tkextlib / tkimg / bmp'
require 'tkextlib / tkimg / jpeg'
require 'tkextlib / tkimg / png'
require 'tkextlib / iwidgets'
require 'tkextlib / bwidget'

SM_CXSCREEN = 0
SM_CYSCREEN = 1
def get_screen_size
#get_screen_size_nv = Win32API.new ('user32', 'GetSystemMetrics', ['L'], 'L')
#x = get_screen_size_nv.Call (SM_CXSCREEN)
#y = get_screen_size_nv.Call (SM_CYSCREEN)
`./s`.split.map {| x | x.to_i}
# [x, y]
end

def zip (path)
zip_path = path + '.zip'
File.delete (zip_path) if File.exist? Zip_path
Zip :: ZipFile.open (zip_path, Zip :: ZipFile :: CREATE) {| f | f.add (File.split (path) [1], path)}
end

def unzip (path)
unzip_path = path [0 ..- 5]
Zip :: ZipFile.open (path) {| f | f.extract (f.entries [0], unzip_path) {true}}
end

DB_PATH = File.expand_path (".") + '/Movies.dbm'

#zip (DB_PATH + '.dir')
#zip (DB_PATH + '.pag')

#unzip (DB_PATH + '.dir.zip')
#unzip (DB_PATH + '.pag.zip')

db = DBM.new (DB_PATH)
# db.clear

at_exit {
db.close
#Compress database
#zip (DB_PATH + '.dir')
#zip (DB_PATH + '.pag')
# File.delete (DB_PATH + '.dir'); File.delete (DB_PATH + '.pag')
}

ROOT_W = 1000
ROOT_H = 610

x, y = get_screen_size
#Calculate the coordinates to move to when the screen is centered
mov_x = (x-ROOT_W) / 2
mov_y = (y-ROOT_H) / 2

root = TkRoot.new (: title => "movie query v1.2")
Tk :: Wm.geometry (root, "+ # {mov_x} + # {mov_y}")
#Tk :: Wm.attributes (root,: toolwindow => true)
Tk :: Wm.geometry (root, "# {ROOT_W} x # {ROOT_H}")
Tk :: Wm.minsize (root, ROOT_W, ROOT_H)
Tk :: Wm.maxsize (root, ROOT_W, ROOT_H)

img_love = TkPhotoImage.new (: file => File.expand_path (".") + '/logo.gif')
Tk :: Wm.iconphoto (root, img_love)

def dlgbox_input_name (in_name)
#puts Tk :: Wm.state dlg
#Tk :: Wm.deiconify dlg
The
dlg = Tk :: Toplevel.new (: title => "Enter actor name")
#Tk :: Wm.attributes (dlg,: toolwindow => true)
Tk :: Wm.attributes (dlg,: notify => true)
#Hide window
#Tk :: Wm.withdraw dlg
The
out_name = nil
The
txt_input_name = Tk :: Tile :: Entry.new (dlg,: width => 40) do
grid: row => 0,: column => 0
end
txt_input_name.value = in_name
The
btn_add_name = Tk :: Tile :: Button.new (dlg) do
text "Add"
command do
out_name = txt_input_name.value
dlg.destroy
end
grid: row => 1,: column => 0
end
The
txt_input_name.bind ("Return") do
btn_add_name.invoke
end
The
txt_input_name.focus
The
#Set the toplevel window (dialog window) as the "transient window" of the main window
Tk :: Wm.transient dlg
#Modal dialog
Tk :: BWidget.grab: set, dlg
#Temporarily suspend the main window thread
# TkTimer.new.tkwait dlg
dlg.wait_window
out_name
end

# (r0, c0)
lab_app = Tk :: Tile :: Label.new do
text "Panda's Favorite Movie Query Tool"
font "新 宋体 14 bold"
foreground "blue"
grid: row => 0,: column => 0,: columnspan => 8,: padx => 10,: pady => 10
end

# (r1, c0)
lab_names = Tk :: Tile :: Label.new do
text "Movie Name"
font "新 宋体 12 bold"
grid: row => 1,: column => 0,: padx => 10,: pady => 10
end

# (r1, c1)
txt_names = TkText.new (: width => 35,: height => 2) do
font "新 宋体 12 bold"
grid: row => 1,: column => 1
end

# (r2, c0)
lab_stars = Tk :: Tile :: Label.new do
text "Panda Star"
font "新 宋体 12 bold"
grid: row => 2,: column => 0,: padx => 10,: pady => 40,: sticky =>: n
end

img_file = File.open (File.expand_path (".") + '/star.jpg','r+b')
img_data = img_file.read
#img_star = TkPhotoImage.new (: data => img_data,: gamma => 0.01)
img_star = TkPhotoImage.new (: data => img_data,: palette => 10)
img_star_chk = TkPhotoImage.new (: data => img_data)
img_file.close

star = 0
btn_stars = []
btn_chks = [false, false, false, false, false]

clr_all_chk = proc do
btn_chks = [false] * 5
btn_stars.each do | btn |
btn.configure (: image => img_star)
end
end

# (r2, c1)
frm_stars = TkFrame.new do
grid: row => 2,: column => 1,: padx => 10,: pady => 10,: sticky =>: n
5.times do | i |
btn_stars << TkButton.new (self,: width => 45,: height => 50) do
text i.to_s
image img_star
relief: flat
grid: row => 0,: column => i + 1
command do
idx = self.cget (: text) .to_i
unless btn_chks [idx]
btn_chks [0..idx] = [true] * (idx + 1)
else
if btn_chks [idx + 1]
btn_chks [(idx + 1) ..- 1] = [false] * (5-idx-1)
else
btn_chks [0..idx] = [false] * (idx + 1)
end
end
The
5.times do | j |
img = if btn_chks [j]; img_star_chk else img_star end
btn_stars [j] .configure (: image => img)
end
star = btn_chks.count (true)
end
end
end
end

# (r3, c0)
lab_direct = Tk :: Tile :: Label.new do
text "Director"
font "新 宋体 12 bold"
grid: row => 3,: column => 0
end

# (r3, c1)
txt_direct = Tk :: Tile :: Entry.new (: width => 35) do
font "新 宋体 12 bold"
grid: row => 3,: column => 1
end

# (r4, c0)
lab_nil = Tk :: Tile :: Label.new do
grid: row => 4,: column => 0
end

# (r5, c0)
lab_artist = Tk :: Tile :: Label.new do
text "Actor"
font "新 宋体 12 bold"
grid: row => 5,: column => 0,: padx => 10,: pady => 10,: sticky =>: n
end

lst_artist = lst_xroll = lst_yroll = nil
# (r5, c2)
lst_yroll = Tk :: Tile :: Scrollbar.new do
command proc {| * idx | lst_artist.yview * idx}
grid (: row => 5,: column => 2,: sticky =>: ns)
end


# (r11, c4)
btn_del = Tk :: Tile :: Button.new (frm_btns) do
text "remove
command do
if db.each_key.select {| k | a = k.split ("") [0] .force_encoding ("gbk");
b = txt_names.value.split ("") [0]
a = ~ /#{b}/}.count == 0
Tk.messageBox (: icon =>: error,: type =>: ok,: title => "error",: message => "The main movie name is not in the database!"); break
end
db.delete (txt_names.value)
txt_names.value = ""
end
grid: row => 11,: column => 4,: padx => 10,: sticky =>: n
end

btn_exit = Tk :: Tile :: Button.new (frm_btns) do
text "Exit"
command do
exit
end
grid: row => 11,: column => 5,: padx => 10,: sticky =>: n
end

# TkGrid.grid (btn_add, "-", "x", btn_del,: sticky =>: nsew)

# (r0, c5)
cvs_line = TkCanvas.new (: width => "0.1c") do
create: line, "0.1c", "1c", "0.1c", "30c",: dash => "10",: width => 4,: fill => "blue"
grid: row => 0,: column => 5,: rowspan => 12,: sticky =>: wns
end

yrl_lst_find = nil
# (r1, c6)
lst_find = TkListbox.new (: width => 20,: height => 20) do
font "新 宋体 12 bold"
yscrollcommand proc {| * idx | yrl_lst_find.set * idx}
grid: row => 1,: column => 6,: rowspan => 13,: sticky =>: wn
end

# (r1, c7)
yrl_lst_find = Tk :: Tile :: Scrollbar.new do
command proc {| * idx | lst_find.yview * idx}
grid (: row => 1,: column => 7,: rowspan => 5,: sticky =>: wns)
end

flash_movie_info = proc do | name |
vals = eval (db [name] .force_encoding ("gbk"))
#First click btn [0] in case the last star> 0
#btn_stars [0] .invoke
idx = vals [: star] .to_i
The
#idx-= 1 if idx> 0
clr_all_chk []
btn_stars [idx-1] .invoke if idx> 0
The
txt_names.value = name
The
txt_direct.value = vals [: direct]
list.value = vals [: artist]
The
scl_clarity.value = vals [: scl] .to_i
The
txt_size.value = vals [: size]
txt_len.value = vals [: len]
txt_locate.value = vals [: locate]
txt_mark.value = vals [: mark]
txt_note.value = vals [: note]

pic = TkPhotoImage.new (: data => vals [: pic] .force_encoding ("ASCII-8BIT")) if vals [: pic]
The
lab_pic.configure (: image => pic)
end

flash_vals = proc do | vals |
idx = vals [: star] .to_i
clr_all_chk []
btn_stars [idx-1] .invoke if idx> 0
The
txt_names.value = vals [: name]
The
txt_direct.value = vals [: direct]
list.value = vals [: artist]
The
scl_clarity.value = vals [: scl] .to_i
The
txt_size.value = vals [: size]
txt_len.value = vals [: len]
txt_locate.value = vals [: locate]
txt_mark.value = vals [: mark]
txt_note.value = vals [: note]

pic = TkPhotoImage.new (: data => vals [: pic] .force_encoding ("ASCII-8BIT")) if vals [: pic]
lab_pic.configure (: image => pic)
end

lst_find.bind ("<ListboxSelect>") do
i = lst_find.curselection [0]
if i.to_s! = ""
name = lst_find.get (i)
flash_movie_info [name]
end
end

lst_find.bind ("ButtonRelease-1") do
i = lst_find.curselection [0]
if i.to_s! = ""
name = lst_find.get (i)
flash_movie_info [name]
end
end

# (r10, c6)
txt_find = Tk :: Tile :: Entry.new (: width => 20) do
font "新 宋体 12 bold"
grid: row => 10,: column => 6
end

btn_find = nil
txt_find.bind ("Return") do
btn_find.invoke
end

# (r11, c6)
btn_find = Tk :: Tile :: Button.new do
text "Check"
command do
name_to_find = txt_find.value
next if name_to_find == ""
The
lst_find.clear
if name_to_find == "*"
db.each_key.select do | k |
lst_find.insert (: end, k.force_encoding ("gbk"))
end
next
end
The
db.each_key.select do | k |
names = k.force_encoding ("gbk"). split ("")
for n in names
(lst_find.insert (: end, k.force_encoding ("gbk")); break) if n = ~ / # {name_to_find} /
end
end
end
grid: row => 11,: column => 6
end

menu = TkMenu.new (: parent => root,: tearoff => 0)
root.configure (: menu => menu)

menu_file = TkMenu.new (: parent => root,: tearoff => 0)

cmd_import = proc do
imp_path = Tk.getOpenFile
next if imp_path == ""
The
data = nil
File.open (imp_path, "r +") do | f |
data = f.read
end
vals = eval (data.force_encoding ("gbk"))
flash_vals [vals]
end

menu_file_import = menu_file.add_command (: label => "Import movie",: underline => 1,: command => cmd_import)

cmd_export = proc do
unless chk_vals []
Tk.messageBox (: icon =>: error,: type =>: ok,: title => "error",: message => "Please select a movie!"); Next
end

exp_path = Tk.getSaveFile
next if exp_path == ""
The
m = get_vals []
m [: name] = txt_names.value
File.open (exp_path, "w +") do | f |
f.write m.to_s
end
end

menu_file_export = menu_file.add_command (: label => "Export movie",: underline => 1,: command => cmd_export)
menu_file.add_separator

cmd_exit = proc do
exit
end
menu_file_exit = menu_file.add_command (: label => "Exit",: underline => 2,: command => cmd_exit)

menu.add_cascade (: menu => menu_file,: label => "File",: underline => 1)
#menu_file = menu.add (: cascade,: label => "File",: underline => 0)

Tk.mainloop
The ugly interface is a little ugly, but it can be adjusted later. The key is that this code runs on Windows, Linux, and OS X, and it is easy to cross-platform birds:



Another way is to use rvm to reinstall the version that supports tcl / tk:


rvm reinstall 2.1.5 --enable-shared --enable-pthread --with-tk --with-tcl
But I tried it and got stuck in brew update infinitely, so there was only the beginning article ...

In the end, the cat felt that it was not very easy to use, especially if the irb compiled by itself was not used, because it still called the rvm path. It is also easy to replace, do a soft connection:


[email protected]: rubies $ ls -lh

total 16

lrwxr-xr-x 1 apple staff 35B 12 10 13:03 default-> /Users/apple/.rvm/rubies/ruby-2.1.5

drwxr-xr-x 8 apple staff 272B 7 27 19:47 ruby-2.1.2

lrwxr-xr-x 1 apple staff 45B 12 10 16:08 ruby-2.1.5-> /Users/apple/src/ruby_Src/ruby2.1.5_installed

drwxr-xr-x 8 apple staff 272B 12 10 13:02 tmp_ruby-2.1.5

First rename the original ruby directory, then add the compiled path, you can see that its version number is slightly different:


[email protected]: rubies $ ruby -v

ruby 2.1.5p273 (2014-11-13 revision 48405) [universal.x86_64-darwin14.0]

[email protected]: rubies $. / tmp_ruby-2.1.5 / bin / ruby -v

ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-darwin14.0]

: message => "The main movie name is not in the database!"); break
end
db.delete (txt_names.value)
txt_names.value = ""
end
grid: row => 11,: column => 4,: padx => 10,: sticky =>: n
end

btn_exit = Tk :: Tile :: Button.new (frm_btns) do
text "Exit"
command do
exit
end
grid: row => 11,: column => 5,: padx => 10,: sticky =>: n
end

# TkGrid.grid (btn_add, "-", "x", btn_del,: sticky =>: nsew)

# (r0, c5)
cvs_line = TkCanvas.new (: width => "0.1c") do
create: line, "0.1c", "1c", "0.1c", "30c",: dash => "10",: width => 4,: fill => "blue"
grid: row => 0,: column => 5,: rowspan => 12,: sticky =>: wns
end

yrl_lst_find = nil
# (r1, c6)
lst_find = TkListbox.new (: width => 20,: height => 20) do
font "新 宋体 12 bold"
yscrollcommand proc {| * idx | yrl_lst_find.set * idx}
grid: row => 1,: column => 6,: rowspan => 13,: sticky =>: wn
end

# (r1, c7)
yrl_lst_find = Tk :: Tile :: Scrollbar.new do
command proc {| * idx | lst_find.yview * idx}
grid (: row => 1,: column => 7,: rowspan => 5,: sticky =>: wns)
end

flash_movie_info = proc do | name |
vals = eval (db [name] .force_encoding ("gbk"))
#First click btn [0] in case the last star> 0
#btn_stars [0] .invoke
idx = vals [: star] .to_i
The
#idx-= 1 if idx> 0
clr_all_chk []
btn_stars [idx-1] .invoke if idx> 0
The
txt_names.value = name
The
txt_direct.value = vals [: direct]
list.value = vals [: artist]
The
scl_clarity.value = vals [: scl] .to_i
The
txt_size.value = vals [: size]
txt_len.value = vals [: len]
txt_locate.value = vals [: locate]
txt_mark.value = vals [: mark]
txt_note.value = vals [: note]

pic = TkPhotoImage.new (: data => vals [: pic] .force_encoding ("ASCII-8BIT")) if vals [: pic]
The
lab_pic.configure (: image => pic)
end

flash_vals = proc do | vals |
idx = vals [: star] .to_i
clr_all_chk []
btn_stars [idx-1] .invoke if idx> 0
The
txt_names.value = vals [: name]
The
txt_direct.value = vals [: direct]
list.value = vals [: artist]
The
scl_clarity.value = vals [: scl] .to_i
The
txt_size.value = vals [: size]
txt_len.value = vals [: len]
txt_locate.value = vals [: locate]
txt_mark.value = vals [: mark]
txt_note.value = vals [: note]

pic = TkPhotoImage.new (: data => vals [: pic] .force_encoding ("ASCII-8BIT")) if vals [: pic]
lab_pic.configure (: image => pic)
end

lst_find.bind ("<ListboxSelect>") do
i = lst_find.curselection [0]
if i.to_s! = ""
name = lst_find.get (i)
flash_movie_info [name]
end
end

lst_find.bind ("ButtonRelease-1") do
i = lst_find.curselection [0]
if i.to_s! = ""
name = lst_find.get (i)
flash_movie_info [name]
end
end

# (r10, c6)
txt_find = Tk :: Tile :: Entry.new (: width => 20) do
font "新 宋体 12 bold"
grid: row => 10,: column => 6
end

btn_find = nil
txt_find.bind ("Return") do
btn_find.invoke
end

# (r11, c6)
btn_find = Tk :: Tile :: Button.new do
text "Check"
command do
name_to_find = txt_find.value
next if name_to_find == ""
The
lst_find.clear
if name_to_find == "*"
db.each_key.select do | k |
lst_find.insert (: end, k.force_encoding ("gbk"))
end
next
end
The
db.each_key.select do | k |
names = k.force_encoding ("gbk"). split ("")
for n in names
(lst_find.insert (: end, k.force_encoding ("gbk")); break) if n = ~ / # {name_to_find} /
end
end
end
grid: row => 11,: column => 6
end

menu = TkMenu.new (: parent => root,: tearoff => 0)
root.configure (: menu => menu)

menu_file = TkMenu.new (: parent => root,: tearoff => 0)

cmd_import = proc do
imp_path = Tk.getOpenFile
next if imp_path == ""
The
data = nil
File.open (imp_path, "r +") do | f |
data = f.read
end
vals = eval (data.force_encoding ("gbk"))
flash_vals [vals]
end

menu_file_import = menu_file.add_command (: label => "Import movie",: underline => 1,: command => cmd_import)

cmd_export = proc do
unless chk_vals []
Tk.messageBox (: icon =>: error,: type =>: ok,: title => "error",: message => "Please select a movie!"); Next
end

exp_path = Tk.getSaveFile
next if exp_path == ""
The
m = get_vals []
m [: name] = txt_names.value
File.open (exp_path, "w +") do | f |
f.write m.to_s
end
end

menu_file_export = menu_file.add_command (: label => "Export movie",: underline => 1,: command => cmd_export)
menu_file.add_separator

cmd_exit = proc do
exit
end
menu_file_exit = menu_file.add_command (: label => "Exit",: underline => 2,: command => cmd_exit)

menu.add_cascade (: menu => menu_file,: label => "File",: underline => 1)
#menu_file = menu.add (: cascade,: label => "File",: underline => 0)

Tk.mainloop
The ugly interface is a little ugly, but it can be adjusted later. The key is that this code runs on Windows, Linux, and OS X, and it is easy to cross-platform birds:



Another way is to use rvm to reinstall the version that supports tcl / tk:


rvm reinstall 2.1.5 --enable-shared --enable-pthread --with-tk --with-tcl
But I tried it and got stuck in brew update infinitely, so there was only the beginning article ...

In the end, the cat felt that it was not very easy to use, especially if the irb compiled by itself was not used, because it still called the rvm path. It is also easy to replace, do a soft connection:


[email protected]: rubies $ ls -lh

total 16

lrwxr-xr-x 1 apple staff 35B 12 10 13:03 default-> /Users/apple/.rvm/rubies/ruby-2.1.5

drwxr-xr-x 8 apple staff 272B 7 27 19:47 ruby-2.1.2

lrwxr-xr-x 1 apple staff 45B 12 10 16:08 ruby-2.1.5-> /Users/apple/src/ruby_Src/ruby2.1.5_installed

drwxr-xr-x 8 apple staff 272B 12 10 13:02 tmp_ruby-2.1.5

First rename the original ruby directory, then add the compiled path, you can see that its version number is slightly different:


[email protected]: rubies $ ruby -v

ruby 2.1.5p273 (2014-11-13 revision 48405) [universal.x86_64-darwin14.0]

[email protected]: rubies $. / tmp_ruby-2.1.5 / bin / ruby -v

ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-darwin14.0]

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.