1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
|
/***************************************************************************
* (C) 2003 Richard Dale All rights reserved. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or (at your option) any later version. *
* *
***************************************************************************/
Here is a Ruby SMOKE adaptor for Qt
Why ruby? From the rubytalk list
On 8/28/03 8:56 PM, "Scott Thompson" wrote:
>> : Can anyone give me a good reason why I would want to use Ruby over
>> Python?
>>
>> Ruby smells better than Python. Also, it has cuter girls.
>>
>> Python sometimes tastes better if you prepare it right.
>
> I hadn't noticed the odor thing. It does have a faintly floral aroma
> doesn't it.
>
> Of course it is no surprise that you can get more and cuter girls with
> Rubies than you can with Pythons.
>
> Scott
So there you have it! :)
Here is 'Hello World' in QtRuby:
#!/usr/bin/ruby -w
require 'Qt'
a = Qt::Application.new(ARGV)
hello = Qt::PushButton.new("Hello World!", nil)
hello.resize(100, 30)
a.setMainWidget(hello)
hello.show()
a.exec()
Ruby 1.8 is unfortunately implicitly required as with 1.6.x it is not possible to:
Make dynamic constants available (thus forcing syntax such as Qt.RichText rather than Qt::RichText)<br>
Call super in the initialize method thus making subclassing of non trivial classes impossible
QtRuby features a very complete coverage of the Qt api:
- You can call all Qt public and protected methods, and all friend methods
such as bitBlt() etc
- Virtual methods
All virtual methods can be overriden, not just event handlers
- Properties
'fooBar = 5' is a synonym for 'setFooBar(5)'
- Predicates
'if foo?' is a synonym for 'if isFoo()' or 'if hasFoo()'
- Use underscore naming for method names instead of camel case if you
prefer. 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()
- Operator overloading
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)
- Declare signals and slots
Signals and slots are declared as list of strings like this:
slots 'setColor(QColor)', 'slotLoad(const QString&)'..
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 )" ) )
And emit signals like this:
emit colorChanged( black )
- Constructors
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" }
- 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() and isDisposed() methods like this:
item2.dispose
if item2.isDisposed
puts "item2 is disposed"
end
- C++ 'int*' and 'int&' argument types
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*' and 'bool&' argument types
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
- Debugging
If a method call can't be matched in the Smoke library giving a 'method_missing'
error, you can 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)
- String 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.
- Qt Designer
A 'rbuic' tool is included in qtruby/rubylib/designer/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
a.setMainWidget(w)
w.show
a.exec
end
Then you can test the example code straight away:
$ ruby mainform.rb
- Loading .ui files at runtime with QWidgetFactory
You can load a Qt Designer .ui file at runtime with the qui extension,
for example:
require 'Qt'
require 'qui'
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
- QtRuby shell
You can use the QtRuby shell in bin/rbqtsh to create widgets
interactively from the command line.
- API reference
Use the bin/rbqtapi tool to discover which methods are available in
the QtRuby api.
- 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 qtruby/rubylib/examples.
- Optional QScintilla text editing widget support
Great for building your own ruby IDE..
Have Fun!
-- Richard
|