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