swing_paradise 0.1.46

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of swing_paradise might be problematic. Click here for more details.

Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +1557 -0
  3. data/doc/README.gen +1510 -0
  4. data/lib/swing_paradise/autoinclude.rb +3 -0
  5. data/lib/swing_paradise/awt/README.md +1 -0
  6. data/lib/swing_paradise/awt/color.rb +45 -0
  7. data/lib/swing_paradise/base_module/base_module.rb +993 -0
  8. data/lib/swing_paradise/classes +1 -0
  9. data/lib/swing_paradise/examples/001_quit_button_example.rb +55 -0
  10. data/lib/swing_paradise/examples/002_text_area_example.rb +55 -0
  11. data/lib/swing_paradise/examples/003_combo_box_example.rb +57 -0
  12. data/lib/swing_paradise/examples/004_jpanel_left_bound_example.rb +41 -0
  13. data/lib/swing_paradise/examples/005_box_layout_example.rb +39 -0
  14. data/lib/swing_paradise/examples/006_frame_example.rb +33 -0
  15. data/lib/swing_paradise/examples/007_textarea_responding_to_enter_key_example.rb +28 -0
  16. data/lib/swing_paradise/examples/008_scrolled_window_example.rb +41 -0
  17. data/lib/swing_paradise/examples/009_font_size_example.rb +39 -0
  18. data/lib/swing_paradise/examples/010_counter_example.rb +183 -0
  19. data/lib/swing_paradise/examples/011_button_with_image_example.rb +58 -0
  20. data/lib/swing_paradise/examples/012_quit_on_escape_key_being_pressed.rb +37 -0
  21. data/lib/swing_paradise/examples/013_simple_box_example.rb +38 -0
  22. data/lib/swing_paradise/examples/014_mouse_events_example.rb +41 -0
  23. data/lib/swing_paradise/examples/015_menu_example.rb +77 -0
  24. data/lib/swing_paradise/examples/016_file_chooser_example.rb +96 -0
  25. data/lib/swing_paradise/examples/017_buttons_example.rb +56 -0
  26. data/lib/swing_paradise/examples/018_colour_chooser_example.rb +51 -0
  27. data/lib/swing_paradise/examples/019_jeditorpane_example.rb +61 -0
  28. data/lib/swing_paradise/examples/020_table_example.rb +77 -0
  29. data/lib/swing_paradise/examples/021_jsplitpane_example.rb +66 -0
  30. data/lib/swing_paradise/examples/022_drawing_oval_example.rb +51 -0
  31. data/lib/swing_paradise/examples/023_show_message_dialog_example.rb +57 -0
  32. data/lib/swing_paradise/java_classes/border_factory/border_factory.rb +19 -0
  33. data/lib/swing_paradise/java_classes/box/box.rb +72 -0
  34. data/lib/swing_paradise/java_classes/button +1 -0
  35. data/lib/swing_paradise/java_classes/checkbox +1 -0
  36. data/lib/swing_paradise/java_classes/combobox +1 -0
  37. data/lib/swing_paradise/java_classes/default_table_model/default_table_model.rb +18 -0
  38. data/lib/swing_paradise/java_classes/frame +1 -0
  39. data/lib/swing_paradise/java_classes/jbutton/jbutton.rb +199 -0
  40. data/lib/swing_paradise/java_classes/jcheckbox/jcheckbox.rb +28 -0
  41. data/lib/swing_paradise/java_classes/jcombobox/jcombobox.rb +31 -0
  42. data/lib/swing_paradise/java_classes/jcomponent/jcomponent.rb +253 -0
  43. data/lib/swing_paradise/java_classes/jeditorpane/jeditorpane.rb +23 -0
  44. data/lib/swing_paradise/java_classes/jfilechooser/jfilechooser.rb +22 -0
  45. data/lib/swing_paradise/java_classes/jframe/jframe.rb +319 -0
  46. data/lib/swing_paradise/java_classes/jlabel/jlabel.rb +171 -0
  47. data/lib/swing_paradise/java_classes/jmenu/jmenu.rb +13 -0
  48. data/lib/swing_paradise/java_classes/jmenubar/jmenubar.rb +13 -0
  49. data/lib/swing_paradise/java_classes/jpanel/jpanel.rb +115 -0
  50. data/lib/swing_paradise/java_classes/jscrollpane/jscrollpane.rb +84 -0
  51. data/lib/swing_paradise/java_classes/jspinner/jspinner.rb +17 -0
  52. data/lib/swing_paradise/java_classes/jtextarea/jtextarea.rb +120 -0
  53. data/lib/swing_paradise/java_classes/jtextfield/jtextfield.rb +314 -0
  54. data/lib/swing_paradise/java_classes/label +1 -0
  55. data/lib/swing_paradise/java_classes/panel +1 -0
  56. data/lib/swing_paradise/java_classes/spinner +1 -0
  57. data/lib/swing_paradise/java_classes/textarea +1 -0
  58. data/lib/swing_paradise/misc/misc.rb +57 -0
  59. data/lib/swing_paradise/prototype/prototype.rb +79 -0
  60. data/lib/swing_paradise/requires/require_the_project.rb +15 -0
  61. data/lib/swing_paradise/toplevel_methods/misc.rb +293 -0
  62. data/lib/swing_paradise/version/version.rb +17 -0
  63. data/lib/swing_paradise/widget_collection/README.md +2 -0
  64. data/lib/swing_paradise/widget_collection/text_viewer.rb +160 -0
  65. data/lib/swing_paradise.rb +1 -0
  66. data/swing_paradise.gemspec +42 -0
  67. metadata +120 -0
data/doc/README.gen ADDED
@@ -0,0 +1,1510 @@
1
+ DEFAULT_HEADER
2
+
3
+ ## Introduction to the swing_paradise project and its different goals
4
+
5
+ In the last some months of the year 2023/2024 I thought about the
6
+ goals of this project. This made me re-arrange the introductionary
7
+ section here. I will keep a numbered list of the goals of the
8
+ swing_paradise project.
9
+
10
+ (1) This gem contains some add-on bindings to jruby-Swing. This
11
+ is the primary goal.
12
+
13
+ <b>Swing</b> is an extension of the <b>Abstract Window Toolkit</b> (AWT),
14
+ a GUI (graphical user interface).
15
+
16
+ As Swing depends on Java, this project here really only makes
17
+ sense for use via <b>jruby</b>.
18
+
19
+ At present the project is fairly incomplete, but over the
20
+ coming months this should be improved. Right now this project
21
+ is beta-quality and I do not recommend anyone to use this
22
+ project. However had, for some limited scope, this project may
23
+ be fairly useful even if incomplete.
24
+
25
+ (2) Note that while the primary focus of this project will be on
26
+ Swing-based applications and add-on improvements, to make working
27
+ with jruby and Swing suck less, there is a secondary focus for
28
+ this project as well, in that I will attempt to create as many
29
+ Swing-based applications as possible, to make working on Windows
30
+ suck less. Most of these add-ons will reside under
31
+ <b>swing_paradise/widget_collection/</b>, but some may be grouped
32
+ into different gems, under either gui/jruby/ or gui/universal_widgets.
33
+ The latter will probably become more relevant in the future,
34
+ whereas for now, gui/jruby/ will be where most of the gui-relevant
35
+ bindings reside under.
36
+
37
+ With "Swing-based applications" I specifically mean being able to
38
+ use custom, ad-hoc widgets that solve certain problems, such
39
+ as "I want to delete the first page of this .pdf file,
40
+ via a GUI", on windows. In fact, that has been one major use
41
+ case why I intensified code for this project in October
42
+ 2023 - I had to use windows as primary operating system
43
+ every now and then, and it always annoyed me compared
44
+ to Linux, so I decided to create widgets (and describe
45
+ them, too) that will help me on windows. Also note that
46
+ this is an ongoing effort - I can not predict how useful
47
+ and extensive this will be. Stay tuned nonetheless.
48
+
49
+ (3) Another focus of this project is to provide useful documentation
50
+ in regards to Swing, as well as jruby. This helps me as a mnemonic,
51
+ but it may also be helpful to new users, in what they can do
52
+ with the project here in the long run. When I started this
53
+ project there was next to no project that documented
54
+ Swing + jruby. So one aim of this project has been to
55
+ polish the documentation as much as possible.
56
+
57
+ ## Terminology
58
+
59
+ In Java-Swing, a window is called a <b>frame</b>, which is represented
60
+ by class <b>JFrame</b>.
61
+
62
+ The default layout for Java-Swing components is a border layout.
63
+
64
+ ## SwingParadise::BaseModule
65
+
66
+ SwingParadise::BaseModule is the core helper module of
67
+ this gem.
68
+
69
+ You can include it, since it is a module, via:
70
+
71
+ require 'swing_paradise/base_module/base_module.rb'
72
+ include SwingParadise::BaseModule
73
+
74
+ See also the distributed examples if you want to know
75
+ more about how to use this in practice.
76
+
77
+ Since as of 29th October 2023, this will also automatically
78
+ pull in most of the important java-swing methods. I found
79
+ this easier to work with, than have to remember which
80
+ widgets I need.
81
+
82
+ This is done via java_import statements, such as:
83
+
84
+ java_import javax.swing.JPasswordField
85
+
86
+ So basically you can omit a few lines in your application
87
+ by tapping into the BaseModule module.
88
+
89
+ ## Simplified quitting
90
+
91
+ Use the following method to <b>quit</b> easily:
92
+
93
+ do_quit
94
+
95
+ For instance, a <b>quit button</b> could then be done in this
96
+ manner:
97
+
98
+ quit_button.on_clicked {
99
+ do_quit
100
+ }
101
+
102
+ ## Useful java_import headers
103
+
104
+ include Java
105
+
106
+ java_import javax.swing.JButton
107
+ java_import javax.swing.JFrame
108
+ java_import javax.swing.JLabel
109
+ java_import javax.swing.JPanel
110
+ java_import javax.swing.JTextArea
111
+ java_import javax.swing.JScrollBar
112
+ java_import javax.swing.JTextField
113
+ java_import javax.swing.JSpinner
114
+ java_import javax.swing.SpinnerNumberModel
115
+ java_import java.lang.System
116
+ java_import java.awt.Font
117
+
118
+ ## Usage example for setBounds
119
+
120
+ _.setBounds(10, 20, 200, 40) /* is: x-coordinate, y-coordinate, width, height) */
121
+ _.set_bounds(10, 20, 200, 40) /* is: x-coordinate, y-coordinate, width, height) */
122
+
123
+ Note that both variants work. I prefer <b>.set_bounds()</b>.
124
+
125
+ <!---
126
+
127
+ https://www.rubydoc.info/gems/swing_paradise/0.1.13#jtextarea
128
+
129
+ -->
130
+ ## JTextArea
131
+
132
+ First, let's have a look as to how a JTextArea may look like (on Windows):
133
+
134
+ <img src="https://i.imgur.com/CWVYskn.png" style="margin: 1em">
135
+
136
+ The <b>JTextArea class</b> provides a component that displays multiple lines of
137
+ text.
138
+
139
+ If only one line of input is required from the user, then a <b>text field</b>
140
+ should be used rather than JTextArea.
141
+
142
+ In <b>raw Java</b>, the code for instantiating a new JTextArea goes like this:
143
+
144
+ text_area = new JTextArea(5, 20);
145
+ JScrollPane scroll_pane = new JScrollPane(text_area);
146
+ text_area.setEditable(false);
147
+
148
+ In the code above, the API for JTextArea() follows this
149
+ signature: <b>JTextArea(int rows, int columns)</b> - so you first
150
+ pass in the number of rows, and then pass in the number of columns.
151
+
152
+ In Java, you can set the background colour to a colour of your choosing via:
153
+
154
+ import java.awt.Color;
155
+ Color color = new Color(255,0,0); /* This is red. */
156
+ text_area.setBackground(color);
157
+
158
+ The textarea is quite flexible. For instance, you can force it to
159
+ ignore newlines entered by the user, thus making it essentially
160
+ a single-line input entry:
161
+
162
+ textview = create_textarea
163
+ textview.getDocument.putProperty('filterNewlines', true)
164
+
165
+ As this is a bit annoying to remember, I added this method:
166
+
167
+ textview.filter_newlines
168
+
169
+ As always, you need to include SwingParadise::BaseModule for
170
+ this add-on functionality.
171
+
172
+ Most of the time you probably don't want this behaviour though.
173
+
174
+ To set to a different background colour, use something like this:
175
+
176
+ textview.setBackground(Color::GREEN)
177
+
178
+ Line-wrapping and wrap-style can also be set:
179
+
180
+ textview.setLineWrap(true)
181
+ textview.setWrapStyleWord(false)
182
+
183
+ ## JComboBox - working with combo-boxes in Java swing and jruby
184
+
185
+ You can instantiate a new combo box via:
186
+
187
+ combo_box = JComboBox.new
188
+
189
+ Now, in order to fill it up, you can use something like this:
190
+
191
+ array = %w( apple bird cat dog eagle ferret )
192
+ array.each {|this_item|
193
+ combo_box.addItem(this_item)
194
+ }
195
+
196
+ So .addItem() can be used to add more elements to the combo-box.
197
+
198
+ As the above is a bit cumbersome, if you make use of
199
+ <b>SwingParadise::BaseModule</b>, you can use the following API
200
+ instead:
201
+
202
+ array = %w( apple bird cat dog eagle ferret )
203
+ combo_box(array) # So you can simply pass in the full Array here
204
+
205
+ To select a specific index, that is, a specific entry on that
206
+ combo box, you can use the method <b>.setSelectedIndex()</b>:
207
+
208
+ combo_box.setSelectedIndex(2) # For the third entry.
209
+
210
+ To query which index is the currently selected one on a
211
+ combo-box, use the method <b>.selected_index</b>, as in:
212
+
213
+ combo_box.selected_index
214
+
215
+ To obtain the selected entry, use <b>.selected_item</b>,
216
+ as in:
217
+
218
+ combo_box.selected_item
219
+
220
+ ## Java::JavaAwtEvent::ActionEvent
221
+
222
+ Events in java can be found under <b>java.awt.events.*</b>.
223
+
224
+ <b>class Java::JavaAwtEvent::ActionEvent</b> is the base class for
225
+ when Java Swing fires an event, such as when the user changes the
226
+ content of a combo-box.
227
+
228
+ The syntax to use it, from <b>jruby</b>, goes like this:
229
+
230
+ widget.add_action_listener { |event|
231
+ }
232
+
233
+ So you designate a block variable; I recommend to consistently call
234
+ it <b>event</b>, as that should simplify things.
235
+
236
+ How can you find out the specific event?
237
+
238
+ One way goes via the method <b>.get_action_command()</b>,
239
+ such as in:
240
+
241
+ event.get_action_command
242
+
243
+ action_command = event.get_action_command
244
+
245
+ For the changed content of a combo-box, the result
246
+ would <b>comboBoxChanged</b>.
247
+
248
+ To respond to this, you can use the following snippet:
249
+
250
+ case event.get_action_command
251
+ when /comboBoxChanged/
252
+ end
253
+
254
+ I needed this functionality for a widget that, when the user changes
255
+ the combo-box content, another entry is also changed, reflecting the
256
+ currently selected entry there.
257
+
258
+ ## Available colours
259
+
260
+ Just a simple listing of available colours in a java swing
261
+ application:
262
+
263
+ Color::RED
264
+ Color::BLUE
265
+ Color::GREEN
266
+ Color::BLACK
267
+
268
+ ## Obtaining the height and width of a widget
269
+
270
+ Use .getBounds as in:
271
+
272
+ frame.getBounds()
273
+ height = r.height
274
+ width = r.width
275
+
276
+ ## The GridLayout
277
+
278
+ A GridLayout in java-swing looks like this:
279
+
280
+ <img src="https://docs.oracle.com/javase/tutorial/figures/uiswing/layout/GridLayoutDemo.png" style="margin: 1em">
281
+
282
+ In other words: you arrange elements (widgets) in a 2D-like matrix. This
283
+ is also called <b>a grid of cells</b>. Each component in the grid
284
+ is <b>exactly</b> the same size.
285
+
286
+ To create a new GridLayout, in raw Java, use this:
287
+
288
+ /* API: GridLayout(int rows, int cols) */
289
+ GridLayout x = new GridLayout(3, 3); /* A 3x3 grid */
290
+
291
+ You can then add new elements to it via:
292
+
293
+ .add(new JButton("Button 1"));
294
+ .add(new JButton("Button 2"));
295
+
296
+ And so forth.
297
+
298
+ If you use SwingParadise::BaseModule then you can also make
299
+ use of the .create_grid() method.
300
+
301
+ grid = create_grid('2x2')
302
+ grid.add(button('Button 1'))
303
+ grid.add(button('Button 2'))
304
+
305
+ This should be equivalent to the above mentioned Java code.
306
+
307
+ ## JCheckBox and checkboxes in Java swing
308
+
309
+ Let's first look at an image how checkboxes look in Java swing:
310
+
311
+ <img src="https://i.imgur.com/E5gugWY.png" style="margin: 1em">
312
+
313
+ Let's next have a look at how we <b>add checkboxes in raw Java swing</b>:
314
+
315
+ JPanel panel = new JPanel();
316
+ panel.add(label);
317
+
318
+ JCheckBox one = new JCheckBox("one");
319
+ JCheckBox two = new JCheckBox("two");
320
+
321
+ panel.add(one);
322
+ panel.add(two);
323
+
324
+ So, we make use of <b>JCheckBox</b>. A second argument can be passed,
325
+ to determine whether the check-box is checked or whether it is not:
326
+
327
+ JCheckBox.new("Foobar", true)
328
+ JCheckBox.new("Foobar", false)
329
+
330
+ To determine whether a JCheckBox is <b>checked</b> - aka selected, the
331
+ following method can be used:
332
+
333
+ checkbox.isSelected()
334
+
335
+ Or, if you use the swing_paradise gem, you can also use:
336
+
337
+ checkbox.is_selected?
338
+
339
+ To mark the checkbox as checked, use:
340
+
341
+ checkbox.setSelected(true)
342
+
343
+ ## JFrame
344
+
345
+ To create a new frame, aka a new JFrame, from jruby, use:
346
+
347
+ frame = JFrame.new # This would be an untitled frame.
348
+ frame = JFrame.new("Frame Title") # And this would set the title to "Frame Title".
349
+
350
+ If you'd like to you could also use the full qualifier (full name),
351
+ which is:
352
+
353
+ frame = javax.swing.JFrame.new
354
+ # panel = Java::javax::swing::JFrame.new # This variant may also work, but is not as elegant as the one above.
355
+
356
+ However had, note that both variants shown above are more verbose, so
357
+ it may not be worth the extra time to type; nonetheless, should you
358
+ ever have a use case to scope specifically to a particular class,
359
+ you can preface it via <b>javax.swing</b> (or wherever else that
360
+ particular swing-class resides at).
361
+
362
+ To set a grid layout you can use the method called <b>.set_layout()</b>,
363
+ as seen in the following example:
364
+
365
+ frame.set_layout(
366
+ java.awt.GridLayout.new(2, 2, 2, 2)
367
+ )
368
+
369
+ This is especially useful for any 2D layouts.
370
+
371
+ To <b>exit a JFrame</b>, as the main pane, Java Swing usually
372
+ requires that you use something like this:
373
+
374
+ frame.setDefaultCloseOperation(JFrame::EXIT_ON_CLOSE)
375
+
376
+ I found this a bit cumbersome to type and difficult to
377
+ remember, so the SwingParadise::BaseModule allows you
378
+ to use this method instead:
379
+
380
+ default_close
381
+
382
+ This one is easier for me to remember, and less to type, too.
383
+
384
+ Note that you can not add a JFrame to another JFrame. I ran into
385
+ this issue in December 2023, so I had to note this down here.
386
+
387
+ The explanation I found stated this:
388
+
389
+ "JFrame is a <b>top level container</b> and as such it cannot
390
+ be <b>added</b> to any other container."
391
+
392
+ Typically a JFrame contains two parts: a space area on top for
393
+ the menu bar, and the content pane below the menu bar. Often
394
+ the menu bar is missing, though, so the content pane is
395
+ ultimately more important than the menu bar.
396
+
397
+ Further methods for the JFrame include these (as a sample):
398
+
399
+ .setVisible(boolean b)
400
+ .setTitle(String title)
401
+ .setSize(int width, int height)
402
+ .setLocation(int horizontal, int vertical)
403
+ .pack()
404
+ .setDefaultCloseOperation(int operation)
405
+
406
+ By default a JFrame is not visible, so we have to use:
407
+
408
+ frame.setVisible(true)
409
+
410
+ To make it visible.
411
+
412
+ You can designate the size of the main JFrame via .setSize():
413
+
414
+ .setSize(int width, int height)
415
+ .setSize(600, 420)
416
+
417
+ Note that calling the method .pack() will resize the frame so that
418
+ it tightly fits around components embedded into its content
419
+ pane.
420
+
421
+ To make the whole application quit when the close-action is
422
+ triggered, use:
423
+
424
+ frame.setDefaultCloseOperation(JFrame::EXIT_ON_CLOSE)
425
+
426
+ ## JPanel
427
+
428
+ In raw jruby, you can create a new instance of JPanel by issuing
429
+ this:
430
+
431
+ panel = JPanel.new
432
+
433
+ You can then assign different layouts to be used. For instance,
434
+ to keep the panel left-aligned, meaning you will see new elements
435
+ all appear in a linear left-to-right fashion, you can use a
436
+ FlowLayout like this:
437
+
438
+ panel.layout = FlowLayout.new(FlowLayout::LEFT)
439
+
440
+ This would look similar to the following image:
441
+
442
+ <img src="https://i.imgur.com/Yr7t7hJ.png" style="margin: 1em">
443
+
444
+ This seems quite convenient and easy to use, so the swing_paradise
445
+ gem tries to make this even easier. Here is the proposed API
446
+ for the above two lines:
447
+
448
+ panel = create_panel { :left }
449
+
450
+ This is <b>exactly</b> the same as:
451
+
452
+ panel = JPanel.new
453
+ panel.layout = FlowLayout.new(FlowLayout::LEFT)
454
+
455
+ Note that FlowLayout is the default layout manager for
456
+ every JPanel. The components will be laid out in a single
457
+ row one after the other.
458
+
459
+ Here is another picture how this would look:
460
+
461
+ <img src="https://www.guru99.com/images/uploads/2012/06/java-flow-layout-manager.jpg" style="margin: 1em">
462
+
463
+ JPanel can also be used to draw onto, via the method called
464
+ <b>paintComponent</b>. Whenever the GUI is resized, this
465
+ method will be automatically called.
466
+
467
+ Take note that .paintComponent() should not be called directly;
468
+ instead, use the .repaint() method in the event you wish to
469
+ draw onto the panel.
470
+
471
+ The API for paintComponent in raw Java Swing goes as follows:
472
+
473
+ public void paintComponent(Graphics g)
474
+
475
+ Graphics here belongs to AWT.
476
+
477
+ ## Working with colours in SWING and jruby
478
+
479
+ The generic way to handle colours in java-swing goes like this:
480
+
481
+ import java.awt.Color;
482
+ Color color = new Color(255,0,0); /* This is red. */
483
+
484
+ ## Using no specific layout
485
+
486
+ Via:
487
+
488
+ frame.setLayout(nil)
489
+
490
+ You can avoid using any specific layout.
491
+
492
+ ## GridBagLayout
493
+
494
+ GridBagLayout aligns components by placing them within a grid
495
+ of cells, allowing components to span more than one cell.
496
+
497
+ The following image shows how this may look like:
498
+
499
+ <img src="https://www.guru99.com/images/uploads/2012/06/java-grid-bag-layout.jpg" style="margin: 1em">
500
+
501
+ ## JButton and buttons in swing
502
+
503
+ Java-Swing calls a button JButton. JButton is not the only button
504
+ available in Java-Swing: we can also use JCheckBox, JRadioButton,
505
+ JMenuItem, JCheckBoxMenuItem, JRadioButtonMenuItem or JToggleButton.
506
+
507
+ An example for a widget that uses three buttons will be shown
508
+ next (on Windows XP):
509
+
510
+ <img src="https://i.imgur.com/xBvl7Fq.png" style="margin: 1em">
511
+
512
+ You can add an icon to a button in swing.
513
+
514
+ First, let's show the Java version for this:
515
+
516
+ JButton button = new JButton(new ImageIcon("foobar.jpg"));
517
+
518
+ <b>ImageIcon</b> can be used for <b>pixel graphics</b>.
519
+
520
+ Next, the equivalent ruby code:
521
+
522
+ button = JButton.new(ImageIcon.new('foobar.jpg'))
523
+
524
+ If you use the swing_paradise gem, the above can be simplified a
525
+ little bit further:
526
+
527
+ button = button(ImageIcon.new('foobar.jpg'))
528
+
529
+ I may extend this API to simplify this further, such as
530
+ <b>button_with_image()</b> or something like that. In fact, in
531
+ February 2024 this was indeed extended: if you use SwingParadise::BaseModule
532
+ then you can use the method called <b>button_with_image()</b> to add
533
+ a button with an image. There are two ways to call this: one is by simply
534
+ passing the path to a local image. The second way is to also pass an
535
+ optional text that is displayed next to the image.
536
+
537
+ To change the background colour for a button, use the following API:
538
+
539
+ button.setBackground(Color.green) # This would make it green.
540
+
541
+ To let a JButton respond to on-click events, one has to
542
+ attach a listener, via the following API:
543
+
544
+ button.addActionListener(ActionListener listener)
545
+
546
+ In jruby this is implemented via a block form, that is via:
547
+
548
+ {
549
+ }
550
+
551
+ To <b>focus</b> on a button, use:
552
+
553
+ button.requestFocusInWindow();
554
+
555
+ To obtain the text (label) if a JButton, use the method
556
+ <b>.getText</b>.
557
+
558
+ If you make use of the swing-paradise gem then you can
559
+ simply call the .on_clicked {} method on a button,
560
+ such as via:
561
+
562
+ button = JButton.new('Please click me.')
563
+ button.on_clicked {
564
+ puts 'I was clicked.'
565
+ }
566
+
567
+ There is, interestingly enough, another way possible for
568
+ achieving the above, in that you specify a distinct
569
+ class that will be invoked when the button is called.
570
+
571
+ So, the code for the button at hand would then look like
572
+ this:
573
+
574
+ button = JButton.new('Please click me.')
575
+ button.addActionListener(ClickAction.new)
576
+
577
+ And you also need to define class ClickAction, like this:
578
+
579
+ class ClickAction
580
+
581
+ include ActionListener
582
+
583
+ def actionPerformed(event) # you can also use: "def action_performed" instead
584
+ puts 'This time the button was called from within clas ClickAction.'
585
+ end
586
+
587
+ end
588
+
589
+ This solution is not quite as convenient as the .on_clicked {} variant,
590
+ but perhaps there may be times when this is needed, so it is mentioned
591
+ here in the documentation. Personally I will continue to prefer
592
+ the <b>.on_clicked {} method variant</b> though - my brain has an
593
+ easier time remembering that variant.
594
+
595
+ You can also use tooltips for a button.
596
+
597
+ Examples:
598
+
599
+ button.setToolTipText('Press Alt+H to trigger this button.')
600
+ button.hint = 'Press Alt+H to trigger this button.'
601
+
602
+ If you need to obtain the tooltip-text, you can use:
603
+
604
+ puts button.getToolTipText
605
+
606
+ The location where the tooltip will be shown, can be obtained via:
607
+
608
+ puts button.getToolTipLocation(MouseEvent)
609
+
610
+ If you want to make the button have a flat-style look, use:
611
+
612
+ button.setBorderPainted(false)
613
+ button.setFocusPainted(false)
614
+ button.setContentAreaFilled(false)
615
+
616
+ The full <b>API documentation</b> for JButton can be found here:
617
+
618
+ https://docs.oracle.com/javase/8/docs/api/javax/swing/JButton.html
619
+
620
+ ## JLabel and text
621
+
622
+ You can right-align a JLabel widget via:
623
+
624
+ JLabel(String text, int horizontalAlignment)
625
+ JLabel label = new JLabel("Telephone", SwingConstants.RIGHT);
626
+
627
+ In jruby-swing this would look like this:
628
+
629
+ label = JLabel.new('Telephone', SwingConstants::RIGHT)
630
+
631
+ After you created a label, you can call several methods on it.
632
+
633
+ For instance, to change the foreground colour, use:
634
+
635
+ label.setForeground(Color c)
636
+
637
+ For the background colour use:
638
+
639
+ label.setBackground(Color c)
640
+
641
+ You can also set the label to be opaque, via:
642
+
643
+ label.setOpaque(boolean b)
644
+ label.setOpaque(true)
645
+ label.setOpaque(false)
646
+
647
+ If true is passed to the latter method then the label
648
+ will be transparent; if it is false, then the label will be
649
+ non-transparent.
650
+
651
+ Interestingly you can also use HTML markup in a JLabel. The
652
+ following example shows how this can be done:
653
+
654
+ label = JLabel.new("<html><span>This is your text</span></html>");
655
+
656
+ ## JColorChooser (javax.swing.colorchooser)
657
+
658
+ <b>JColorChooser</b> can be used to pick a certain colours.
659
+
660
+ Let's have a look at an image, to find out how this may actually look:
661
+
662
+ <img src="https://docs.oracle.com/javase/tutorial/figures/uiswing/components/ColorChooserDemoMetal.png" style="margin: 1em">
663
+
664
+ In raw Java, we would use the following to create a new JColorChooser instance:
665
+
666
+ banner = new JLabel("Some text.", JLabel.CENTER);
667
+ banner.setForeground(Color.yellow);
668
+ jcolorchooser = new JColorChooser(banner.getForeground());
669
+ add(jcolorchooser, BorderLayout.PAGE_END);
670
+
671
+ If you want to create a dialog, for the user to make a choice, you can
672
+ use the <b>.createDialog()</b> method:
673
+
674
+ jcolorchooser.createDialog()
675
+ jcolorchooser.createDialog # Remember, in ruby you can omit the ().
676
+
677
+ ## JOptionPane
678
+
679
+ <b>JOptionPane</b> can be used to ask the user about confirmation about
680
+ certain actions, such as <b>Do you really want to delete this
681
+ file?</b>.
682
+
683
+ ## BorderLayout
684
+
685
+ A BorderLayout places components in up to five areas:
686
+
687
+ <b>top</b>, <b>bottom</b>, <b>left</b>, <b>right</b>,
688
+ and <b>center</b>.
689
+
690
+ It is <b>the default layout manager</b> for every java JFrame.
691
+
692
+ It looks like this:
693
+
694
+ <img src="https://www.guru99.com/images/uploads/2012/06/java-border-layout-manager.jpg" style="margin: 1em">
695
+
696
+ ## BorderFactory
697
+
698
+ BorderFactory can be used to create a frame with a label.
699
+
700
+ Usage example in jruby:
701
+
702
+ _ = BorderFactory.createTitledBorder(' Shell ')
703
+ _.setTitleFont(Font.new('Tahoma', Font::PLAIN, 50)) # This here can be used to set the font that is used.
704
+
705
+ Many variants exist for BorderFactory.
706
+
707
+ For instance, to set a matte-border, you can use:
708
+
709
+ ImageIcon icon = createImageIcon("images/wavy.gif", "wavy-line border icon"); # 20x22
710
+ BorderFactory.createMatteBorder(-1, -1, -1, -1, icon));
711
+
712
+ ## ImageIcon
713
+
714
+ The name icon is a slight misnomer for this class, as it can also deal with
715
+ large images.
716
+
717
+ As argument to this class the path to a local filename should be supplied,
718
+ as a String.
719
+
720
+ Example:
721
+
722
+ image_icon = ImageIcon.new('/tmp/foobar.png')
723
+
724
+ You can also supply an URL instead of a String to a local path.
725
+
726
+ You can query the height and width of this image via:
727
+
728
+ image_icon.getImageHeight() # returns the image height, in n pixels.
729
+ image_icon.getImageWidth() # returns the image width, in n pixels.
730
+
731
+ Keep in mind that instances of class ImageIcon are non-graphical components.
732
+ This means that they have to be put into some container, such as
733
+ JLabel, e. g.:
734
+
735
+ JLabel.new(ImageIcon picture)
736
+ JLabel.new(image_icon) # re-using the variable defined above ^^^
737
+
738
+ You can also load images <b>asynchronously</b>. This can be done via
739
+ <b>Toolkit</b> from the AWT library.
740
+
741
+ Example in Java-Swing:
742
+
743
+ Image picture = Toolkit.getDefaultToolkit.getImage(String filename);
744
+ Image picture = Toolkit.getDefaultToolkit.getImage(String url);
745
+
746
+ In jruby-Swing:
747
+
748
+ picture = Toolkit.getDefaultToolkit.getImage(String filename)
749
+ picture = Toolkit.getDefaultToolkit.getImage('foobar.png')
750
+
751
+ If you need to load multiple images, possibly distributed on
752
+ various servers on the internet, you may want to make use
753
+ of class <b>MediaTracker</b>, which is part of the AWT
754
+ library. MediaTracker can monitor the loading process of many
755
+ images. Interestingly MediaTracker makes use of an id,
756
+ such as via the following method call:
757
+
758
+ .addImage(Image picture, int id)
759
+
760
+ ## Java::JavaAwtEvent::ActionEvent and events in general
761
+
762
+ An event in a SWING application is typically of class
763
+ <b>Java::JavaAwtEvent::ActionEvent</b>, as far as Ruby is
764
+ concerned.
765
+
766
+ ## JTextField
767
+
768
+ <b>JTextField</b> is a lightweight component that allows the
769
+ editing of a single line of text.
770
+
771
+ A <b>JTextField</b> - also known as an <b>entry</b> - is
772
+ a <b>subclass</b> of the <b>JTextComponent</b> class.
773
+
774
+ <b>Padding</b> can be added to a JTextField via the method
775
+ .setMargin() and passing proper insets to it.
776
+
777
+ Example:
778
+
779
+ setMargin(Insets m)
780
+
781
+ text_field = new JTextField("A text field example.");
782
+ text_field.setMargin(new Insets(10, 10, 10, 10));
783
+
784
+ JTextField can also be instantiated in this manner:
785
+
786
+ JTextField(String text, int columns)
787
+
788
+ So the second argument means how many columns this entry
789
+ should have.
790
+
791
+ Documentation for JTextField can be seen here:
792
+
793
+ https://docs.oracle.com/javase/8/docs/api/javax/swing/JTextField.html
794
+
795
+ ## Textfields in Java-SWING via JFormattedTextField
796
+
797
+ If you have a need to hide certain input elements, such as
798
+ via a user-password, you could use the following code, in
799
+ Java-SWING:
800
+
801
+ import javax.swing.text.MaskFormatter;
802
+ MaskFormatter mask_formatter = new MaskFormatter("###-##-####");
803
+
804
+ JFormattedTextField has three preconfigured format types:
805
+
806
+ numbers
807
+ dates
808
+ strings
809
+
810
+ ## JScrollBar
811
+
812
+ First, before this subsection explains some things about a <b>JScollBar</b>, let us state
813
+ that in many cases a developer may want to use <b>JScrollPane</b> instead.
814
+
815
+ <b>JScrollBar</b> is used to create a scrolling widget. This refers to
816
+ a widget that has a vertical and a horizontal bar - both of which
817
+ can be optional - allowing the mouse pointer to click and drag
818
+ the child-widget, to the right, left, up or down. This is especially
819
+ useful for a text-buffer widget, where regular text is displayed
820
+ that overflows to the right hand side (or somewhere else).
821
+
822
+ The following image shows how this looked on Windows XP:
823
+
824
+ <img src="https://i.imgur.com/6AEwGR7.png" style="margin: 1em">
825
+
826
+ So, to summarize: the scroll bar is used to determine the
827
+ viewing area of the component (the child-widget).
828
+
829
+ The scroll bar involves a knob that can be adjusted by the
830
+ user. This is meant for use with the mouse pointer.
831
+
832
+ How to create a new instance for a scroll bar in Java?
833
+
834
+ The following code example (<b>ScrollBarExample.java</b>) shows this:
835
+
836
+ import javax.swing.*;
837
+ import java.awt.*;
838
+
839
+ class ScrollBarExample {
840
+
841
+ public static void main(String[] args) {
842
+ final JFrame frame = new JFrame("ScrollBarExample");
843
+
844
+ JScrollBar scrollBarH = new JScrollBar(JScrollBar.HORIZONTAL, 30, 20, 0, 500);
845
+ JScrollBar scrollBarV = new JScrollBar(JScrollBar.VERTICAL, 30, 40, 0, 500);
846
+
847
+ frame.setSize(300,200);
848
+ frame.getContentPane().add(scrollBarH, BorderLayout.SOUTH);
849
+ frame.getContentPane().add(scrollBarV, BorderLayout.EAST);
850
+ frame.setVisible(true);
851
+ }
852
+
853
+ }
854
+
855
+ Which relevant properties does the scroll bar have?
856
+
857
+ orientation: This indicates a horizontal or a vertical Scrollbar.
858
+ value: This indicates the model's current value. The upper
859
+ limit on the model's value is maximum - extent and the
860
+ lower limit is minimum.
861
+ extent: This indicates the width of the knob of the scrollbar.
862
+ minimum: This indicates the minimum width of the track on which the scrollbar moves.
863
+ maximum: This indicates the maximum width of the track on which the scrollbar moves.
864
+
865
+ If you instantiate a new scrollbar in jruby, using this syntax:
866
+
867
+ JScrollBar.new
868
+
869
+ then the following initial values are used:
870
+
871
+ minimum = 0
872
+ maximum = 100
873
+ value = 0
874
+ extent = 10
875
+
876
+ The first argument is orientation (as Integer).
877
+
878
+ Example:
879
+
880
+ JScrollBar.new(int orientation)
881
+ JScrollBar.new(1)
882
+
883
+ In other words: you can use this to determine the orientation
884
+ of the scrollbar. The value <b>orientation=0</b> means we will
885
+ make use of a horizontal scroll bar, whereas the value
886
+ <b>orientation=1</b> means we will get a vertical scroll bar.
887
+ Most commonly a horizontal scroll bar is used.
888
+
889
+ The most commonly used methods of the JScrollBar class are
890
+ as follows:
891
+
892
+ - The addAdjustmentListener(AdjustmentListener l) method adds a
893
+ listener to the specified JScrollBar instance. The listener
894
+ will be notified every time a change to the model of the
895
+ scroll bar is detected.
896
+ - The getModel() method returns the model of the scroll bar.
897
+ - The getMaximum() method returns the maximum value (maximum -
898
+ extent) of the scrollbar.
899
+ - The getMinimum() method returns the minimum value of the scroll
900
+ bar.
901
+ - The getOrientation() method returns the orientation of the
902
+ scroll bar.
903
+ - The getValue() method returns the scrollbar’s value.
904
+ - The setMaximum() method is used to set the maximum value
905
+ of the scrollbar.
906
+ - The setMinimum() method is used to set the minimum value of the scroll bar.
907
+ - The setOrientation() method is used to set the orientation of the scroll bar.
908
+ - The setValue() method is used to set the scrollbar’s value.
909
+
910
+ If you want to set inner padding, you have to make use of
911
+ a border:
912
+
913
+ scroll_bar.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10))
914
+
915
+ ## Checking for the escape-key being pressed
916
+
917
+ In raw Java SWING, we can use the following line of code to check whether
918
+ the user has pressed the escape-key:
919
+
920
+ if (event.getKeyCode() == KeyEvent.VK_ESCAPE) {
921
+ }
922
+
923
+ In jruby SWING, this would be:
924
+
925
+ if (event.getKeyCode() == KeyEvent::VK_ESCAPE) {
926
+ }
927
+
928
+ Note that <b>KeyEvent::VK_ESCAPE</b> returns a number; in this case
929
+ that number is <b>27</b>.
930
+
931
+ ## The Graphics class
932
+
933
+ Available methods include:
934
+
935
+ drawLine(int xstart, int ystart, int xend, int yend)
936
+ drawRect(int xleft, int ytop, int width, int height)
937
+ drawOval(int xleft, int ytop, int width, int height)
938
+ drawString(String text, int xleft, int ybottom)
939
+ fillRect(int xleft, int ytop, int width, int height)
940
+ fillOval(int xleft, int ytop, int width, int height)
941
+ setColor(Color col)
942
+
943
+ All these int-arguments refer to <b>pixels</b>.
944
+
945
+ <b>.drawLine(xstart,ystart,xend,yend)</b> draws a line segment
946
+ between the points with coordinates (xstart, ystart) and
947
+ (xend, yend).
948
+
949
+ Note that .setColor(col) sets the colour of the drawing to col.
950
+ This colour is used until the setColor command is used again.
951
+
952
+ ## The mouse and mouse-events
953
+
954
+ A mouse event in jruby is of class <b>Java::JavaAwtEvent::MouseEvent</b>.
955
+
956
+ In Java-Swing two interfaces process mouse events:
957
+
958
+ 1) MouseListener
959
+ 2) MouseMotionListener
960
+
961
+ Note that key listeners react to key strokes (aka key press events).
962
+
963
+ ## JScrollPane
964
+
965
+ First, let's have a look how a JScrollPane may look like:
966
+
967
+ <img src="https://i.imgur.com/sGd0NN6.png" style="margin: 1em">
968
+
969
+ JScrollPane is the primary widget to be used when scrolling
970
+ should be used (in Swing).
971
+
972
+ Next, let's look at a raw Java example for how to work with a <b>JScrollPane</b>:
973
+
974
+ import java.awt.FlowLayout;
975
+ import javax.swing.JFrame;
976
+ import javax.swing.JScrollPane; /* This is where it resides. */
977
+ import javax.swing.JtextArea;
978
+
979
+ public class JScrollPaneExample {
980
+ private static final long serialVersionUID = 1L;
981
+
982
+ private static void createAndShowGUI() {
983
+
984
+ // Create and set up the window.
985
+ final JFrame frame = new JFrame("Scroll Pane Example");
986
+
987
+ // Display the window.
988
+ frame.setSize(500, 500);
989
+ frame.setVisible(true);
990
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
991
+
992
+ // set flow layout for the frame
993
+ frame.getContentPane().setLayout(new FlowLayout());
994
+
995
+ JTextArea textArea = new JTextArea(20, 20);
996
+ JScrollPane scrollableTextArea = new JScrollPane(textArea);
997
+
998
+ scrollableTextArea.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
999
+ scrollableTextArea.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
1000
+
1001
+ frame.getContentPane().add(scrollableTextArea);
1002
+ }
1003
+ public static void main(String[] args) {
1004
+
1005
+ javax.swing.SwingUtilities.invokeLater(new Runnable() {
1006
+ public void run() {
1007
+ createAndShowGUI();
1008
+ }
1009
+ });
1010
+ }
1011
+ }
1012
+
1013
+ In jruby this may look like so:
1014
+
1015
+ text_area = JTextArea.new(20, 20)
1016
+ scrollable_text_area = JScrollPane.new(text_area) # Add the scroll-pane here.
1017
+ scrollable_text_area.setHorizontalScrollBarPolicy(JScrollPane::HORIZONTAL_SCROLLBAR_ALWAYS)
1018
+ scrollable_text_area.setVerticalScrollBarPolicy(JScrollPane::VERTICAL_SCROLLBAR_ALWAYS)
1019
+
1020
+ In other words: you pass the widget that you want to see scroll-bars for,
1021
+ into JScrollPane.new() - in that case, the variable text_area.
1022
+
1023
+ The viewport that you see will display the content of the JTextArea then.
1024
+
1025
+ If the whole component fits into the viewport then the default behaviour is
1026
+ that the scroll bars disappear. This behaviour can be changed, though, via
1027
+ the horizontal and vertical policy.
1028
+
1029
+ ## Using mnemonics for JButton
1030
+
1031
+ You can use shortcut-keys, aka mnemonics, for buttons.
1032
+
1033
+ This is done in general via the method called <b>.setMnemonic()</b>.
1034
+
1035
+ Example for this:
1036
+
1037
+ button.setMnemonic(KeyEvent::VK_H)
1038
+
1039
+ VK_H means Alt+H. Alt here refers to the Alt-key. H is simply the letter
1040
+ H on the keyboard, so this means "press the alt-key as well as the h
1041
+ key".
1042
+
1043
+ If you instead want to enable Akt+H, use:
1044
+
1045
+ button.setMnemonic(KeyEvent::VK_A)
1046
+
1047
+ You can also use numbers instead. For instance:
1048
+
1049
+ button.setMnemonic(KeyEvent::VK_1)
1050
+
1051
+ This would allow you to respond to "Alt+1" key combinations. You can
1052
+ find examples related to this in the file at <b>examples/017_button_example.rb</b>.
1053
+ That file will, in the long run, contain all useful button-related
1054
+ activities that may be useful when designing applications via jruby-SWING.
1055
+
1056
+ As I find this a bit cumbersome to remember (I can't remember VK_1 or
1057
+ similar crypt names), I decided to add an API that simplifies this.
1058
+
1059
+ Usage example:
1060
+
1061
+ button.keycombo('Alt+1') # respond to alt+1
1062
+ button.keycombo('Alt+W') # respond to alt+W
1063
+
1064
+ Note that this currently (<b>January 2024</b>) only works for Alt-key
1065
+ combinations. At a later time I may extend this for more key-combinations.
1066
+
1067
+ ## Working with JTable
1068
+
1069
+ A new table can be created via:
1070
+
1071
+ JTable(int rows, int cols): Creates a table of size rows * cols.
1072
+
1073
+ Like a table with (2, 3), 2 rows, and 3 columns.
1074
+
1075
+ You can also simplify it a bit, by using
1076
+ <b>javax.swing.table.DefaultTableModel</b> via:
1077
+
1078
+ m = javax.swing.table.DefaultTableModel.new
1079
+ m.add_column("id")
1080
+ m.add_column("name")
1081
+ m.add_row(['1', "jimmy"].to_java)
1082
+ m.add_row(['2', "robert"].to_java)
1083
+
1084
+ table = JTable.new(m)
1085
+ # The fulle qualifier for JTable is javax.swing.JTable, by the way.
1086
+
1087
+ You can add java-specific objects, such as a vector, via:
1088
+
1089
+ m.add_row java.util.Vector.new('"ト', 'あ', 'い'])
1090
+
1091
+ You can also pass the columns by calling DefaultTableModel.new,
1092
+ like this:
1093
+
1094
+ m = DefaultTableModel.new(nil, ["No.", "Name", "Path"].to_java)
1095
+
1096
+ The <b>API documentation</b> for JTable can be found here:
1097
+
1098
+ https://docs.oracle.com/javase/8/docs/api/javax/swing/JTable.html
1099
+
1100
+ ## Converting an Array into Java::JavaLang:Object:
1101
+
1102
+ This can be done by calling .to_java.
1103
+
1104
+ Example for this:
1105
+
1106
+ pp ["1", "jimmy"].to_java # => #<Java::JavaLang::Object[2]: ["1", "jimmy"]>
1107
+
1108
+ ## JEditorPane()
1109
+
1110
+ <b>JEditorPane()</b> can be used to <b>display text via java-swing</b>.
1111
+
1112
+ Let's have a look at an image, how this may look:
1113
+
1114
+ <img src="https://i.imgur.com/aVioB68.png" style="margin: 1em">
1115
+
1116
+ If you need to obtain the current text stored in a JEditorPane,
1117
+ you can use the method called <b>.getText()</b>.
1118
+
1119
+ ## JComponent
1120
+
1121
+ Every <b>JComponent</b> can have one or more <b>borders</b>.
1122
+
1123
+ You can put a border around a JComponent. This is done via
1124
+ the <b>.setBorder()</b> method.
1125
+
1126
+ This method is usually combined with the <b>BorderFactory class</b>.
1127
+
1128
+ In raw Java swing, the code would look like this:
1129
+
1130
+ JPanel pane = new JPanel();
1131
+ pane.setBorder(BorderFactory.createLineBorder(Color.black));
1132
+
1133
+ ## javax.swing.border
1134
+
1135
+ This subsection may eventually contain some information about
1136
+ borders in java-swing applications.
1137
+
1138
+ ## JTextPane
1139
+
1140
+ <b>JTextPane</b> can be used to render HTML content.
1141
+
1142
+ The full scope of JTextPane is <b>javax.swing.JTextPane</b>.
1143
+
1144
+ ## Creating a MenuBar via JMenu
1145
+
1146
+ First, let's look at how a Menu (JMenu) looks in Java-Swing:
1147
+
1148
+ <img src="https://i.imgur.com/PNlkIfK.png" style="margin: 1em">
1149
+
1150
+ The primary menu bar is called <b>JMenuBar</b> in Java-Swing.
1151
+
1152
+ To then create a menu, in raw Java-Swing, the following code
1153
+ could be used:
1154
+
1155
+ JMenuBar menu_bar = new JMenuBar(); # Create a new menubar here.
1156
+ JMenu m1 = new JMenu("FILE");
1157
+ menu_bar.add(m1);
1158
+ JMenu m2 = new JMenu("Help");
1159
+ menu_bar.add(m2);
1160
+
1161
+ Or in jruby code:
1162
+
1163
+ menu_bar = JMenuBar.new
1164
+ m1 = JMenu.new("FILE")
1165
+ menu_bar.add(m1)
1166
+ m2 = JMenu.new("Help")
1167
+ menu_bar.add(m2)
1168
+
1169
+ If you use the swing_paradise gem then you can also use <<
1170
+ rather than .add(). Example:
1171
+
1172
+ menu_bar << m1
1173
+ menu_bar << m2
1174
+
1175
+ This is a bit shorter to type.
1176
+
1177
+ Take note that the constructor for <b>JMenu</b> is this:
1178
+
1179
+ JMenu(String menuTitle);
1180
+ JMenu.new(menuTitle) # This for jruby.
1181
+
1182
+ So the name of the menu entry should be given, as a <b>String</b>.
1183
+
1184
+ You can also attach mnemonics to this, such as via:
1185
+
1186
+ menu = JMenu.new('A Menu')
1187
+ menu.setMnemonic(KeyEvent.VK_A)
1188
+
1189
+ As can be seen from the above code, we first need to create a new
1190
+ <b>JMenuBar</b> - this is the first step.
1191
+
1192
+ Then, now that we have a menu-bar, we can add new menus to
1193
+ it, of class JMenu. We use the method called .add() to
1194
+ add menu-entries there.
1195
+
1196
+ Once you are done with the menu, it is time to add it. The menu
1197
+ is typically added to a <b>JFrame</b>, via the following
1198
+ API:
1199
+
1200
+ setJMenuBar(JMenuBar menuBar)
1201
+ frame.setJMenuBar(menuBar)
1202
+
1203
+ Take note that there are two distinct methods that are rather
1204
+ similar: one is called <b>.setJMenuBar</b> and the other one is
1205
+ called <b>.setMenuBar</b>. JMenuBar() is for Swing and MenuBar()
1206
+ is for AWT.
1207
+
1208
+ Individual Menu items behave like buttons.
1209
+
1210
+ If you have a need to disable an individual menu item then you
1211
+ can do so via:
1212
+
1213
+ setEnabled(boolean b)
1214
+
1215
+ Example in jruby-Swing for disabling a menu item:
1216
+
1217
+ menu_item.setEnabled(false)
1218
+
1219
+ To then bind an event to a menu-item, use <b>.addActionListener</b>.
1220
+
1221
+ Example for this:
1222
+
1223
+ first = JMenuItem.new('Item 1')
1224
+ m1.add(first)
1225
+ first.addActionListener {|event|
1226
+ puts 'Hello world!'
1227
+ }
1228
+ # Or, to exit, use this:
1229
+ first.add_action_listener { |event|
1230
+ System.exit(0) # or just exit, should be fine too.
1231
+ }
1232
+
1233
+ If you have a need to repaint the menu bar, you can use .revalidate()
1234
+ as in:
1235
+
1236
+ menu_bar.revalidate()
1237
+ menu_bar.revalidate # or this one, as ruby allows you to omit ()
1238
+
1239
+ Once you created your menu, you have to fill the submenus with
1240
+ JMenuItem entries. The following shows such an example I was
1241
+ using in January 2024:
1242
+
1243
+ open_a_local_file_entrypoint = JMenuItem.new('Open a local file', KeyEvent::VK_T)
1244
+ open_a_local_file_entrypoint.use_this_font = :hack_26
1245
+ open_a_local_file_entrypoint.addActionListener {|event|
1246
+ do_choose_a_local_file_then_read_it_in
1247
+ }
1248
+ m1.add(open_a_local_file_entrypoint)
1249
+
1250
+ So, to respond to the on-selected event, make use of .addActionListenere.
1251
+
1252
+ ## Working with JSplitPane
1253
+
1254
+ Via JSplitPane - to be found under <b>javax.swing.JSplitPane</b> - you can
1255
+ split a pane, such as splitting into a left and a right component.
1256
+
1257
+ Let's look at two images as to how <b>JSplitPane</b> looks like:
1258
+
1259
+ <img src="https://i.imgur.com/zDe6NHK.png" style="margin: 1em">
1260
+ <img src="https://i.imgur.com/ucVpEcj.png" style="margin: 1em">
1261
+
1262
+ To create a new <b>split-pane</b>, you would use the following code:
1263
+
1264
+ split_pane = JSplitPane.new(JSplitPane::VERTICAL_SPLIT)
1265
+
1266
+ You can then modify its layout, or whether it allows one-touch
1267
+ expendable behaviour:
1268
+
1269
+ split_pane.setContinuousLayout(true)
1270
+ split_pane.setOneTouchExpandable(true)
1271
+
1272
+ You can then put other widgets into it, such as a button on top:
1273
+
1274
+ button_on_top = JButton.new('A')
1275
+ split_pane.setTopComponent(button_on_top)
1276
+
1277
+ And a button on bottom:
1278
+
1279
+ button_on_bottom =JButton.new('B')
1280
+ split_pane.setBottomComponent(button_on_bottom)
1281
+
1282
+ ## Assigning Enter as the trigger key for all JButtons in a Java-Swing application
1283
+
1284
+ UIManager.put("Button.defaultButtonFollowsFocus", Boolean::TRUE)
1285
+
1286
+ ## Font, working with fonts and using fonts in a java-swing application
1287
+
1288
+ Working with fonts in a java-swing application (or jruby-swing application)
1289
+ can be a bit tricky. This paragraph here tries to gather useful information
1290
+ pertaining to this.
1291
+
1292
+ The raw Java code for creating a new font, goes like this:
1293
+
1294
+ Font use_this_font = new Font("SansSerif", Font.PLAIN, 20);
1295
+
1296
+ In jruby this would be equivalent to the following code:
1297
+
1298
+ use_this_font = Font.new('SansSerif', Font::Plain, 20)
1299
+
1300
+ Next follows a list, as example, how to handle different fonts - first
1301
+ in java-swing, then in jruby-swing:
1302
+
1303
+ widget.setFont(new Font("Times New Roman", Font.PLAIN, 12))
1304
+ widget.setFont(new Font("Hack", Font.PLAIN, 40))
1305
+
1306
+ # now in jruby:
1307
+ widget.setFont(Font.new("Times New Roman", Font::PLAIN, 12))
1308
+ widget.setFont(Font.new("Hack", Font::PLAIN, 40))
1309
+
1310
+ ## Choosing files via a GUI, through JFileChooser - file-chooser functionality
1311
+
1312
+ Let's first have a look how JFileChooser may look on WinXP:
1313
+
1314
+ <img src="https://i.imgur.com/pkEoG6T.png" style="margin: 1em">
1315
+
1316
+ You can use something like the following to get a file-chooser
1317
+ in jruby-swing:
1318
+
1319
+ file_chooser = JFileChooser.new
1320
+ # file_chooser.setFileSelectionMode(JFileChooser::DIRECTORIES_ONLY)
1321
+
1322
+ result = file_chooser.showOpenDialog(nil) # or pass true here, to show the open dialog.
1323
+ case result
1324
+ when JFileChooser::APPROVE_OPTION
1325
+ this_file = file_chooser.getSelectedFile.getAbsoluteFile.to_s
1326
+ # this_file = File.absolute_path(this_file)
1327
+ main_entry?.set_text(this_file)
1328
+ end
1329
+
1330
+ Adjust accordingly to your use case. Keep in mind that on closing, a
1331
+ file selection dialogue returns an integer value which is one of
1332
+ the following integer constants:
1333
+
1334
+ APPROVE_OPTION: indicates that the ‘Open’ or ‘Save’, in case of a
1335
+ save dialogue button of the dialogue has been
1336
+ clicked.
1337
+ CANCEL_OPTION: indicates that the ‘Cancel’ button of the dialogue
1338
+ has been clicked.
1339
+
1340
+ Note that <b>JFileChooser::APPROVE_OPTION</b> returns <b>0</b>.
1341
+
1342
+ To obtain the file that was selected, the method <b>.getSelectedFile</b>
1343
+ can be used, as shown in the code example above.
1344
+
1345
+ Since as of January 2024 you can also use UniversalWidgets.main_file?
1346
+ and UniversalWidgets.set_main_file() to keep track of the chosen file.
1347
+
1348
+ ## JDialog and dialogues in jruby-SWING
1349
+
1350
+ First, what is a dialogue?
1351
+
1352
+ A dialogue is basically a simple means, via a widget, to obtain
1353
+ information from the user. This can then be of help for user-program
1354
+ interaction.
1355
+
1356
+ Dialogues - that is, the widgets - are used when the application needs
1357
+ information from the user in order to proceed with a task or some
1358
+ other event.
1359
+
1360
+ In jruby-SWING, the primary use of dialogues happens via
1361
+ <b>JDialog</b>:
1362
+
1363
+ <b>JDialog</b> can be thought of to be <b>a pop-up window</b> that pops out
1364
+ when a message has to be displayed to the user.
1365
+
1366
+ The namespace for <b>JDialog</b> is <b>javax.swing.JDialog</b>.
1367
+
1368
+ Some dialoguses are pre-defined. For instance, a message dialogue
1369
+ can be invoked via:
1370
+
1371
+ JOptionPane.showMessageDialog(
1372
+ Component parent,
1373
+ String title,
1374
+ String message,
1375
+ int type
1376
+ );
1377
+
1378
+ More documentation pertaining to JDialog, in particular its API,
1379
+ can be seen here:
1380
+
1381
+ https://docs.oracle.com/javase/8/docs/api/javax/swing/JDialog.html
1382
+
1383
+ ## Working with JRadioButton
1384
+
1385
+ First, let's look at <b>two images</b> to see how a JRadioButton
1386
+ may look like:
1387
+
1388
+ <img src="https://i.imgur.com/E4S1VWL.png" style="margin-right: 1em">
1389
+ <img src="https://i.imgur.com/hSrhzWz.jpg" style="margin: 1em">
1390
+
1391
+ <b>JRadioButton</b>'s fully qualified namespace is
1392
+ <b>javax.swing.JRadioButton</b>. Its superclass is
1393
+ a <b>JToggleButton</b>.
1394
+
1395
+ To create a new JRadioButton via java-swing, use:
1396
+
1397
+ JRadioButton x = new JRadioButton("Foobar");
1398
+
1399
+ <b>Radio buttons</b> can be pressed and they can be grouped. They
1400
+ will stay pressed until another radio button of the group is
1401
+ pressed. A black dot appears inside the circular area if
1402
+ the button is pressed, as can be seen on the above image.
1403
+
1404
+ The text that is displayed on a radio-button can be defined
1405
+ via passing a String as the first argument, as seen in the
1406
+ above example. For sake of completion we will show how this
1407
+ is done in jruby too:
1408
+
1409
+ radio_button = JRadioButton.new('Foobar')
1410
+
1411
+ If you have a need to programmatically set that radio button
1412
+ selected or de-selected, use this method:
1413
+
1414
+ radio_button.setSelected(true) # It is now selected.
1415
+ radio_button.setSelected(false) # It is now de-selected.
1416
+
1417
+ .setActionCommand(String command) assigns the string command
1418
+ as the action command to the button. Radio buttons are not
1419
+ automatically assigned an action command. This is because
1420
+ their label is often not a text but a picture. The action
1421
+ command can be set via this method.
1422
+
1423
+ <b>.getActionCommand()</b> returns the action command
1424
+ assigned to the button.
1425
+
1426
+ Normally radio buttons are put into a <b>ButtonGroup</b>. This
1427
+ has the effect that if the user selects one radio button,
1428
+ all other radio buttons are de-selected. In other words:
1429
+ this achieves that only one radio button is actively
1430
+ selected at any given moment in time.
1431
+
1432
+ In order to group radio-buttons into a button group, we should
1433
+ first create a new instance of ButtonGroup, such as via:
1434
+
1435
+ button_group = ButtonGroup.new
1436
+
1437
+ Next, use the method <b>.add()</b> to add radio_buttons into that
1438
+ button group:
1439
+
1440
+ button_group.add(radio_button1)
1441
+ button_group.add(radio_button2)
1442
+
1443
+ The <b>API documentation</b> for <b>JRadioButton</b> can be seen here:
1444
+
1445
+ https://docs.oracle.com/javase/8/docs/api/javax/swing/JRadioButton.html
1446
+
1447
+ ## Java Swing Plaf
1448
+
1449
+ The javax.swing.plaf package contains several subpackages and related packages.
1450
+
1451
+ <b>Plaf</b> stands for <b>pluggable look and feel</b>.
1452
+
1453
+ ## Swing versus AWT
1454
+
1455
+ <b>Swing component</b> class names begin with a J. AWT components do
1456
+ not.
1457
+
1458
+ For instance, JButton is a swing-component whereas Button is an
1459
+ AWT component.
1460
+
1461
+ This distinction holds true for most components, but one exception
1462
+ is the <b>JComboBox</b>, which replaces the AWT Choice component.
1463
+
1464
+ The following table shows the AWT component and the nearest
1465
+ swing replacement:
1466
+
1467
+ AWT Component | Nearest Swing Replacement
1468
+ -------------------------------------------------
1469
+ Button | JButton
1470
+ Canvas | JPanel
1471
+ Checkbox | JCheckBox
1472
+ Checkbox in CheckboxGroup | JRadioButton in ButtonGroup
1473
+ Choice | JComboBox
1474
+ Component | JComponent
1475
+ Container | JPanel
1476
+ Label | JLabel
1477
+ List | JList
1478
+ Menu | JMenu
1479
+ MenuBar | JMenuBar
1480
+ MenuItem | JMenuItem
1481
+ Panel | JPanel
1482
+ PopupMenu | JPopupMenu
1483
+ Scrollbar | JScrollBar
1484
+ ScrollPane | JScrollPane
1485
+ TextArea | JTextArea
1486
+ TextField | JTextField
1487
+ Applet | JApplet
1488
+ Dialog | JDialog
1489
+ FileDialog | JFileChooser
1490
+ Frame | JFrame
1491
+ Window | JWindow
1492
+
1493
+ ## JPasswordField
1494
+
1495
+ JPasswordField is a specialized text field that can be used for inputting
1496
+ a password into a Swing-Application.
1497
+
1498
+ Cut and copy operations are not possible within this
1499
+ component, but text can be pasted into it.
1500
+
1501
+ On Windows it may look like this:
1502
+
1503
+ <img src="https://static.javatpoint.com/java/swing/images/java-jpasswardfield1.png" style="margin: 1em">
1504
+
1505
+ ## Potentially useful links pertaining to Java-Swing
1506
+
1507
+ https://web.mit.edu/6.005/www/sp14/psets/ps4/java-6-tutorial/components.html
1508
+ https://www.javatpoint.com/java-swing
1509
+
1510
+ CONTACT_INFORMATION