1 <!doctype html> 2 <html lang="en"> 3 <head> 4 <meta charset="utf-8"/> 5 <title>Using the Multiplexing Look and Feel</title> 6 </head> 7 <!-- 8 Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. 9 DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 10 11 This code is free software; you can redistribute it and/or modify it 12 under the terms of the GNU General Public License version 2 only, as 13 published by the Free Software Foundation. Oracle designates this 14 particular file as subject to the "Classpath" exception as provided 15 by Oracle in the LICENSE file that accompanied this code. 16 17 This code is distributed in the hope that it will be useful, but WITHOUT 18 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 20 version 2 for more details (a copy is included in the LICENSE file that 21 accompanied this code). 22 23 You should have received a copy of the GNU General Public License version 24 2 along with this work; if not, write to the Free Software Foundation, 25 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 26 27 Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 28 or visit www.oracle.com if you need additional information or have any 29 questions. 30 --> 31 32 <body> 33 <main role="main"> 34 <div class="contentContainer"> 35 <h1>Using the Multiplexing Look and Feel</h1> 36 37 <blockquote> 38 <hr> 39 <p> 40 <i> 41 This document is based on an article 42 originally published in 43 <a href="http://www.oracle.com/technetwork/java/javase/tech/articles-jsp-139072.html" 44 target="_top"><em>The Swing Connection</em></a>. 45 </i> 46 </p> 47 <hr> 48 </blockquote> 49 50 <p> 51 The Multiplexing look and feel lets 52 you supplement an ordinary look and feel 53 (called the <em>default</em> look and feel) 54 with one or more <em>auxiliary</em> look and feels. 55 For example, you could 56 simultaneously provide text-to-speech and Braille outputs, 57 in addition to the ordinary visual output that a Swing-based 58 application generates, 59 by adding 60 two auxiliary look and feels (one for text-to-speech, 61 the other for Braille) 62 to the default look and feel. 63 The default look and feel can be any ordinary look and feel -- 64 the Java or Windows look and feel, for example -- 65 and requires no modifications to work with auxiliary look and feels. 66 </p> 67 68 69 <p> 70 This document has the following sections: 71 <ul> 72 <li> <a href="#overview">Overview</a> 73 <li> <a href="#howtouse">How to Use Auxiliary Look and Feels</a> 74 <li> <a href="#howtowrite">Tips for Writing an Auxiliary Look and Feel</a> 75 <ul> 76 <li> <a href="#dosanddonts">Dos and Don'ts</a> 77 <li> <a href="#uidefaults">Extending UIDefaults</a> 78 <li> <a href="#defaultui">Examining Other UI Objects</a> 79 </ul> 80 <li> <a href="#implementation">How the Multiplexing Look and Feel is 81 Implemented</a> 82 <li> <a href="#custom">How to Provide a Custom Multiplexing 83 Look and Feel</a> 84 </ul> 85 86 <p> 87 Before reading further, you should be familiar 88 with the concept of pluggable look and feels. 89 For basic information, see 90 <a href="https://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html"> 91 How to Set the Look and Feel</a>, a section in <em>The Java Tutorial</em>. 92 For architectural details, you can read 93 <a 94 href="http://www.oracle.com/technetwork/java/architecture-142923.html#pluggable"> 95 Pluggable look-and-feel architecture</a>, a section within 96 a <em>Swing Connection</em> article. 97 </p> 98 99 <p> 100 <a id="overview"></a> 101 <hr> 102 <h2>Overview</h2> 103 104 <p> 105 106 The classes in the 107 <code>javax.swing.plaf.multi</code> package 108 implement a 109 <i>multiplexing look and feel</i>. 110 A multiplexing look and feel transparently creates -- and 111 simultaneously supports -- UI objects from several different look and feels 112 in response to a component requesting its UI object 113 (with the <code>getUI</code> method). 114 115 <p> 116 Without a multiplexing look and feel, a 117 developer who wanted to enhance a particular look and feel would 118 need to extend the classes supporting that look and feel. For example, to 119 add text-to-speech support to the Java look and feel without using a multiplexing 120 look and feel, the developer would need to create a group of 121 classes that extend those of 122 the Java look and feel, and add text-to-speech support to the new classes. 123 If the developer also wanted to add text-to-speech support to other look 124 and feels, 125 such as Motif or Windows, the developers would need to create subclasses 126 of those classes as well. 127 </p> 128 129 <p> 130 This approach has at least two shortcomings: 131 <ul> 132 <li>First, each subclass must use what is 133 essentially a copy of the same code, potentially creating a difficult 134 support situation for the developer.<br></li> 135 <li>Second, and more significantly for the 136 end user, some application developers might force a 137 particular look and feel to be used. When this approach is used, 138 the end user can't even use the enhanced look and feel.</li> 139 </ul> 140 141 <p> 142 A multiplexing look and feel 143 both these problems simultaneously because it allows multiple look 144 and feels to be combined. 145 The first problem (having to use what amounts to a second copy of the same 146 code) is solved because the developer can create a specialized look 147 and feel that can then be combined with other look and feels. 148 </p> 149 150 <p> 151 The second problem (having to force the use of 152 a particular look and feel) is solved because a specialized look and feel 153 can be used with whatever default look and feel the 154 application may have locked in place. 155 </p> 156 157 <p> 158 The default multiplexing look and feel implementation, 159 represented by the <code>MultiLookAndFeel</code> class 160 in the <code>javax.swing.plaf.multi</code> package, 161 is called (unsurprisingly) 162 the Multiplexing look and feel. 163 164 <p> 165 <a id="howtouse"></a> 166 <hr> 167 <h2>How to Use Auxiliary Look and Feels</h2> 168 169 <p> 170 It's easy to use auxiliary look and feels with Swing. To instruct 171 Swing to use the Multiplexing look and feel, all an application 172 has to do is modify the <code>$JDKHOME/conf/swing.properties</code> 173 file to include a definition of the <code>swing.auxiliarylaf</code> 174 property. Swing treats the <code>swing.auxiliarylaf</code> 175 property as a comma-separated list of <code>LookAndFeel</code> 176 subclasses that specify what auxiliary look and feels should be 177 used in addition to the default look and feel. If at least one valid 178 <code>LookAndFeel</code> 179 subclass is specified in the <code>swing.auxiliarylaf</code> 180 property, Swing automatically uses the Multiplexing look and feel 181 to load and support the default and auxiliary look and feels. 182 </p> 183 184 <p> 185 For example, let's assume that an application 186 makes use of a look and feel that supports text-to-speech feedback, and also 187 uses an look and feel that adds support for a device 188 that emits perfume. 189 Let's assume that the text-to-speech 190 look and feel is named <code>com.myco.TextTalkerLookAndFeel</code>, 191 and the look and feel that adds support for perfume 192 is named <code>com.smellco.OlfactoryLookAndFeel</code>. 193 </p> 194 195 <p> 196 To tell Swing to use both these look and feels 197 -- and to use a default look and feel at the same time -- your application 198 could simply add the following line to the <code>$JDKHOME/conf/swing.properties</code> file: 199 </p> 200 201 <p> 202 <code> 203 swing.auxiliarylaf=com.myco.TextTalkerLookAndFeel,<br> 204 com.smellco.OlfactoryLookAndFeel</code> 205 </p> 206 207 <p> 208 This statement tells Swing to obtain a component's UI from the Multiplexing 209 look and feel automatically, instead of obtaining it directly from 210 the default look and feel. The resulting multiplexing UI is a small 211 delegate that obtains and maintains UIs from the default and auxiliary 212 look and feels. As a result, when a method is invoked in a multiplexing 213 UI object, the multiplexing UI invokes the same method on each 214 of the UIs obtained from the default and auxiliary look and feels. 215 </p> 216 217 <p> 218 <a id="howtowrite"></a> 219 <hr> 220 <h2>Tips for Writing an Auxiliary Look and Feel</h2> 221 222 <p> 223 An auxiliary look and feel is like any other look and feel, 224 except that it doesn't have to provide the complete support 225 that a default look and feel must. For 226 example, an auxiliary look and feel that supports just text-to-speech feedback 227 doesn't need to provide any code for painting. 228 Also, it might not need to support all components -- 229 <code>JSeparator</code>s, for example, might be ignored. 230 231 <p> 232 Auxiliary look and feels tend to be simple, 233 so developing one can be easier than developing a visual 234 look and feel. 235 The developer can concentrate solely 236 on providing the specialized functionality. 237 238 <p> 239 Because the primary purpose of an auxiliary look and feel is to enhance the 240 default look and feel, auxiliary look and feels tend 241 be nonvisual. Since an auxiliary look and feel is a genuine 242 look and feel, however, there is nothing to prevent it 243 from rendering information on the display. 244 </p> 245 246 <p> 247 Just like for any other look and feel, you 248 implement an auxiliary look and feel 249 by writing a subclass of <code>javax.swing.LookAndFeel</code> 250 and creating subclasses of the 251 <code><em>Foo</em>UI</code> classes defined in 252 the <code>javax.swing.plaf</code> package. 253 </p> 254 255 <a id="dosanddonts"></a> 256 <h3>Dos and Don'ts</h3> 257 258 <p> 259 The following paragraphs provide some general recommendations for developing 260 auxiliary look and feels. 261 </p> 262 263 <h4>Use the <code>installUI</code> method 264 to perform all initialization, 265 and the <code>uninstallUI</code> method 266 to perform all cleanup.</h4> 267 268 <blockquote> 269 The <code>installUI</code> and <code>uninstallUI</code> 270 methods are invoked when a component's look and feel is set. 271 The <code>installUI</code> method gives the new UI object 272 a chance to add listeners on the component and its data model. 273 Similarly, the <code>uninstallUI</code> method 274 lets the previous UI object remove its listeners. 275 </blockquote> 276 <h4><b>Don't extend visual look and feels.</b></h4> 277 <blockquote> 278 We recommended that you <i>don't</i> implement 279 UI classes of an auxiliary look and feel as subclasses of the 280 UI classes of a visual look and feel. Why not? Because they might 281 accidentally inherit code that installs listeners on a component 282 object or renders the component on the display. As a result, 283 your auxiliary look and feel would compete with the default look 284 and feel rather than cooperating with it.<br> 285 <br> 286 Instead, we recommend that the UI classes of an auxiliary look 287 and feel directly extend the abstract UI classes in the <code>javax.swing.plaf</code> 288 package. By using this strategy, the developer of an auxiliary 289 look and feel can avoid competing with the default look and feel. 290 </blockquote> 291 <h4><b>Override all UI-specific methods your UI classes inherit.</b></h4> 292 293 <blockquote> 294 We recommend that each UI class of 295 an auxiliary look and feel override the methods 296 defined in the <code>javax.swing.plaf</code> 297 UI classes it descends from 298 The reasons for this recommendation are similar 299 to those for not extending a visual look and feel. 300 For example, the <code>ComponentUI</code> 301 class, from which all UI classes descend, 302 provides a default implementation for the <code>update</code> 303 method. This default implementation paints on the display 304 if the 305 component is opaque. If a UI class from a non-visual auxiliary 306 look and feel does not override this method, all 307 opaque components appear as blank areas on the screen! 308 </blockquote> 309 310 <a id="uidefaults"></a> 311 <h3>Extending UIDefaults</h3> 312 313 <p>In many cases, you 314 might want an auxiliary look and feel to be "incomplete." That 315 is, you might not need to support the complete set 316 of components. 317 For example, an auxiliary look and feel might choose 318 to provide a <code>ButtonUI</code> subclass but no 319 <code>LabelUI</code> subclass. 320 This 321 option is allowed, and the multiplexing look and feel gracefully 322 handles such situations.</p> 323 <p>By default, however, Swing issues an error message when it asks 324 a look and feel for a UI object and the look and feel does not 325 support that UI. This message can be annoying, especially to auxiliary 326 look-and-feel developers who don't want to support a particular 327 component.</p> 328 <p>Fortunately, you can prevent this error 329 message by creating a subclass of the <code>UIDefaults</code> 330 class and returning an instance of it from the 331 <code>getDefaults</code> method 332 of your <code>LookAndFeel</code> class. 333 For example: 334 </p> 335 <p><code>public class MyAuxLookAndFeel 336 extends LookAndFeel {<br> 337 ...<br> 338 public UIDefaults getDefaults() {<br> 339 <b>UIDefaults table = <br> 340 341 new MyAuxUIDefaults();<br> 342 </b> Object[] uiDefaults = {<br> 343 "ButtonUI", "MyAuxButtonUI",<br> 344 ...<br> 345 }<br> 346 table.putDefaults(uiDefaults);<br> 347 return table;<br> 348 }<br> 349 }<br> 350 <br> 351 <b>class MyAuxUIDefaults extends UIDefaults {<br> 352 protected void getUIError(String msg) {<br> 353 //System.err.println<br> 354 // ("An 355 annoying message!");<br> 356 }<br> 357 }</b></code></p> 358 359 <p> 360 In the preceding example, an auxiliary look and feel named <code>MyAux</code> 361 creates a <code>UIDefaults</code> subclass 362 that overrides the <code>getUIError</code> 363 method. The <code>getUIError</code> 364 method is the method that is invoked when Swing cannot find a UI 365 object in a look and feel. By merely doing nothing in this method, 366 you can avoid the error message.</p> 367 <p> 368 369 <a id="defaultui"></a> 370 <h3>Examining Other UI Objects</h3> 371 372 <p>In 373 rare instances, a UI object from an auxiliary look and feel 374 may be interested in the default UI object used by the component. In 375 these cases, the UI object from auxiliary look and feel can obtain 376 the UI from a component by calling its <code>getUI</code> 377 method. The returned UI is an instance of one of the multiplexing 378 look and feel UI classes (for example, <code>MultiButtonUI</code>). 379 The UI object from the auxiliary look and feel can call the <code>getUIs</code> 380 method of the returned object to obtain an array containing a complete list 381 of all UI objects handled by the multiplexing UI. The first element 382 is guaranteed to be the UI created from the default look and feel. 383 </p> 384 385 <p> 386 <a id="implementation"></a> 387 <hr> 388 <h2>How the Multiplexing Look and Feel Is Implemented</h2> 389 390 <p> 391 The Multiplexing look and feel 392 (represented by 393 <code>javax.swing.plaf.multi.MultiLookAndFeel</code>) 394 is meant to be transparent to 395 all developers and users. It should "just work" -- and 396 it is used only when the user tells Swing to use an auxiliary look 397 and feel.</p> 398 399 <p> 400 When the Multiplexing look and 401 feel is in use, the type of the UI object 402 associated with each component 403 depends on whether 404 any of the auxiliary look and feels currently in use 405 support the component. 406 If so, the component's UI object is 407 an instance of a multiplexing UI. 408 If only the default look and feel supports the component, 409 then the component gets 410 a UI object from the default look and feel, 411 just as if no auxiliary look and feels were installed. 412 413 <p> 414 A multiplexing UI object 415 obtains and maintains UI objects 416 from the default and auxiliary look 417 and feels, 418 referring to these UIs in the following manner: 419 420 <ul> 421 <li> The UI object from the default look 422 and feel is always the first to be created. After that, a UI object 423 is created from each auxiliary look and feel in the order 424 they are specified in the <code>swing.auxiliarylaf</code> 425 property.<br><br></li> 426 427 <li> When a method that requests information 428 from a UI object is invoked, the multiplexing UI object 429 invokes the method on all the UI objects, but returns 430 only the results from the UI for the default look and feel. 431 For example, when the <code>getPreferredSize</code> 432 method is invoked on a multiplexing UI, the UI returns only the 433 results of invoking <code>getPreferredSize</code> 434 on the UI obtained from the default look and feel. 435 The <code>getPreferredSize</code> method 436 is also invoked on the UI object for each auxiliary look and feel, 437 but the return values are ignored. 438 <br><br></li> 439 440 <li> When a method that does not request information 441 from the UI object is invoked, the multiplexing UI object 442 invokes that method on all UIs -- 443 on the UI object obtained from the default look 444 and feel 445 and on all the UIs obtained from the auxiliary look and feels, 446 as well. 447 For example, invoking the <code>installUI</code> 448 method on a multiplexing UI causes the multiplexing UI to invoke 449 <code>installUI</code> 450 on the UI obtained from the default look and feel and the UIs obtained from 451 the auxiliary factories.</li> 452 </ul> 453 <p> In all cases, the UI object obtained from 454 the default look and feel is acted upon first, and then the auxiliary 455 look and feels are acted upon in the order they are specified in 456 the <code>swing.auxiliarylaf</code> 457 property. 458 </p> 459 460 <p> 461 462 <a id="custom"></a> 463 <hr> 464 <h2>How to Provide a Custom Multiplexing Look and Feel</h2> 465 466 <p>While 467 we hope the behavior of the Multiplexing look and feel is 468 flexible enough not to require an alternative multiplexing look 469 and feel, Swing allows the user to specify another multiplexing look 470 and feel to use. 471 </p> 472 473 <p> To do that, all the user has to do is modify 474 the <code>$JDKHOME/conf/swing.properties</code> 475 file to include a definition of the <code>swing.plaf.multiplexinglaf</code> 476 property. Swing then treats the <code>swing.plaf.multiplexinglaf</code> 477 property as a <code>LookAndFeel</code> 478 subclass that supports multiplexing. 479 </p> 480 <p> For example, if a user has a multiplexing 481 look and feel represented by <code>com.myco.SuperMultiLookAndFeel</code> 482 that is a better match for their needs than the Multiplexing 483 look and feel 484 (<code>javax.swing.plaf.multi.MultiLookAndFeel</code>), 485 the user could include the following line in <code>$JDKHOME/conf/swing.properties</code>: 486 </p> 487 488 <p> 489 <code>swing.plaf.multiplexinglaf = com.myco.SuperMultiLookAndFeel</code> 490 </p> 491 492 <p> 493 This statement instructs Swing to use <code>com.myco.SuperMultiLookAndFeel</code> 494 instead of <code>javax.swing.plaf.multi.MultiLookAndFeel</code>. But 495 if you use this kind of statement, be careful, because the suppliers 496 of auxiliary look and feels will most likely have developed and 497 tested against our Multiplexing look and feel. 498 </p> 499 </div> 500 </main> 501 </body> 502 </html>