Archive:Development/Languages/Ruby (zh TW): Difference between revisions

From KDE TechBase
(Created page with '{{Template:I18n/Language Navigation Bar|Development/Languages/Ruby}} Image:ruby.png 非常完整的綁定包括 KDE API 和 Qt API。The Korundum package includes both a QtR...')
 
No edit summary
Line 2: Line 2:
[[Image:ruby.png]]
[[Image:ruby.png]]


非常完整的綁定包括 KDE API 和 Qt API。The Korundum package includes both a QtRuby Qt-only binding along with the full combined Qt/KDE one. The QtRuby package contains just Qt bindings with no dependencies on KDE.
非常完整的綁定包括 KDE API 和 Qt API。Korundum 套件包括 QtRuby,以及完整結合 Qt/KDE。QtRuby 套件僅包含 Qt 綁定並不相依 KDE。


[http://rubyforge.org/projects/korundum/ Korundum/QtRuby - Ruby-KDE/Qt bindings]
[http://rubyforge.org/projects/korundum/ Korundum/QtRuby - Ruby-KDE/Qt 綁定]


The book [http://www.pragmaticprogrammer.com/titles/ctrubyqt/ Rapid GUI Development with QtRuby] (for Qt version 3.x) is available.
The book [http://www.pragmaticprogrammer.com/titles/ctrubyqt/ Rapid GUI Development with QtRuby] (for Qt version 3.x) is available.


Being [http://developer.kde.org/language-bindings/smoke/index.html Smoke-based] bindings means that they offer full access to most KDE 4.x and Qt 4.x classes.
作為[[Development/Languages/Smoke|基於 Smoke]] 的綁定,意味著他們提供完整使用大多數 KDE 4.x Qt 4.x 的類別。


= QtRuby =
= QtRuby =
Line 68: Line 68:
       createStandardStatusBarAction()
       createStandardStatusBarAction()


==Operator overloading==
==運算子重載==


The full range of Qt operator methods is available, for example:
The full range of Qt operator methods is available, for example:
Line 76: Line 76:
       p1 + p2                  => (25, 25)
       p1 + p2                  => (25, 25)


==Declare signals and slots==
==宣告訊號(Signals)和槽(Slots)==


Signals and slots are declared as list of strings like this:
Signals and slots are declared as list of strings like this:
Line 103: Line 103:
       emit colorChanged( black )
       emit colorChanged( black )


==Constructors==
==建構子==


You can call constructors in the conventional style:
You can call constructors in the conventional style:
Line 125: Line 125:
       w = MyWidget.new { |theWidget| theWidget.setCaption "foobar" }
       w = MyWidget.new { |theWidget| theWidget.setCaption "foobar" }


==Garbage Collection==
==垃圾回收==


When a ruby instance is garbage collected, the underlying C++ instance will only be deleted if it isn't 'owned' by a parent object. Normally this will 'just work', but there are occasions when you need to delete the C++ ahead of garbage collection, and whether or not it has a parent. Use the dispose(), isDisposed() and disposed? methods like this:
When a ruby instance is garbage collected, the underlying C++ instance will only be deleted if it isn't 'owned' by a parent object. Normally this will 'just work', but there are occasions when you need to delete the C++ ahead of garbage collection, and whether or not it has a parent. Use the dispose(), isDisposed() and disposed? methods like this:
Line 134: Line 134:
       end
       end


==C++ 'int*' and 'int&' argument types==
==C++ 'int*' 'int&' 參數型態==


Ruby passes numeric values by value, and so they can't be changed when passed to a method. The Qt::Integer class provides a mutable numeric type which does get updated when passed as an argument. For example, this C++ method 'findByFileContent()':
Ruby passes numeric values by value, and so they can't be changed when passed to a method. The Qt::Integer class provides a mutable numeric type which does get updated when passed as an argument. For example, this C++ method 'findByFileContent()':
Line 147: Line 147:
It supports the arithmetic operators, and so expressions such as 'acc + 3' will work.
It supports the arithmetic operators, and so expressions such as 'acc + 3' will work.


==C++ 'bool*' and 'bool&' argument types==
==C++ 'bool*' 'bool&' 參數型態==


There is a similar problem for bool arg types, and the mutable Qt::Boolean class can be used like this:
There is a similar problem for bool arg types, and the mutable Qt::Boolean class can be used like this:
Line 166: Line 166:
Use 'nil?' to test the value returned in the Boolean
Use 'nil?' to test the value returned in the Boolean


==C++ (const )(unsigned )char* argument types==
==C++ (const )(unsigned )char* 參數型態==


In some cases Qt/KDE object "takes ownership" over Ruby String passed as char* argument type. Programmer needs to make sure that Ruby String is not being garbage collected or changed for the time it's being used by Qt/KDE object. It is also quite possible that Qt/KDE object will change and eventually free it(memory used internally by Ruby String to store its data). Be very careful when you call this kind of methods and make sure that there is no overloaded version witch accepts QString or QByteArray first!
In some cases Qt/KDE object "takes ownership" over Ruby String passed as char* argument type. Programmer needs to make sure that Ruby String is not being garbage collected or changed for the time it's being used by Qt/KDE object. It is also quite possible that Qt/KDE object will change and eventually free it(memory used internally by Ruby String to store its data). Be very careful when you call this kind of methods and make sure that there is no overloaded version witch accepts QString or QByteArray first!


==C++ unsigned char* functions==
==C++ unsigned char* 函式==


Very few functions (as QImage::bits()) return a uchar* to directly manipulate data. These functions are not supported in Ruby and will throw an ArgumentError. More information on the [http://lists.kde.org/?l=kde-bindings&m=122899325331866&w=2 mail list].
Very few functions (as QImage::bits()) return a uchar* to directly manipulate data. These functions are not supported in Ruby and will throw an ArgumentError. More information on the [http://lists.kde.org/?l=kde-bindings&m=122899325331866&w=2 mail list].


==Debugging==
==除錯==


If a method call can't be matched in the Smoke library giving a 'method_missing' error, first check that you are passing correct class instance that is properly initialized (with super method called in constructors of custom Qt classes descendants). You can also turn on debugging to trace the matching process:
If a method call can't be matched in the Smoke library giving a 'method_missing' error, first check that you are passing correct class instance that is properly initialized (with super method called in constructors of custom Qt classes descendants). You can also turn on debugging to trace the matching process:
Line 203: Line 203:
       Qt::Internal::setDebug(Qt::QtDebugChannel::QTDB_GC)
       Qt::Internal::setDebug(Qt::QtDebugChannel::QTDB_GC)


==String i18n==
==字串 i18n==


QtRuby supports $KCODE values of 'u', 'e' and 's' or the corresponding '-K' options from the command line. Qt Designer .ui files have UTF-8 strings so if you use any 8 bit UTF-8 characters, you will need to set $KCODE='u' or use the -Ku command line option.
QtRuby supports $KCODE values of 'u', 'e' and 's' or the corresponding '-K' options from the command line. Qt Designer .ui files have UTF-8 strings so if you use any 8 bit UTF-8 characters, you will need to set $KCODE='u' or use the -Ku command line option.
Line 295: Line 295:
       end
       end


==API reference==
==API 參考==


Use the bin/rbqtapi tool to discover which methods are available in the QtRuby api. This command:
Use the bin/rbqtapi tool to discover which methods are available in the QtRuby api. This command:
Line 307: Line 307:
Lists all methods whose names contain the string 'setCaption'
Lists all methods whose names contain the string 'setCaption'


==Example programs==
==範例程式==


The best way to start programming QtRuby is to look at some existing code and start messing with it.. The are various samples under qtrubyexamples and korundum/examples.
The best way to start programming QtRuby is to look at some existing code and start messing with it.. The are various samples under qtrubyexamples and korundum/examples.


=KDE Specific Infomation=
=KDE 的特定資訊=


Instead of <code>require 'Qt4'</code>, use <code>require 'korundum4'</code> for KDE programs.
KDE 程式不是用 <code>require 'Qt4'</code>,而是用 <code>require 'korundum4'</code>  


The KDE K* classes such as KApplication are renamed as KDE::Application. The other KDE classes are in the KParts::, KIO:: or DOM:: namespaces, with the same names as their C++ counterparts.
The KDE K* classes such as KApplication are renamed as KDE::Application. The other KDE classes are in the KParts::, KIO:: or DOM:: namespaces, with the same names as their C++ counterparts.
Line 323: Line 323:
Will list all the methods in the KDE::Action class. There are currently (as at KDE 3.3 beta 2) 977 classes/30841 methods in the Smoke library runtime, so the coverage of the Qt/KDE api is pretty complete.
Will list all the methods in the KDE::Action class. There are currently (as at KDE 3.3 beta 2) 977 classes/30841 methods in the Smoke library runtime, so the coverage of the Qt/KDE api is pretty complete.


=Build dependencies=
=建構依賴=


* ruby 1.8 or greater (svn trunk works with 1.9.1)
* ruby 1.8 或更高版本 (svn trunk works with 1.9.1)
* cmake 2.6 or greater
* cmake 2.6 或更高版本
* Qt 4.0 or greater
* Qt 4.0 或更高版本
* KDE 4.1 or greater (for korundum)
* KDE 4.1 或更高版本(korundum 需要)


=Tutorials=
=教學=


There is a ruby translation of [http://developer.kde.org/language-bindings/ruby/tutorial/tutorial.html Qt Tutorial #1], and the corresponding ruby code is in qtruby/rubylib/tutorial/t1 to t14.
There is a ruby translation of [http://developer.kde.org/language-bindings/ruby/tutorial/tutorial.html Qt Tutorial #1], and the corresponding ruby code is in qtruby/rubylib/tutorial/t1 to t14.


And a Qt4 version of the same tutorial translated to Ruby by Darshan Ishaya [http://www.darshancomputing.com/qt4-qtruby-tutorial/ Qt4 Tutorial #1]  
相同的教學的Qt4版本,由 Darshan Ishaya 翻譯為 Ruby,[http://www.darshancomputing.com/qt4-qtruby-tutorial/ Qt4 教學 #1]


[http://developer.kde.org/language-bindings/ruby/tutorial2/tutorial2.html Qt Tutorial #2], a Charting Application with ruby code in qtruby/rubylib/examples/qt-examples/chart.
[http://developer.kde.org/language-bindings/ruby/tutorial2/tutorial2.html Qt Tutorial #2], a Charting Application with ruby code in qtruby/rubylib/examples/qt-examples/chart.
Line 346: Line 346:
The book [http://www.pragmaticprogrammer.com/titles/ctrubyqt/ Rapid GUI Development with QtRuby] is now available.
The book [http://www.pragmaticprogrammer.com/titles/ctrubyqt/ Rapid GUI Development with QtRuby] is now available.


=Download=
=下載=
You can obtain recent SVN snapshots on the Rubyforge [http://rubyforge.org/projects/korundum/ QtRuby/Korundum site].
您可以從 RubyForge 的[http://rubyforge.org/projects/korundum/ QtRuby/Korundum 網站]取得最新的 SVN 快照。


=More help=
=更多協助=
There are two IRC channels (<tt><nowiki>#qtruby</nowiki></tt> and <tt><nowiki>#kde-ruby</nowiki></tt>) in [http://www.freenode.net FreeNode]. If you prefer e-mail, you can use the [http://mail.kde.org/mailman/listinfo/kde-bindings kde-bindings mailing-list] (low traffic) or ask in the [http://www.ruby-lang.org/en/20020104.html ruby-talk] mailing list (you may use the [http://www.ruby-forum.com/ Ruby Forum] gateway to post in ruby-talk from web).


=More information=
在[http://www.freenode.net FreeNode]有兩個 IRC 頻道(<tt><nowiki>#qtruby</nowiki></tt> and <tt><nowiki>#kde-ruby</nowiki></tt>)。如果你偏好電子郵件,您可以使用  [http://mail.kde.org/mailman/listinfo/kde-bindings kde-bindings 郵件列表](低流量),或者在 [http://www.ruby-lang.org/en/20020104.html ruby-talk] 郵件列表提問(您可以使用 [http://www.ruby-forum.com/ Ruby 論壇] gateway,從網頁發表文章到 ruby-talk)。
A series of articles on ruby QT (inspired by the work done for the [http://dradis.nomejortu.com dradis] project):
 
=更多資訊=
 
ruby Qt 的系列文章(靈感來自[http://dradis.nomejortu.com dradis]專案的工作):
* [http://weblog.nomejortu.com/x-windows/ruby-workshop-the-way-of-the-qt-samurai ruby workshop: the way of the Qt samurai]
* [http://weblog.nomejortu.com/x-windows/ruby-workshop-the-way-of-the-qt-samurai ruby workshop: the way of the Qt samurai]
* [http://weblog.nomejortu.com/x-windows/ruby-qt-model-view-controller ruby Qt: model / view / controller]
* [http://weblog.nomejortu.com/x-windows/ruby-qt-model-view-controller ruby Qt: model / view / controller]
* [http://weblog.nomejortu.com/x-windows/ruby-qt-menu-bar-status-bar-and-resources ruby Qt: menu bar, status bar and resources]
* [http://weblog.nomejortu.com/x-windows/ruby-qt-menu-bar-status-bar-and-resources ruby Qt:選單列、狀態列和資源]
* [http://weblog.nomejortu.com/x-windows/ruby-qt-custom-widget-example ruby Qt custom widget example]
* [http://weblog.nomejortu.com/x-windows/ruby-qt-custom-widget-example ruby Qt 自定 widget 範例]
* [http://weblog.nomejortu.com/x-windows/ruby-qttreewidget-example ruby Qt::TreeWidget example]
* [http://weblog.nomejortu.com/x-windows/ruby-qttreewidget-example ruby Qt::TreeWidget 範例]
* [http://www.ruby-forum.com/topic/189346#new Very usefull link how to create your first Qt window dialog]
* [http://www.ruby-forum.com/topic/189346#new Very usefull link how to create your first Qt window dialog]


[[Category:Ruby]]
[[Category:Ruby]]

Revision as of 10:05, 1 December 2009


Development/Languages/Ruby

非常完整的綁定包括 KDE API 和 Qt API。Korundum 套件包括 QtRuby,以及完整結合 Qt/KDE。QtRuby 套件僅包含 Qt 綁定並不相依 KDE。

Korundum/QtRuby - Ruby-KDE/Qt 綁定

The book Rapid GUI Development with QtRuby (for Qt version 3.x) is available.

作為基於 Smoke 的綁定,意味著他們提供完整使用大多數 KDE 4.x 和 Qt 4.x 的類別。

QtRuby

Hello world 範例:

  1. !/usr/bin/ruby -w

require 'Qt4' a = Qt::Application.new(ARGV) hello = Qt::PushButton.new("Hello World!") hello.resize(100, 30) hello.show a.exec

更'Rubyish'方式的 Hello Qt 範例:

require 'Qt4'

Qt::Application.new(ARGV) do

   Qt::Widget.new do
       self.window_title = 'Hello QtRuby v1.0'
       resize(200, 100)
   
       button = Qt::PushButton.new('Quit') do
           connect(SIGNAL :clicked) { Qt::Application.instance.quit }
       end
       label = Qt::Label.new('Hello Qt in the Ruby way!')
       
       self.layout = Qt::VBoxLayout.new do
           add_widget(label, 0, Qt::AlignCenter)
           add_widget(button, 0, Qt::AlignRight)
       end
       
       show
   end
   
   exec

end

目前 API 範圍概覽

可用呼叫

You can call all Qt public and protected methods, and all friend methods such as bitBlt() etc

虛擬方法

All virtual methods can be overridden, not just event handlers

屬性

'foobar = 5' is a synonym for 'setFooBar(5)'

Use either CamelCase or lowercase with underscore naming

Any underscores in method names are removed, and the following character is capitalised. For example, you can use either of these two forms to call the same method:

      create_standard_status_bar_action()
      createStandardStatusBarAction()

運算子重載

The full range of Qt operator methods is available, for example:

      p1 = Qt::Point.new(5,5)   => (5, 5)
      p2 = Qt::Point.new(20,20) => (20, 20)
      p1 + p2                   => (25, 25)

宣告訊號(Signals)和槽(Slots)

Signals and slots are declared as list of strings like this:

      slots 'setColor(QColor)', 'slotLoad(const QString&)'..
      signals 'clicked()'..

For slots and signals without arguments you can use Ruby symbols:

      slots :slotLoad
      signals :clicked
       

Currently C++ type signatures must be used, a future version of QtRuby will allow ruby type signatures instead.

Connect slots and signals like this:

      Qt::Object.connect( @colormenu, SIGNAL( "activated(int)" ),
                        self, SLOT( "slotColorMenu(int)" ) )

Or you can connect signal to a block:

      quit_button.connect(SIGNAL :clicked) { $qApp.quit }

And emit signals like this:

      emit colorChanged( black )

建構子

You can call constructors in the conventional style:

      quit = Qt::PushButton.new("Quit", self, "quit")

Or you can pass a block if you prefer:

      w = MyWidget.new { setCaption("foobar") }

The block will be called in the context of the newly created instance.

Ordinary arguments can be provided as well as a block at the end:

      w = MyWidget.new(nil) { setCaption("foobar") }

They are run in the context of the new instance.

And there's more! You can also pass an arg to the block, and it will be run in the context of the arg:

      w = MyWidget.new { |theWidget| theWidget.setCaption "foobar" }

垃圾回收

When a ruby instance is garbage collected, the underlying C++ instance will only be deleted if it isn't 'owned' by a parent object. Normally this will 'just work', but there are occasions when you need to delete the C++ ahead of garbage collection, and whether or not it has a parent. Use the dispose(), isDisposed() and disposed? methods like this:

      item2.dispose
      if item2.disposed?
      	puts "item2 is disposed"
      end

C++ 'int*' 和 'int&' 參數型態

Ruby passes numeric values by value, and so they can't be changed when passed to a method. The Qt::Integer class provides a mutable numeric type which does get updated when passed as an argument. For example, this C++ method 'findByFileContent()':

      # static Ptr findByFileContent( const QString &fileName, 
      #                               int *accuracy=0 );

      acc = Qt::Integer.new(0)
      fc = KDE::MimeType.findByFileContent("mimetype.rb", acc)

It supports the arithmetic operators, and so expressions such as 'acc + 3' will work.

C++ 'bool*' 和 'bool&' 參數型態

There is a similar problem for bool arg types, and the mutable Qt::Boolean class can be used like this:

      # QFont getFont(bool * ok, const QFont&initial, 
      #               QWidget* parent = 0, const char *name = 0);		
		
      ok = Qt::Boolean.new
      font = Qt::FontDialog.getFont(ok, 
                          Qt::Font.new("Helvetica [Cronyx]", 10), 
                          self)
      if !ok.nil? 
      	# font is set to the font the user selected
      else 
      	# the user canceled the dialog
      end

Use 'nil?' to test the value returned in the Boolean

C++ (const )(unsigned )char* 參數型態

In some cases Qt/KDE object "takes ownership" over Ruby String passed as char* argument type. Programmer needs to make sure that Ruby String is not being garbage collected or changed for the time it's being used by Qt/KDE object. It is also quite possible that Qt/KDE object will change and eventually free it(memory used internally by Ruby String to store its data). Be very careful when you call this kind of methods and make sure that there is no overloaded version witch accepts QString or QByteArray first!

C++ unsigned char* 函式

Very few functions (as QImage::bits()) return a uchar* to directly manipulate data. These functions are not supported in Ruby and will throw an ArgumentError. More information on the mail list.

除錯

If a method call can't be matched in the Smoke library giving a 'method_missing' error, first check that you are passing correct class instance that is properly initialized (with super method called in constructors of custom Qt classes descendants). You can also turn on debugging to trace the matching process:

      a = Qt::Application.new(ARGV)
      Qt.debug_level = Qt::DebugLevel::High
      a.loadLibrary("foo")  # Non existent method

Will give the following output:

      classname    == QApplication
      :: method == loadLibrary$
      -> methodIds == []
      candidate list:
      Possible prototypes:
          static QWidget* QApplication::widgetAt(int, int, bool)
			...

Here, the list of candidate methods 'methodIds' is empty

Another debugging mechanism allows various trace 'channels' to be switched on.

You can trace virtual method callbacks:

      Qt::Internal::setDebug(Qt::QtDebugChannel::QTDB_VIRTUAL)

Or trace QtRuby garbage collection:

      Qt::Internal::setDebug(Qt::QtDebugChannel::QTDB_GC)

字串 i18n

QtRuby supports $KCODE values of 'u', 'e' and 's' or the corresponding '-K' options from the command line. Qt Designer .ui files have UTF-8 strings so if you use any 8 bit UTF-8 characters, you will need to set $KCODE='u' or use the -Ku command line option.

Other capabilities and offerings

Qt Designer

A 'rbuic4' tool is included in qtruby/tools/rbuic to compile .ui files into ruby code. As described above, Qt Designer uses UTF-8. In addition to the options in the original uic C++ utility an '-x' flag has been added. This will generate a top level stub in the code:

      $ rbuic mainform.ui -x -o mainform.rb

Will add this to the end of the generated code:

      if $0 == __FILE__
          a = Qt::Application.new(ARGV)
          w = MainForm.new
          w.show
          a.exec
      end

Then you can test the example code straight away:

      $ ruby mainform.rb

Use the '-kde' option to require the 'korundum4' extension rather than the 'Qt4' one. If the '-x' option is used in conjunction, it generates a KDE top level. For example:

      $ rbuic4 -x -kde knotifywidgetbase.ui -o knotifywidgetbase.rb

Will generate this top level code:

      if $0 == __FILE__
      	about = KDE::AboutData.new("knotifywidgetbase", 
		                           "KNotifyWidgetBase", "0.1")
      	KDE::CmdLineArgs.init(ARGV, about)
        a = KDE::Application.new()
    	w = KNotifyWidgetBase.new
    	w.show
    	a.exec
      end

Loading .ui files at runtime with Qt::UILoader

Warning
This section needs improvements: Please help us to

cleanup confusing sections and fix sections which contain a todo


Remove example that does not work

You can load a Qt Designer .ui file at runtime with the 'quiloader' extension, for example:

      require 'Qt4'
      require 'quiloader'

      a = Qt::Application.new(ARGV)
      if ARGV.length == 0
        exit
      end

      if ARGV.length == 2
        QUI::WidgetFactory.loadImages ARGV[0]
        w = QUI::WidgetFactory.create ARGV[1]
        if w.nil?
          exit
        end
        w.show()
        a.connect(a, SIGNAL('lastWindowClosed()'), a, SLOT('quit()'))
        a.exec()
      end

With new version API changed a little.

      require 'Qt4'
      require 'qtuitools'

      a = Qt::Application.new(ARGV)
      if ARGV.length == 0
        exit
      end

      if ARGV.length == 1
        file = Qt::File.new(ARGV[1])
        file.open(Qt::File::ReadOnly)

        loader = Qt::UiLoader.new
        window = loader.load(file, nil)
        file.close
        if (window.nil?)
          print "Error. Window is nil.\n"
          exit
        end
        window.show
        a.connect(a, SIGNAL('lastWindowClosed()'), a, SLOT('quit()'))
        a.exec
      end

API 參考

Use the bin/rbqtapi tool to discover which methods are available in the QtRuby api. This command:

	  $ rbqtapi Qt::TextEdit

Will list all the methods in the Qt::TextEdit class

	  $ rbqtapi -rsetCaption 

Lists all methods whose names contain the string 'setCaption'

範例程式

The best way to start programming QtRuby is to look at some existing code and start messing with it.. The are various samples under qtrubyexamples and korundum/examples.

KDE 的特定資訊

KDE 程式不是用 require 'Qt4',而是用 require 'korundum4'

The KDE K* classes such as KApplication are renamed as KDE::Application. The other KDE classes are in the KParts::, KIO:: or DOM:: namespaces, with the same names as their C++ counterparts.

Use the 'rbkdeapi' script to introspect the Korundum api from the command line. For example:

      $ rbkdeapi KDE::Action

Will list all the methods in the KDE::Action class. There are currently (as at KDE 3.3 beta 2) 977 classes/30841 methods in the Smoke library runtime, so the coverage of the Qt/KDE api is pretty complete.

建構依賴

  • ruby 1.8 或更高版本 (svn trunk works with 1.9.1)
  • cmake 2.6 或更高版本
  • Qt 4.0 或更高版本
  • KDE 4.1 或更高版本(korundum 需要)

教學

There is a ruby translation of Qt Tutorial #1, and the corresponding ruby code is in qtruby/rubylib/tutorial/t1 to t14.

相同的教學的Qt4版本,由 Darshan Ishaya 翻譯為 Ruby,Qt4 教學 #1

Qt Tutorial #2, a Charting Application with ruby code in qtruby/rubylib/examples/qt-examples/chart.

The Qt Designer Color Tool Tutorial, with ruby code in qtruby/rubylib/designer/examples/colortool.

Paul Lutus has written a tutorial on how to get started with Ruby GUI programming with Qt

For KDE, there is a ruby translation of this KDE 3.0 tutorial originally written for C++ by Antonio Larrosa Jiménez. The sources are in korundum/rubylib/tutorials/p1 to p9.

The book Rapid GUI Development with QtRuby is now available.

下載

您可以從 RubyForge 的QtRuby/Korundum 網站取得最新的 SVN 快照。

更多協助

FreeNode有兩個 IRC 頻道(#qtruby and #kde-ruby)。如果你偏好電子郵件,您可以使用 kde-bindings 郵件列表(低流量),或者在 ruby-talk 郵件列表提問(您可以使用 Ruby 論壇 gateway,從網頁發表文章到 ruby-talk)。

更多資訊

ruby Qt 的系列文章(靈感來自dradis專案的工作):