{"id":656,"date":"2017-11-02T15:35:38","date_gmt":"2017-11-02T15:35:38","guid":{"rendered":"https:\/\/devexperts.com\/blog\/?p=656"},"modified":"2022-05-18T10:54:09","modified_gmt":"2022-05-18T10:54:09","slug":"swing-oldie-but-goldie","status":"publish","type":"post","link":"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/","title":{"rendered":"SWING: Oldie But Goldie"},"content":{"rendered":"\n<p>No one&#8217;s talking Swing&#8217;s retirement &#8211; despite it being in its golden years. As you probably imagine, it is the most heavily used JAVA library for GUI creation. Which is well justified as Swing-based applications can be of any complexity and will look (and work!) the same when run on any OS. There\u2019s, of course, a price to pay: as your application becomes more complex and accumulates lots of custom graphics, you\u2019re bound to run into problems with performance and response speed.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/10\/swing.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"561\" src=\"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/10\/swing-1024x561.png\" alt=\"trading platform charting\" class=\"wp-image-657\" srcset=\"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/10\/swing-1024x561.png 1024w, https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/10\/swing-300x164.png 300w, https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/10\/swing-768x421.png 768w, https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/10\/swing.png 1707w\" sizes=\"auto, (max-width: 959px) calc(100vw - 30px), 870px\" \/><\/a><\/figure>\n\n\n\n<p>At Devexperts, we develop an application of this kind, which is a trading platform for brokers. With huge amounts of graphics in numerous windows, this application is designed for usage in multi-monitor configurations (see the screenshot below) \u2013 so you may be surprised to learn that its client is entirely Swing-based.<\/p>\n\n\n\n<p>Here, we\u2019ll be discussing what you should keep in mind when working with Swing. We\u2019ll also be sharing some tips and tricks to boost your application\u2019s performance.<\/p>\n\n\n\n<h2 id=\"h-sample-application\" class=\"wp-block-heading\">SAMPLE APPLICATION<\/h2>\n\n\n\n<p>To keep things simple, we\u2019ll be discussing all of our examples in the context of a really basic sample application, nothing too crazy. Since it is graphic interfaces that we&#8217;re gathered here for, we\u2019ll choose the application accordingly. Let\u2019s draw 500 rectangles of miscellaneous sizes and also a circle as a mouse cursor. Our very first implementation of this application will look like this:<\/p>\n\n\n\n<div class=\"oldCode\" style=\"background: #ffffff; overflow: auto; width: auto; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #bb0066; font-weight: bold;\">MouseCirclePaintingComponentForSlide<\/span> <span style=\"color: #008800; font-weight: bold;\">extends<\/span> JPanel <span style=\"color: #333333;\">{<\/span>\n  <span style=\"color: #008800; font-weight: bold;\">private<\/span> Point currentMousePoint <span style=\"color: #333333;\">=<\/span> <span style=\"color: #008800; font-weight: bold;\">new<\/span> Point<span style=\"color: #333333;\">(-<\/span><span style=\"color: #0000dd; font-weight: bold;\">1<\/span><span style=\"color: #333333;\">,<\/span> <span style=\"color: #333333;\">-<\/span><span style=\"color: #0000dd; font-weight: bold;\">1<\/span><span style=\"color: #333333;\">);<\/span>\n\n  MouseCirclePaintingComponentForSlide<span style=\"color: #333333;\">()<\/span> <span style=\"color: #333333;\">{<\/span>\n      addMouseMotionListener<span style=\"color: #333333;\">(<\/span><span style=\"color: #008800; font-weight: bold;\">new<\/span> MouseAdapter<span style=\"color: #333333;\">()<\/span> <span style=\"color: #333333;\">{<\/span>\n          <span style=\"color: #555555; font-weight: bold;\">@Override<\/span>\n          <span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #333399; font-weight: bold;\">void<\/span> <span style=\"color: #0066bb; font-weight: bold;\">mouseMoved<\/span><span style=\"color: #333333;\">(<\/span>MouseEvent e<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\n              currentMousePoint <span style=\"color: #333333;\">=<\/span> e<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getPoint<\/span><span style=\"color: #333333;\">();<\/span>\n              repaint<span style=\"color: #333333;\">();<\/span>\n          <span style=\"color: #333333;\">}<\/span>\n      <span style=\"color: #333333;\">});<\/span>\n  <span style=\"color: #333333;\">}<\/span>\n\n  <span style=\"color: #555555; font-weight: bold;\">@Override<\/span>\n  <span style=\"color: #008800; font-weight: bold;\">protected<\/span> <span style=\"color: #333399; font-weight: bold;\">void<\/span> <span style=\"color: #0066bb; font-weight: bold;\">paintComponent<\/span><span style=\"color: #333333;\">(<\/span>Graphics g<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\n      <span style=\"color: #008800; font-weight: bold;\">super<\/span><span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">paintComponent<\/span><span style=\"color: #333333;\">(<\/span>g<span style=\"color: #333333;\">);<\/span>\n      Graphics2D g2 <span style=\"color: #333333;\">=<\/span> <span style=\"color: #333333;\">(<\/span>Graphics2D<span style=\"color: #333333;\">)<\/span> g<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">create<\/span><span style=\"color: #333333;\">();<\/span>\n     \n      <span style=\"color: #888888;\">\/\/ paint 500 rectangles<\/span>\n      <span style=\"color: #888888;\">\/\/ paint mouse cursor<\/span>\n\n      g2<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">dispose<\/span><span style=\"color: #333333;\">();<\/span>\n  <span style=\"color: #333333;\">}<\/span>\n<span style=\"color: #333333;\">}<\/span>\n<\/pre>\n<\/div>\n\n\n\n<p>Launching this application on an average machine will most definitely result in the following:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/10\/1_first_slow.gif\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"768\" src=\"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/10\/1_first_slow.gif\" alt=\"sample application\" class=\"wp-image-664\"\/><\/a><\/figure>\n\n\n\n<p>The first thing you see is the lag between the mouse movement and the rendering of the circle. While it\u2019s not exactly rocket science to find out the reason behind the lagging (spoiler: 500 rectangles, Carl!), let\u2019s pretend the application is complex and this reason is yet to be revealed. In real life, we might as well collect metrics upon each release to see if the lagging situation has worsened in our most recent build. Which is why the number one thing to be discussed here is measuring performance of the drawing code.<\/p>\n\n\n\n<h2 id=\"h-to-the-profiler\" class=\"wp-block-heading\">TO THE PROFILER!<\/h2>\n\n\n\n<p>One can expect that the most basic and obvious approach is to measure the runtime of the paintComponent method. What could possibly go wrong here? Let\u2019s see! A sample code could be something like this:<\/p>\n\n\n\n<div class=\"oldCode\" style=\"background: #ffffff; overflow: auto; width: auto; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #555555; font-weight: bold;\">@Override<\/span>\n<span style=\"color: #008800; font-weight: bold;\">protected<\/span> <span style=\"color: #333399; font-weight: bold;\">void<\/span> <span style=\"color: #0066bb; font-weight: bold;\">paintComponent<\/span><span style=\"color: #333333;\">(<\/span>Graphics g<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\n\t<span style=\"color: #008800; font-weight: bold;\">super<\/span><span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">paintComponent<\/span><span style=\"color: #333333;\">(<\/span>g<span style=\"color: #333333;\">);<\/span>\n\t<span style=\"color: #333399; font-weight: bold;\">long<\/span> start <span style=\"color: #333333;\">=<\/span> System<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">nanoTime<\/span><span style=\"color: #333333;\">();<\/span>\n\n\t<span style=\"color: #888888;\">\/\/ paint rectangles here<\/span>\n\n\t<span style=\"color: #333399; font-weight: bold;\">long<\/span> elapsed <span style=\"color: #333333;\">=<\/span> System<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">nanoTime<\/span><span style=\"color: #333333;\">()<\/span> <span style=\"color: #333333;\">-<\/span> start<span style=\"color: #333333;\">;<\/span>\n\tSystem<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">out<\/span><span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">println<\/span><span style=\"color: #333333;\">(<\/span><span style=\"background-color: #fff0f0;\">\"paintComponent: \"<\/span> <span style=\"color: #333333;\">+<\/span> TimeUnit<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">NANOSECONDS<\/span><span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">toMillis<\/span><span style=\"color: #333333;\">(<\/span>elapsed<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">+<\/span> <span style=\"background-color: #fff0f0;\">\" ms\"<\/span><span style=\"color: #333333;\">);<\/span>\n<span style=\"color: #333333;\">}<\/span>\n<\/pre>\n<\/div>\n\n\n\n<p>Everything\u2019s cool, we\u2019ve done this before like thousand times. Launching the application, we\u2019ll see the following:<\/p>\n\n\n<pre><code class='codeBlock nohighlight'><br \/>\npaintComponent: 0 ms<br \/>\npaintComponent: 0 ms<br \/>\npaintComponent: 0 ms<br \/>\npaintComponent: 0 ms<br \/>\npaintComponent: 0 ms<br \/>\npaintComponent: 0 ms<br \/>\npaintComponent: 0 ms<br \/>\npaintComponent: 0 ms<\/code><\/pre>\n\n\n\n<p>The figures are at least confusing. Are the rectangles really being drawn this fast? We\u2019re having a hard time believing that, considering the obvious cursor lagging! Let\u2019s see what\u2019s in the profiler then.<\/p>\n\n\n\n<p>Having our application profiled, we\u2019re getting curious results: AWT is just completely idle! What is going on here? To answer this question, we might as well take a look at the profiler once again. In the thread monitoring charts, you can see this D3D Screen Updater thread working on something while the AWT is inactive. Dig this a bit deeper and you will see that AWT is not just being inactive, it is waiting for something. And this something happens to be D3D.<\/p>\n\n\n\n<p>Here, a brief digression is needed: you will not see this AWT-D3D thing on every single machine (not to mention you can only see D3D on Windows). It\u2019s also possible that based on your hardware parameters, you cannot observe any extra threads at all \u2013 but that\u2019s more of an exception.<\/p>\n\n\n\n<p>So, back to our question \u2013 what is really going on with these threads? The thing is, when you\u2019re executing a painting method like drawLine or drawRect \u2013 drawing isn\u2019t really happening. Swing is trying to enable hardware acceleration \u2013 which, in this case, is D3D \u2013 and when painting methods are called, commands are recorded to a special buffer (RenderBuffer). The drawing, on the other hand, is completed a bit later, at the moment the Repaint Manager completes the drawing cycle of the image command copy on the screen. This is also the moment the control is passed on to the D3D thread, which executes all of the commands stored in the buffer. Which means the AWT will be waiting until D3D is finished.<\/p>\n\n\n\n<h2 id=\"h-measuring-101\" class=\"wp-block-heading\">MEASURING 101<\/h2>\n\n\n\n<p>So, how do we measure the method execution time? There are actually several ways to do so. First is simply turning off the hardware acceleration using the corresponding flag. This will force Java to independently do the drawing in AWT. Of course, it\u2019s not exactly a straightforward measuring method, but it will allow us to at least measure some of the relative metrics. For example, we\u2019ll be able to define how slowly a component is drawn compared to another component. The profiler will also show real data. Now we see that the entire time is spent on drawing the rectangles.<\/p>\n\n\n\n<p>As an alternative, we can measure execution time of the paintImmediately method.<\/p>\n\n\n\n<p>There are other means of profiling that do not require turning off the hardware acceleration. These are not always precise (when measuring a single component) and are more suitable for evaluation of the overall response of an application or when comparing a new build with a previous. Long story short, they may prove quite useful in a complex application.<\/p>\n\n\n\n<p>Let\u2019s kick off with a technique that is redefining the standard repaintManager and logging the execution time of the paintDirtyRegions method. An advantage of this approach is that it allows us to get the exact metric of each iteration in AWT (including the D3D waiting time). On the other hand, its coverage is so large that we can\u2019t really determine which component takes the most time to be drawn.<\/p>\n\n\n\n<p>Up next: a substitute for EventQueue. If we replace EventQueue with a custom queue, we\u2019ll be free to redefine the dispatchEvent method and measure the execution time of each event in the queue. In addition, this will allow us to measure the delay before execution for some of the events.&nbsp; As a rule of thumb, this can be done for an event that has the getTime method that returns this particular event&#8217;s creation timestamp. Basically, these are mouse events, repainting events, and some others. Repainting events in this queue are generally represented by the InvocationEvent class. Sometimes this class represents other events, but on the whole, it does not affect the measurements.<\/p>\n\n\n\n<p>So, here&#8217;s the most basic example of such a queue.<\/p>\n\n\n\n<div class=\"oldCode\" style=\"background: #ffffff; overflow: auto; width: auto; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #bb0066; font-weight: bold;\">MonitoringEventQueue<\/span> <span style=\"color: #008800; font-weight: bold;\">extends<\/span> EventQueue <span style=\"color: #333333;\">{<\/span>\n  <span style=\"color: #555555; font-weight: bold;\">@Override<\/span>\n  <span style=\"color: #008800; font-weight: bold;\">protected<\/span> <span style=\"color: #333399; font-weight: bold;\">void<\/span> <span style=\"color: #0066bb; font-weight: bold;\">dispatchEvent<\/span><span style=\"color: #333333;\">(<\/span>AWTEvent event<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\n      <span style=\"color: #008800; font-weight: bold;\">if<\/span> <span style=\"color: #333333;\">(<\/span>event <span style=\"color: #008800; font-weight: bold;\">instanceof<\/span> InvocationEvent<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\n          InvocationEvent invocationEvent <span style=\"color: #333333;\">=<\/span> <span style=\"color: #333333;\">(<\/span>InvocationEvent<span style=\"color: #333333;\">)<\/span> event<span style=\"color: #333333;\">;<\/span>\n          <span style=\"color: #333399; font-weight: bold;\">long<\/span> waitingInQueueTime <span style=\"color: #333333;\">=<\/span> System<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">currentTimeMillis<\/span><span style=\"color: #333333;\">()<\/span> <span style=\"color: #333333;\">-<\/span> invocationEvent<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getWhen<\/span><span style=\"color: #333333;\">();<\/span>\n          System<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">out<\/span><span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">println<\/span><span style=\"color: #333333;\">(<\/span><span style=\"background-color: #fff0f0;\">\"In queue: \"<\/span> <span style=\"color: #333333;\">+<\/span> waitingInQueueTime <span style=\"color: #333333;\">+<\/span> <span style=\"background-color: #fff0f0;\">\"ms\"<\/span> <span style=\"color: #333333;\">+<\/span> <span style=\"background-color: #fff0f0;\">\" : \"<\/span> <span style=\"color: #333333;\">+<\/span> event<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">toString<\/span><span style=\"color: #333333;\">());<\/span>\n      <span style=\"color: #333333;\">}<\/span>\n      <span style=\"color: #333399; font-weight: bold;\">long<\/span> start <span style=\"color: #333333;\">=<\/span> System<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">nanoTime<\/span><span style=\"color: #333333;\">();<\/span>\n      <span style=\"color: #008800; font-weight: bold;\">super<\/span><span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">dispatchEvent<\/span><span style=\"color: #333333;\">(<\/span>event<span style=\"color: #333333;\">);<\/span>\n      <span style=\"color: #333399; font-weight: bold;\">long<\/span> elapsed <span style=\"color: #333333;\">=<\/span> System<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">nanoTime<\/span><span style=\"color: #333333;\">()<\/span> <span style=\"color: #333333;\">-<\/span> start<span style=\"color: #333333;\">;<\/span>\n      System<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">out<\/span><span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">println<\/span><span style=\"color: #333333;\">(<\/span><span style=\"background-color: #fff0f0;\">\"dispatchEvent: \"<\/span> <span style=\"color: #333333;\">+<\/span> TimeUnit<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">NANOSECONDS<\/span><span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">toMillis<\/span><span style=\"color: #333333;\">(<\/span>elapsed<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">+<\/span> <span style=\"background-color: #fff0f0;\">\" ms\"<\/span><span style=\"color: #333333;\">);<\/span>\n  <span style=\"color: #333333;\">}<\/span>\n<span style=\"color: #333333;\">}<\/span>\n<\/pre>\n<\/div>\n\n\n\n<p>This approach is efficient and convenient, especially when you have to measure the overall response of an application \u2013 and it allows freeze capturing! For example, you can message the user in case some event has spent too much time on the queue.<\/p>\n\n\n\n<p>We use this approach at Devexperts in performance testing of each new version of the UI client.<\/p>\n\n\n\n<h2 id=\"h-optimizations-back-to-classics\" class=\"wp-block-heading\">OPTIMIZATIONS: BACK TO CLASSICS<\/h2>\n\n\n\n<p>So, we have somewhat successfully measured the performance, it&#8217;s time to go back to our initial problem: how to optimize the sample application so the cursor lagging is removed? We know that in our case the slowness is blatant when drawing the rectangles. By the way, in most of the cases, it is simple rendering operations that appear to be the bottleneck.<\/p>\n\n\n\n<p>Let&#8217;s look closely at the code of the mouse handler. Is there a problem with it? It&#8217;s well evident that the cursor is only 20 pixels, but we\u2019re still repainting the entire component.<\/p>\n\n\n\n<p>That&#8217;s costly!&nbsp; Calling the repaint method without specifying the repainting area is a common mistake in many Swing-based applications. Let&#8217;s re-write the code so it only repaints the necessary areas. Basically, we only need to repaint the region the cursor was initially at and the region it went to. Yes, it&#8217;s that simple.<\/p>\n\n\n\n<div class=\"oldCode\" style=\"background: #ffffff; overflow: auto; width: auto; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #555555; font-weight: bold;\">@Override<\/span>\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #333399; font-weight: bold;\">void<\/span> <span style=\"color: #0066bb; font-weight: bold;\">mouseMoved<\/span><span style=\"color: #333333;\">(<\/span>MouseEvent e<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\n  currentMousePoint <span style=\"color: #333333;\">=<\/span> e<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getPoint<\/span><span style=\"color: #333333;\">();<\/span>\n  repaint<span style=\"color: #333333;\">(<\/span>lastPaintedPoint<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">x<\/span> <span style=\"color: #333333;\">-<\/span> <span style=\"color: #0000dd; font-weight: bold;\">15<\/span><span style=\"color: #333333;\">,<\/span> lastPaintedPoint<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">y<\/span> <span style=\"color: #333333;\">-<\/span> <span style=\"color: #0000dd; font-weight: bold;\">15<\/span><span style=\"color: #333333;\">,<\/span> <span style=\"color: #0000dd; font-weight: bold;\">30<\/span> <span style=\"color: #333333;\">,<\/span> <span style=\"color: #0000dd; font-weight: bold;\">30<\/span><span style=\"color: #333333;\">);<\/span>\n  repaint<span style=\"color: #333333;\">(<\/span>currentMousePoint<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">x<\/span> <span style=\"color: #333333;\">-<\/span> <span style=\"color: #0000dd; font-weight: bold;\">15<\/span><span style=\"color: #333333;\">,<\/span> currentMousePoint<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">y<\/span> <span style=\"color: #333333;\">-<\/span> <span style=\"color: #0000dd; font-weight: bold;\">15<\/span><span style=\"color: #333333;\">,<\/span> <span style=\"color: #0000dd; font-weight: bold;\">30<\/span><span style=\"color: #333333;\">,<\/span> <span style=\"color: #0000dd; font-weight: bold;\">30<\/span><span style=\"color: #333333;\">);<\/span>\n<span style=\"color: #333333;\">}<\/span>\n<\/pre>\n<\/div>\n\n\n\n<p>Having launched the application, we see that the performance has dramatically increased. A great thing about this approach is that we don&#8217;t even have to check clipBounds in the painting code (in the current implementation). The graphics can easily detect that we&#8217;re trying to draw rectangles and spend no extra time on that. On a side note though, clipBounds should always be taken into account whenever it&#8217;s possible.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/10\/2_repaintEffective.gif\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"768\" src=\"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/10\/2_repaintEffective.gif\" alt=\"Swing-based applications\" class=\"wp-image-667\"\/><\/a><\/figure>\n\n\n\n<p>Let&#8217;s make our example a bit more complex. What if we need to visualize the cursor position with crosshairs, not a circle? Let&#8217;s see&#8230; Using the same optimization as we did in the circle example will not result in any performance enhancements. It\u2019s going to keep lagging as it did before.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/10\/3_crossSlow.gif\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"768\" src=\"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/10\/3_crossSlow.gif\" alt=\"crosshairs\" class=\"wp-image-668\"\/><\/a><figcaption> <\/figcaption><\/figure>\n\n\n\n<p>The thing is that when calling repaint, no painting is happening and RepaintManager only records the dirty region. It also does Region extension, which is, in fact, merging several dirty regions into a single larger one. Although it has worked for the circles, crosshairs are a bit more complicated as merging the horizontal and the vertical line takes the entire display. It&#8217;s a shame, what should we do then? One of the possible options is using our own back buffer. If we once render the rectangles there and then just copy those upon each rendering, it would take much less time than drawing 500 rectangles. However, we&#8217;re not going to be contemplating this approach now. Let&#8217;s see what other options we have.<\/p>\n\n\n\n<h2 id=\"h-synchronous-painting\" class=\"wp-block-heading\">SYNCHRONOUS PAINTING<\/h2>\n\n\n\n<p>As the matter of fact, the problem of the repaint method is not just merging the repaint regions. We may also face a problem in it being asynchronous, which results in the repainting event finding itself in the queue so a small lag is inevitable. If the queue also contains other events, this lag increases. Wouldn&#8217;t it be nice if we could repaint the mouse cursor immediately in the mouse event handler? And we do have means for that! In Swing, there is an option of calling the paintImmediately method on the component.&nbsp; When calling this method, the painting of the component is immediately done. Also, when calling this method multiple times, repaint regions are not merged. Now let&#8217;s use this approach in our code:<\/p>\n\n\n\n<div class=\"oldCode\" style=\"background: #ffffff; overflow: auto; width: auto; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #555555; font-weight: bold;\">@Override<\/span>\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #333399; font-weight: bold;\">void<\/span> <span style=\"color: #0066bb; font-weight: bold;\">mouseMoved<\/span><span style=\"color: #333333;\">(<\/span>MouseEvent e<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\n  currentMousePoint <span style=\"color: #333333;\">=<\/span> e<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getPoint<\/span><span style=\"color: #333333;\">();<\/span>\n  <span style=\"color: #888888;\">\/\/ erase old<\/span>\n  paintImmediately<span style=\"color: #333333;\">(<\/span><span style=\"color: #0000dd; font-weight: bold;\">0<\/span><span style=\"color: #333333;\">,<\/span> lastPaintedPoint<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">y<\/span><span style=\"color: #333333;\">,<\/span> getWidth<span style=\"color: #333333;\">(),<\/span> <span style=\"color: #0000dd; font-weight: bold;\">1<\/span> <span style=\"color: #333333;\">);<\/span>\n  paintImmediately<span style=\"color: #333333;\">(<\/span>lastPaintedPoint<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">x<\/span><span style=\"color: #333333;\">,<\/span> <span style=\"color: #0000dd; font-weight: bold;\">0<\/span><span style=\"color: #333333;\">,<\/span> <span style=\"color: #0000dd; font-weight: bold;\">1<\/span><span style=\"color: #333333;\">,<\/span> getHeight<span style=\"color: #333333;\">());<\/span>\n  <span style=\"color: #888888;\">\/\/ paint new<\/span>\n  paintImmediately<span style=\"color: #333333;\">(<\/span><span style=\"color: #0000dd; font-weight: bold;\">0<\/span><span style=\"color: #333333;\">,<\/span> currentMousePoint<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">y<\/span><span style=\"color: #333333;\">,<\/span> getWidth<span style=\"color: #333333;\">(),<\/span> <span style=\"color: #0000dd; font-weight: bold;\">1<\/span><span style=\"color: #333333;\">);<\/span>\n  paintImmediately<span style=\"color: #333333;\">(<\/span>currentMousePoint<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">x<\/span><span style=\"color: #333333;\">,<\/span> <span style=\"color: #0000dd; font-weight: bold;\">0<\/span><span style=\"color: #333333;\">,<\/span> <span style=\"color: #0000dd; font-weight: bold;\">1<\/span><span style=\"color: #333333;\">,<\/span> getHeight<span style=\"color: #333333;\">());<\/span>\n<span style=\"color: #333333;\">}<\/span>\n<\/pre>\n<\/div>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/10\/4_CrossPaintImediatlty.gif\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"768\" src=\"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/10\/4_CrossPaintImediatlty.gif\" alt=\"CrossPaintImmediately\" class=\"wp-image-669\"\/><\/a><\/figure>\n\n\n\n<p>Launch to see that the lag has sufficiently decreased and the application works much faster. However, we need to take into account that we&#8217;re calling the same painting code several times with different repaint regions. This is why it&#8217;s crucial that we also make the code take into account the region so no extra operations are performed. In our example we&#8217;re not doing this for the sake of keeping things simple.<\/p>\n\n\n\n<p>The synchronous painting approach does have a multitude of advantages, but we can observe some drawbacks as well:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>The paintImmediately method should always be called in AWT, which is not the case with the repaint method<\/li><li>Upon calling this method each time, many things happen, including double buffering. Given we call it four times in our example, the overhead is quite serious.<\/li><li>Generally, the painting code when using this approach is more complicated as we need to account for the repainting regions. Although in the perfect world, this should always be done, whatever the approach is.<\/li><\/ol>\n\n\n\n<p>In fact, we should be concerned the most about the drawback #2. Can we actually avoid calling such a heavy method four times? It seems that we can!<\/p>\n\n\n\n<h2 id=\"h-time-to-get-active\" class=\"wp-block-heading\"><strong>TIME TO GET ACTIVE<\/strong><\/h2>\n\n\n\n<p>Active painting is an interesting solution to our problem. First off, why is it called active? Well, that&#8217;s because we&#8217;re now painting by ourselves directly on-screen, controlling the entire process. Thankfully, Swing gives us this opportunity. To do so, we can use the getGraphics method present in each of the Swing components so we paint avoiding any other Swing mechanisms. Of course, the burden of the painting optimization is now ours to take, but we&#8217;ll happily take it, won&#8217;t we? There are several special things about this approach that are worth mentioning:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>The getGraphics method may return null, so before we start taking any actions, we&#8217;d better ensure that the object exists.<\/li><li>We&#8217;re going to paint directly into the screen buffer of the component, meaning above anything painted there by Swing itself. That&#8217;s why we&#8217;ll have to address the problem of cleaning out and repainting of the necessary component region. This also means that we can paint something extra incrementally.<\/li><li>The paintComponent methods can be called by the framework even without our participation (e.g., upon the OS request) so everything you paint should be duplicated there (of course, only if you absolutely need it). When drawing the crosshairs, it may not be obligatory, but it&#8217;s still worth remembering.<\/li><\/ol>\n\n\n\n<p>Taking all of this into account, let\u2019s re-write our example. Since we need to restore the image after each crosshairs rendering, we&#8217;ll record the image in our own buffer to avoid many complications.<\/p>\n\n\n\n<div class=\"oldCode\" style=\"background: #ffffff; overflow: auto; width: auto; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\">addMouseMotionListener<span style=\"color: #333333;\">(<\/span><span style=\"color: #008800; font-weight: bold;\">new<\/span> MouseAdapter<span style=\"color: #333333;\">()<\/span> <span style=\"color: #333333;\">{<\/span>\n  <span style=\"color: #555555; font-weight: bold;\">@Override<\/span>\n  <span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #333399; font-weight: bold;\">void<\/span> <span style=\"color: #0066bb; font-weight: bold;\">mouseMoved<\/span><span style=\"color: #333333;\">(<\/span>MouseEvent e<span style=\"color: #333333;\">)<\/span> <span style=\"color: #333333;\">{<\/span>\n      Point mousePointNow <span style=\"color: #333333;\">=<\/span> MouseInfo<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getPointerInfo<\/span><span style=\"color: #333333;\">().<\/span><span style=\"color: #0000cc;\">getLocation<\/span><span style=\"color: #333333;\">();<\/span>\n      SwingUtilities<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">convertPointFromScreen<\/span><span style=\"color: #333333;\">(<\/span>mousePointNow<span style=\"color: #333333;\">,<\/span> MouseCrossActivePaintingComponent<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">this<\/span><span style=\"color: #333333;\">);<\/span>\n\n      Graphics graphics <span style=\"color: #333333;\">=<\/span> MouseCrossActivePaintingComponent<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">this<\/span><span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getGraphics<\/span><span style=\"color: #333333;\">();<\/span>\n      <span style=\"color: #008800; font-weight: bold;\">if<\/span> <span style=\"color: #333333;\">(<\/span>graphics <span style=\"color: #333333;\">==<\/span> <span style=\"color: #008800; font-weight: bold;\">null<\/span><span style=\"color: #333333;\">)<\/span>\n          <span style=\"color: #008800; font-weight: bold;\">return<\/span><span style=\"color: #333333;\">;<\/span>\n      Graphics2D g2 <span style=\"color: #333333;\">=<\/span> <span style=\"color: #333333;\">(<\/span>Graphics2D<span style=\"color: #333333;\">)<\/span> graphics<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">create<\/span><span style=\"color: #333333;\">();<\/span>\n\n      <span style=\"color: #888888;\">\/\/ erase previous cross by restoring rectangles from image<\/span>\n      g2<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">drawImage<\/span><span style=\"color: #333333;\">(<\/span>backBuffer<span style=\"color: #333333;\">,<\/span> <span style=\"color: #0000dd; font-weight: bold;\">0<\/span><span style=\"color: #333333;\">,<\/span> <span style=\"color: #0000dd; font-weight: bold;\">0<\/span><span style=\"color: #333333;\">,<\/span> <span style=\"color: #008800; font-weight: bold;\">null<\/span><span style=\"color: #333333;\">);<\/span>\n\n      g2<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">setColor<\/span><span style=\"color: #333333;\">(<\/span>Color<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">BLUE<\/span><span style=\"color: #333333;\">);<\/span>\n      g2<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">drawLine<\/span><span style=\"color: #333333;\">(<\/span><span style=\"color: #0000dd; font-weight: bold;\">0<\/span><span style=\"color: #333333;\">,<\/span> currentMousePoint<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">y<\/span><span style=\"color: #333333;\">,<\/span> getWidth<span style=\"color: #333333;\">(),<\/span> currentMousePoint<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">y<\/span><span style=\"color: #333333;\">);<\/span>\n      g2<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">drawLine<\/span><span style=\"color: #333333;\">(<\/span>currentMousePoint<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">x<\/span><span style=\"color: #333333;\">,<\/span> <span style=\"color: #0000dd; font-weight: bold;\">0<\/span><span style=\"color: #333333;\">,<\/span> currentMousePoint<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">x<\/span><span style=\"color: #333333;\">,<\/span> getHeight<span style=\"color: #333333;\">());<\/span>\n\n      lastPaintedPoint <span style=\"color: #333333;\">=<\/span> currentMousePoint<span style=\"color: #333333;\">;<\/span>\n      g2<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">dispose<\/span><span style=\"color: #333333;\">();<\/span>\n      Toolkit<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getDefaultToolkit<\/span><span style=\"color: #333333;\">().<\/span><span style=\"color: #0000cc;\">sync<\/span><span style=\"color: #333333;\">();<\/span>\n  <span style=\"color: #333333;\">}<\/span>\n<span style=\"color: #333333;\">});<\/span>\n<\/pre>\n<\/div>\n\n\n\n<p>In the above case you may notice that we get the mouse position from the MouseInfo class, not from the event. This little trick lets us further decrease the lag of the cursor from the real mouse position. The coordinates recorded in the event might differ from the real ones because the event has already spent some time in the queue before being handled.<\/p>\n\n\n\n<p>Now the cursor lag is completely eliminated.<\/p>\n\n\n\n<h2 id=\"h-summing-it-all-up\" class=\"wp-block-heading\">SUMMING IT ALL UP<\/h2>\n\n\n\n<p>Our discussion has only covered a small (yet important) part of nuances specific to working with Swing. A real-life application is likely to include tables, lists, trees, etc., in addition to the custom graphics we\u2019ve taken a short dive into. No matter how hard we try, fitting specifics of these controls into a single article is next to impossible. But here\u2019s a thing to remember: the total performance of an application depends on that of its elements. If there is an element that lags behind, there\u2019s no way others will catch up.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>No one&#8217;s talking Swing&#8217;s retirement &#8211; despite it being in its golden years. As you probably imagine, it is the &hellip; <\/p>\n","protected":false},"author":39,"featured_media":1614,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2020],"tags":[36],"class_list":["post-656","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-fintech","tag-development"],"acf":{"nifty_post_card_image":null,"nifty_post_card_index_big":null,"nifty_post_inner_image":null,"nifty_post_card_banner":null},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.2 (Yoast SEO v27.2) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>SWING Java Library: Oldie But Goldie \u2013 Devexperts Blog<\/title>\n<meta name=\"description\" content=\"Swing is the most heavily used Java library for GUI creation. We show how to overcome issues when having multiple graphic elements in the UI.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"SWING: Oldie But Goldie\" \/>\n<meta property=\"og:description\" content=\"Swing is the most heavily used Java library for GUI creation. We show how to overcome issues when having multiple graphic elements in the UI.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/\" \/>\n<meta property=\"og:site_name\" content=\"Devexperts Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/devexperts\/\" \/>\n<meta property=\"article:published_time\" content=\"2017-11-02T15:35:38+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-05-18T10:54:09+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/11\/green-full.png\" \/>\n\t<meta property=\"og:image:width\" content=\"3840\" \/>\n\t<meta property=\"og:image:height\" content=\"700\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Sergey Lukashevich\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@devexperts\" \/>\n<meta name=\"twitter:site\" content=\"@devexperts\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Sergey Lukashevich\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"20 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":[\"Article\",\"BlogPosting\"],\"@id\":\"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/\"},\"author\":{\"name\":\"Sergey Lukashevich\"},\"headline\":\"SWING: Oldie But Goldie\",\"datePublished\":\"2017-11-02T15:35:38+00:00\",\"dateModified\":\"2022-05-18T10:54:09+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/\"},\"wordCount\":2318,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/devexperts.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/11\/green-full.png\",\"keywords\":[\"development\"],\"articleSection\":[\"Fintech\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/\",\"url\":\"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/\",\"name\":\"SWING Java Library: Oldie But Goldie \u2013 Devexperts Blog\",\"isPartOf\":{\"@id\":\"https:\/\/devexperts.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/11\/green-full.png\",\"datePublished\":\"2017-11-02T15:35:38+00:00\",\"dateModified\":\"2022-05-18T10:54:09+00:00\",\"description\":\"Swing is the most heavily used Java library for GUI creation. We show how to overcome issues when having multiple graphic elements in the UI.\",\"breadcrumb\":{\"@id\":\"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/#primaryimage\",\"url\":\"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/11\/green-full.png\",\"contentUrl\":\"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/11\/green-full.png\",\"width\":3840,\"height\":700},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/devexperts.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"SWING: Oldie But Goldie\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/devexperts.com\/blog\/#website\",\"url\":\"https:\/\/devexperts.com\/blog\/\",\"name\":\"Devexperts Blog\",\"description\":\"We make complex finance ideas on technology, innovation and business simple\",\"publisher\":{\"@id\":\"https:\/\/devexperts.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/devexperts.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/devexperts.com\/blog\/#organization\",\"name\":\"Devexperts LLC\",\"url\":\"https:\/\/devexperts.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/devexperts.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/devexperts.com\/blog\/app\/uploads\/2019\/08\/DX-logo.png\",\"contentUrl\":\"https:\/\/devexperts.com\/blog\/app\/uploads\/2019\/08\/DX-logo.png\",\"width\":167,\"height\":30,\"caption\":\"Devexperts LLC\"},\"image\":{\"@id\":\"https:\/\/devexperts.com\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/devexperts\/\",\"https:\/\/x.com\/devexperts\",\"https:\/\/www.linkedin.com\/company\/devexperts\",\"https:\/\/www.youtube.com\/channel\/UCF3FRmes2KrcVsTXQ1aAB5w\/featured\"]}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"SWING Java Library: Oldie But Goldie \u2013 Devexperts Blog","description":"Swing is the most heavily used Java library for GUI creation. We show how to overcome issues when having multiple graphic elements in the UI.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/","og_locale":"en_US","og_type":"article","og_title":"SWING: Oldie But Goldie","og_description":"Swing is the most heavily used Java library for GUI creation. We show how to overcome issues when having multiple graphic elements in the UI.","og_url":"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/","og_site_name":"Devexperts Blog","article_publisher":"https:\/\/www.facebook.com\/devexperts\/","article_published_time":"2017-11-02T15:35:38+00:00","article_modified_time":"2022-05-18T10:54:09+00:00","og_image":[{"width":3840,"height":700,"url":"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/11\/green-full.png","type":"image\/png"}],"author":"Sergey Lukashevich","twitter_card":"summary_large_image","twitter_creator":"@devexperts","twitter_site":"@devexperts","twitter_misc":{"Written by":"Sergey Lukashevich","Est. reading time":"20 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":["Article","BlogPosting"],"@id":"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/#article","isPartOf":{"@id":"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/"},"author":{"name":"Sergey Lukashevich"},"headline":"SWING: Oldie But Goldie","datePublished":"2017-11-02T15:35:38+00:00","dateModified":"2022-05-18T10:54:09+00:00","mainEntityOfPage":{"@id":"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/"},"wordCount":2318,"commentCount":0,"publisher":{"@id":"https:\/\/devexperts.com\/blog\/#organization"},"image":{"@id":"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/#primaryimage"},"thumbnailUrl":"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/11\/green-full.png","keywords":["development"],"articleSection":["Fintech"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/","url":"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/","name":"SWING Java Library: Oldie But Goldie \u2013 Devexperts Blog","isPartOf":{"@id":"https:\/\/devexperts.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/#primaryimage"},"image":{"@id":"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/#primaryimage"},"thumbnailUrl":"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/11\/green-full.png","datePublished":"2017-11-02T15:35:38+00:00","dateModified":"2022-05-18T10:54:09+00:00","description":"Swing is the most heavily used Java library for GUI creation. We show how to overcome issues when having multiple graphic elements in the UI.","breadcrumb":{"@id":"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/#primaryimage","url":"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/11\/green-full.png","contentUrl":"https:\/\/devexperts.com\/blog\/app\/uploads\/2017\/11\/green-full.png","width":3840,"height":700},{"@type":"BreadcrumbList","@id":"https:\/\/devexperts.com\/blog\/swing-oldie-but-goldie\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/devexperts.com\/blog\/"},{"@type":"ListItem","position":2,"name":"SWING: Oldie But Goldie"}]},{"@type":"WebSite","@id":"https:\/\/devexperts.com\/blog\/#website","url":"https:\/\/devexperts.com\/blog\/","name":"Devexperts Blog","description":"We make complex finance ideas on technology, innovation and business simple","publisher":{"@id":"https:\/\/devexperts.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/devexperts.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/devexperts.com\/blog\/#organization","name":"Devexperts LLC","url":"https:\/\/devexperts.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/devexperts.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/devexperts.com\/blog\/app\/uploads\/2019\/08\/DX-logo.png","contentUrl":"https:\/\/devexperts.com\/blog\/app\/uploads\/2019\/08\/DX-logo.png","width":167,"height":30,"caption":"Devexperts LLC"},"image":{"@id":"https:\/\/devexperts.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/devexperts\/","https:\/\/x.com\/devexperts","https:\/\/www.linkedin.com\/company\/devexperts","https:\/\/www.youtube.com\/channel\/UCF3FRmes2KrcVsTXQ1aAB5w\/featured"]}]}},"_links":{"self":[{"href":"https:\/\/devexperts.com\/blog\/wp-json\/wp\/v2\/posts\/656","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devexperts.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devexperts.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devexperts.com\/blog\/wp-json\/wp\/v2\/users\/39"}],"replies":[{"embeddable":true,"href":"https:\/\/devexperts.com\/blog\/wp-json\/wp\/v2\/comments?post=656"}],"version-history":[{"count":22,"href":"https:\/\/devexperts.com\/blog\/wp-json\/wp\/v2\/posts\/656\/revisions"}],"predecessor-version":[{"id":4126,"href":"https:\/\/devexperts.com\/blog\/wp-json\/wp\/v2\/posts\/656\/revisions\/4126"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devexperts.com\/blog\/wp-json\/wp\/v2\/media\/1614"}],"wp:attachment":[{"href":"https:\/\/devexperts.com\/blog\/wp-json\/wp\/v2\/media?parent=656"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devexperts.com\/blog\/wp-json\/wp\/v2\/categories?post=656"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devexperts.com\/blog\/wp-json\/wp\/v2\/tags?post=656"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}