Documentation

Trace:

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revision Both sides next revision
jvx:reference [2020/06/15 08:14]
cduncan [Conclusion]
jvx:reference [2020/06/15 08:54]
cduncan [Master/Detail]
Line 138: Line 138:
 ===== The Factory ===== ===== The Factory =====
  
-The heart piece of the UI layer is the factory that is creating the implemented classes. It’s a rather simple system, a singleton which is set to the Technology ​specific implementation and can be retrieved later:+The heart piece of the UI layer is the factory that is creating the implemented classes. It’s a rather simple system, a singleton which is set to the technology-specific implementation and can be retrieved later:
  
 <code java> <code java>
Line 172: Line 172:
 {{:​jvx:​reference:​multi-layers.png?​nolink|Multiple Extensions/​Implementations/​Technologies can be used}} {{:​jvx:​reference:​multi-layers.png?​nolink|Multiple Extensions/​Implementations/​Technologies can be used}}
  
-Changing between them can be as easy as setting a different factory. I say “can” because that is only true for Swing, JavaFX, and similar technologies. Vaadin, obviously, requires some more setup work. Theoretically,​ one could embed a complete application server and launch it when the factory for Vaadin is created, allowing the application to be basically stand-alone and be started as easily as a Swing application. That is possible.+Changing between them can be as easy as setting a different factory. I say “can” because that is only true for Swing, JavaFX, and similar technologies. Vaadin, obviously, requires some more setup work. Theoretically,​ one could embed a complete application server and launch it when the factory for Vaadin is created, allowing the application to be basically stand alone and started as easily as a Swing application. That is possible.
  
 ===== What else? ===== ===== What else? =====
  
-That is how [[https://​sourceforge.net/​projects/​jvx/​|JVx]] works in regards to the UI layer. It depends on “technology-specific stacks”, which can be swapped out and implemented for pretty much every GUI framework out there. We currently provide support for Swing, JavaFX, and Vaadin, but we also had implementations for GWT and Qt. Additionally,​ we do support a “headless” implementation,​ which uses lightweight objects that can be serialized and send over the wire without much effort.+That is how [[https://​sourceforge.net/​projects/​jvx/​|JVx]] works in regards to the UI layer. It depends on “technology-specific stacks”, which can be swapped out and implemented for pretty much every GUI framework out there. We currently provide support for Swing, JavaFX, and Vaadin, but we also had implementations for GWT and Qt. Additionally,​ we support a “headless” implementation,​ which uses lightweight objects that can be serialized and send over the wire without much effort.
  
 ===== Adding a New Technology ===== ===== Adding a New Technology =====
  
-Adding support for a new technology is as straightforward as one can imagine: simply ​creating ​the extensions/​implementations layers and implementing ​the factory for that technology. Giving a complete manual would be out for scope for this document, but the most simple approach to adding a new stack to [[https://​sourceforge.net/​projects/​jvx/​|JVx]] is to start with stubbing out the ''​%%IFactory%%''​ and implementing ''​%%IWindow%%''​. Once that one window shows up, it’s just implementing one interface after another in a quite straightforward manner. In the end, your application can switch to yet another GUI framework without the need to change your code.+Adding support for a new technology is as straightforward as one can imagine: simply ​create ​the extensions/​implementations layers and implement ​the factory for that technology. Giving a complete manual would be out for scope for this document, but the most simple approach to adding a new stack to [[https://​sourceforge.net/​projects/​jvx/​|JVx]] is to start with stubbing out the ''​%%IFactory%%''​ and implementing ''​%%IWindow%%''​. Once that one window shows up, it’s just implementing one interface after another in a quite straightforward manner. In the end, your application can switch to yet another GUI framework without the need to change your code.
  
 ===== Conclusion ===== ===== Conclusion =====
Line 198: Line 198:
 {{:​jvx:​reference:​resource.png?​nolink|The JVx layers revisited. UI wrapper and implementation implement the interface, extension and technology do not.}} {{:​jvx:​reference:​resource.png?​nolink|The JVx layers revisited. UI wrapper and implementation implement the interface, extension and technology do not.}}
  
-The UI wrappers are the main UI classes that are used to create the GUI (f.e. ''​%%UIButton%%''​). These are wrapping the implementations (f.e. ''​%%SwingButton%%''​),​ which themselves are wrapping the extension/​technology (f.e. a ''​%%JVxButton%%''/''​%%JButton%%''​). Only the UI and implementation classes implementing the interface are required for the component (f.e. ''​%%IButton%%''​). That also means that the implementation is dependent on the extension/​technology component, but the UI can use any object which implements the interface.+The UI wrappers are the main UI classes that are used to create the GUI (e.g., ''​%%UIButton%%''​). These are wrapping the implementations (e.g., ''​%%SwingButton%%''​),​ which themselves are wrapping the extension/​technology (e.g., a ''​%%JVxButton%%''/''​%%JButton%%''​). Only the UI and implementation classes implementing the interface are required for the component (e.g., ''​%%IButton%%''​). That also means that the implementation is dependent on the extension/​technology component, but the UI can use any object which implements the interface.
  
 Now, with that knowledge, we can start defining what is what: Now, with that knowledge, we can start defining what is what:
Line 206: Line 206:
 The resource itself, accessed by calling ''​%%<​uiwrapper>​.getResource()%%'',​ is the extension/​technology component. The  UI resource can be accessed by calling ''​%%<​uiwrapper>​.getUIResource()%%''​. The UI component can be accessed by calling ''​%%<​uiwrapper>​.getUIComponent()%%''​ and is usually the UI wrapper class itself. If we use our previous Swing example, the resource would be a ''​%%JVxButton%%''/''​%%JButton%%'',​ the  UI resource would be the ''​%%SwingButton%%''​ and the UI component would be the ''​%%UIButton%%''​. The resource itself, accessed by calling ''​%%<​uiwrapper>​.getResource()%%'',​ is the extension/​technology component. The  UI resource can be accessed by calling ''​%%<​uiwrapper>​.getUIResource()%%''​. The UI component can be accessed by calling ''​%%<​uiwrapper>​.getUIComponent()%%''​ and is usually the UI wrapper class itself. If we use our previous Swing example, the resource would be a ''​%%JVxButton%%''/''​%%JButton%%'',​ the  UI resource would be the ''​%%SwingButton%%''​ and the UI component would be the ''​%%UIButton%%''​.
  
-As one can see, access to all objects which comprise GUI possible at all times. We, of course, have the UI component, we can access the implementation component, and we can access the extension/​technology component. Theoretically,​ we could also swap them at runtime, but in [[https://​sourceforge.net/​projects/​jvx/​|JVx]],​ this is limited to the construction of the object to greatly reduce the error potential and complexity of the framework code.+As one can see, access to all objects which comprise GUI possible at all times. We, of course, have the UI component, we can access the implementation component, and we can access the extension/​technology component. Theoretically,​ we could also swap them at runtime, but in [[https://​sourceforge.net/​projects/​jvx/​|JVx]],​ this is limited to the construction of the object to greatly reduce the potential ​for error and complexity of the framework code.
  
 ===== Creating Custom Components ===== ===== Creating Custom Components =====
  
-We will use an example from the [[#​part_about_creating_custom_components|part about creating custom components]],​ which we will come to later. The ''​%%BeepComponent%%''​ is a simple ''​%%UIComponent%%''​ extension ​which contains a label and two buttons inside itself.+We will use an example from the [[#​part_about_creating_custom_components|part about creating custom components]],​ which we will come to later. The ''​%%BeepComponent%%''​ is a simple ''​%%UIComponent%%''​ extension ​that contains a label and two buttons inside itself.
  
 <code java> <code java>
Line 234: Line 234:
 } }
 </​code>​ </​code>​
-We are setting a new UI resource (a ''​%%UIPanel%%''​) in the constructor (at line #5) that is to be used by the ''​%%UI component%%''​. In this case, it is not an implementation,​ but another UI component. However, that doesn’t matter because the UI resource ​only must implement the expected interface. At line #15 we start using that custom UI resource.+We are setting a new UI resource (a ''​%%UIPanel%%''​) in the constructor (at line #5), which is to be used by the ''​%%UI component%%''​. In this case, it is not an implementation,​ but another UI component. However, that doesn’t matter because the UI resource must only implement the expected interface. At line #15 we start using that custom UI resource.
  
-Because UI component is an abstract component designed for exactly this usage, the example might not be the most exciting one, but it clearly illustrates the mechanic.+Because UI component is an abstract component designed for exactly this usage, the example might not be the most exciting one, but it clearly illustrates the mechanics.
  
 ===== Bolting on Functionality ===== ===== Bolting on Functionality =====
Line 253: Line 253:
 Now ''​%%testLabel%%''​ will be using the ''​%%PostfixedLabel%%''​ internally but with no indication to the user of the object that this is the case. This allows us to extend the functionality of a component completely transparently,​ especially in combination with functions that return a ''​%%UI component%%''​ and similar. Now ''​%%testLabel%%''​ will be using the ''​%%PostfixedLabel%%''​ internally but with no indication to the user of the object that this is the case. This allows us to extend the functionality of a component completely transparently,​ especially in combination with functions that return a ''​%%UI component%%''​ and similar.
  
-===== An Important Note About The Component Hierarchy =====+===== An Important Note About the Component Hierarchy =====
  
 If we create a simple component extensions, like the ''​%%BeepComponent%%''​ above, it is important to note that there is one other layer of indirection in regards to the hierarchy on the technology layer. If we create a simple frame with the ''​%%BeepComponent%%''​ in it, one might expect the following hierarchy: If we create a simple component extensions, like the ''​%%BeepComponent%%''​ above, it is important to note that there is one other layer of indirection in regards to the hierarchy on the technology layer. If we create a simple frame with the ''​%%BeepComponent%%''​ in it, one might expect the following hierarchy:
Line 280: Line 280:
                                     \-Button                                     \-Button
 </​code>​ </​code>​
-That is because such extended components are not “passed” to the technology; they only exist on the UI layer because they do not have a Technology ​component which could be used. That is done by adding the ''​%%UI component%%''​ to the UI parent, but for adding the actual technology component the set UI resource is used.+That is because such extended components are not “passed” to the technology; they only exist on the UI layer because they do not have a technology ​component which could be used. That is done by adding the ''​%%UI component%%''​ to the UI parent, but for adding the actual technology componentthe set UI resource is used.
  
 ===== The Special Case of Containers ===== ===== The Special Case of Containers =====
Line 333: Line 333:
 } }
 </​code>​ </​code>​
-Which is easy enough, but let’s say we’d like to add logic to that wrapper. At that point, it becomes more complicated. We can’t use the same technique as the custom component from above because, in that case, the “overlaying panel” would simply not be displayed. However, there is a similar mechanism for containers: setting the UI resource container.+This is easy enough, but let’s say we’d like to add logic to that wrapper. At that point, it becomes more complicated. We can’t use the same technique as the custom component from above because, in that case, the “overlaying panel” would simply not be displayed. However, there is a similar mechanism for containers: setting the UI resource container.
  
-The UI resource container is another special mechanism that works similar to setting the UI resource, but it works exactly ​the other way round. While setting the UI resource “hides” components from the technology in UI layer, setting the UI resource container hides components from the UI layer, while they are added in the technology. ​little complicated,​ here is our example using this technique again:+The UI resource container is another special mechanism that works similar to setting the UI resource, but it works the other way round. While setting the UI resource “hides” components from the technology in UI layer, setting the UI resource container hides components from the UI layer, while they are added in the technology.. As it is a little complicated,​ here is our example using this technique again:
  
 <code java> <code java>
Line 413: Line 413:
 Because of the way the [[https://​sourceforge.net/​projects/​jvx/​|JVx]] framework is designed, it is easy to access all layers of the GUI framework and facilitate the usage of these layers to create custom components and allow easy access to the wrapped components, no matter on what layer or of what kind they are. Because of the way the [[https://​sourceforge.net/​projects/​jvx/​|JVx]] framework is designed, it is easy to access all layers of the GUI framework and facilitate the usage of these layers to create custom components and allow easy access to the wrapped components, no matter on what layer or of what kind they are.
  
-====== Launchers and applications ​======+====== Launchers and Applications ​======
  
-Let’s talk about Launchers, and how they are used to start [[https://​sourceforge.net/​projects/​jvx/​|JVx]] applications.+Let’s talk about launchers, and how they are used to start [[https://​sourceforge.net/​projects/​jvx/​|JVx]] applications.
  
-===== Starting an application ​=====+===== Starting an Application ​=====
  
 From a technical point of view, there are two prerequisites which must be fulfilled before a [[https://​sourceforge.net/​projects/​jvx/​|JVx]] application can run: From a technical point of view, there are two prerequisites which must be fulfilled before a [[https://​sourceforge.net/​projects/​jvx/​|JVx]] application can run:
  
-  * the JVM must have started. +  * The JVM must have started. 
-  * the technology specific system must have started.+  * The technology specific system must have started.
  
-Then, and only then, the [[https://​sourceforge.net/​projects/​jvx/​|JVx]] application can run. Depending on the implementation that is used, that can be as easily ​as instancing the factory (Swing, JavaFX), but can also mean that a servlet server has to start (Vaadin). Because we do not wish to encumber our applications with technology specific code, we have to entrust all this to an encapsulated entity, meaning the implementations of ''​%%ILauncher%%''​ and ''​%%IApplication%%''​.+Then, and only then, the [[https://​sourceforge.net/​projects/​jvx/​|JVx]] application can run. Depending on the implementation that is used, that can be as easy as instancing the factory (Swing, JavaFX), but it can also mean that a servlet server has to start (Vaadin). Because we do not wish to encumber our applications with technology-specific code, we have to entrust all this to an encapsulated entity, meaning the implementations of ''​%%ILauncher%%''​ and ''​%%IApplication%%''​.
  
 ===== Following the Chain ===== ===== Following the Chain =====
Line 457: Line 457:
 } }
 </​code>​ </​code>​
-All we have to do there is start the launcher itself. As the comment suggests, there might be work required for a “real” application startup. For this example, it is all we need to do. Of course, we could also directly embed this little function into the launcher implementation itself to save us one class.+All we have to do there is start the launcher itself. As the comment suggests, there might be work required for a “real” application startup. For this example, however, it is all we need to do. Of course, we could also directly embed this little function into the launcher implementation itself to save us one class.
  
 ===== The Launcher ===== ===== The Launcher =====
  
-The ''​%%ILauncher%%''​ implementation,​ on the other hand, contains quite some logic but nothing ​not manageable:+The ''​%%ILauncher%%''​ implementation,​ on the other hand, contains quite a bit of logic but nothing ​unmanageable:
  
 <code java> <code java>
Line 576: Line 576:
 ===== Notes on the Launcher ===== ===== Notes on the Launcher =====
  
-As you might have noticed, in our example the launcher is a (window) frame. That makes sense for nearly every desktop GUI toolkit as they all depend upon a window as main method to display their applications. But the launcher could also be simpler: for example, just a call to start the GUI thread. Or it could be something completely different: for example, an incoming HTTP request.+As you might have noticed, in our example the launcher is a (window) frame. That makes sense for nearly every desktop GUI toolkitas they all depend upon a window as the main method to display their applications. But the launcher could also be simpler: for example, just a call to start the GUI thread. Or it could be something completely different: for example, an incoming HTTP request.
  
 Also, don’t forget that the launcher is providing additional functionality to the application,​ like saving file handles, reading and writing the configuration,​ and similar platform and toolkit-dependent operations. See the [[https://​sourceforge.net/​p/​jvx/​code/​HEAD/​tree/​trunk/​java/​swing/​src/​com/​sibvisions/​rad/​ui/​swing/​impl/​SwingApplication.java|launcher for Swing for further details]]. Also, don’t forget that the launcher is providing additional functionality to the application,​ like saving file handles, reading and writing the configuration,​ and similar platform and toolkit-dependent operations. See the [[https://​sourceforge.net/​p/​jvx/​code/​HEAD/​tree/​trunk/​java/​swing/​src/​com/​sibvisions/​rad/​ui/​swing/​impl/​SwingApplication.java|launcher for Swing for further details]].
Line 602: Line 602:
 {{:​jvx:​reference:​databook.png?​nolink|DataBook Architecture,​ the DataBook contains DataPages, which contain DataRows.}} {{:​jvx:​reference:​databook.png?​nolink|DataBook Architecture,​ the DataBook contains DataPages, which contain DataRows.}}
  
-===== RowDefinition ​=====+===== Row Definition ​=====
  
-The RowDefinition ​defines what columns are available in the row and stores some additional information about them, like the names of the [[https://​en.wikipedia.org/​wiki/​Unique_key|primary key]] columns. You can think of the RowDefinition ​as the headers of a table.+The row definition ​defines what columns are available in the row and stores some additional information about them, like the names of the [[https://​en.wikipedia.org/​wiki/​Unique_key|primary key]] columns. You can think of the row definition ​as the headers of a table.
  
-Its creation and usage is rather simple, and if you’re working with RemoteDataBooks there is no need to create one at all, as it is automatically created when the DataBook ​is opened. A RowDefinition ​holds and manages ​ColumnDefinitions, which define the columns.+Its creation and usage is rather simple, andif you’re working with RemoteDataBooks there is no need to create one at all, as it is automatically created when the data book is opened. A row definition ​holds and manages ​column definitions, which define the columns.
  
 <code java> <code java>
Line 628: Line 628:
 Most of the column definition is additional information about the column, like if it is nullable, the label of the column, default values, allowed values, and similar information. Most of the column definition is additional information about the column, like if it is nullable, the label of the column, default values, allowed values, and similar information.
  
-==== DataType ​====+==== Data Type ====
  
-Of course, we must define what type the value in the column has. This is done by setting a data type on the column definition. The data type defines what kind of values the column holds, like if it is a String, a Number, or something else. We provide the most often used data types out of the box:+Of course, we must define what type the value in the column has. This is done by setting a data type on the column definition. The data type defines what kind of values the column holds, like if it is a string, a number, or something else. We provide the most often used data types out of the box:
  
   * BigDecimal   * BigDecimal
Line 642: Line 642:
 It is possible to add new data types by simply implementing ''​%%IDataType%%''​. It is possible to add new data types by simply implementing ''​%%IDataType%%''​.
  
-===== DataRow ​=====+===== Data Row =====
  
 The data row represents a single row of data; it holds/​references its own row definition and, of course, provides access to the values of the row. Accessing the  data row can be done either by column index or column name, and the methods either return or accept objects. Let’s look at a simple usage example: The data row represents a single row of data; it holds/​references its own row definition and, of course, provides access to the values of the row. Accessing the  data row can be done either by column index or column name, and the methods either return or accept objects. Let’s look at a simple usage example:
Line 653: Line 653:
 dataRow.setValue("​COLUMN_A",​ "New Value"​);​ dataRow.setValue("​COLUMN_A",​ "New Value"​);​
 </​code>​ </​code>​
-===== DataPage ​=====+===== Data Page =====
  
-The data page is basically a list of data rows, it also holds its own row definition, which is shared with all the contained data rows.+The data page is basically a list of data rows. It also holds its own row definition, which is shared with all the contained data rows.
  
-The main usage of data pages is to allow paging in a master/​detail relationship. If the master selects a different row, the detail ​databook ​selects the related data page.+The main usage of data pages is to allow paging in a master/​detail relationship. If the master selects a different row, the detail ​data book selects the related data page.
  
-===== DataBook ​=====+===== Data Book =====
  
 The data book is the main model of [[https://​sourceforge.net/​projects/​jvx/​|JVx]],​ it provides direct access to its current data page and data row by extending from IDataRow and IDataPage. The data book is the main model of [[https://​sourceforge.net/​projects/​jvx/​|JVx]],​ it provides direct access to its current data page and data row by extending from IDataRow and IDataPage.
Line 665: Line 665:
 By default, the data book holds one data page and only has multiple data pages if it is the detail in a master/​detail relationship. By default, the data book holds one data page and only has multiple data pages if it is the detail in a master/​detail relationship.
  
-===== Usage example ​=====+===== Usage Example ​=====
  
-Here is a simple ​usage example of a ''​%%MemDataBook%%'',​ an ''​%%IDataBook%%''​ implementation which does only operate ​in memory:+Here is a simple example of a ''​%%MemDataBook%%'',​ an ''​%%IDataBook%%''​ implementation which only operates ​in memory:
  
 <code java> <code java>
Line 724: Line 724:
 ===== Master/​Detail ===== ===== Master/​Detail =====
  
-[[https://​en.wikipedia.org/​wiki/​Master%E2%80%93detail_interface#​Data_model|Master/​detail]] is something that occurs in nearly every data model. It means simply that there is one master ​dataset which is referenced by one or multiple detail ​datasets. Or to express it in SQL:+[[https://​en.wikipedia.org/​wiki/​Master%E2%80%93detail_interface#​Data_model|Master/​detail]] is something that occurs in nearly every data model. It simply ​means that there is one master ​data set that is referenced by one or multiple detail ​data sets. Or to express it in SQL:
  
 <code sql> <code sql>
Line 733: Line 733:
   left join DETAIL d on m.ID=d.MASTER_ID;​   left join DETAIL d on m.ID=d.MASTER_ID;​
 </​code>​ </​code>​
-We can of course express a master/​detail relationship when using data books. For that we just create a ''​%%ReferenceDefinition%%''​ and assign it to the detail data book:+We canof courseexpress a master/​detail relationship when using data books. For thatwe just create a ''​%%ReferenceDefinition%%''​ and assign it to the detail data book:
  
 <code java> <code java>
Line 767: Line 767:
                    ​8| ​        3                    ​8| ​        3
 </​code>​ </​code>​
-Now if we select the second row in the ''​%%masterDataBook%%'',​ the ''​%%detailDataBook%%''​ will just contain the rows with the corresponding ''​%%MASTER_ID%%'',​ so 3, 4 and 5.+Nowif we select the second row in the ''​%%masterDataBook%%'',​ the ''​%%detailDataBook%%''​ will just contain the rows with the corresponding ''​%%MASTER_ID%%'',​ so 3, 4and 5.
  
 <​code>​ <​code>​
Line 778: Line 778:
      ​3 ​            ​5| ​        2      ​3 ​            ​5| ​        2
 </​code>​ </​code>​
-The ''​%%detailDataBook%%''​ is automatically adjusted according to the selection in the ''​%%masterDatabook%%''​. Of course this can have an arbitrary depthtoo.+The ''​%%detailDataBook%%''​ is automatically adjusted according to the selection in the ''​%%masterDatabook%%''​. Of coursethis can have an arbitrary depth too.
  
 ===== Conclusion ===== ===== Conclusion =====
Line 796: Line 796:
 The following method is a simplified way to launch a [[https://​sourceforge.net/​projects/​jvx/​|JVx]] application. Normally, you’d use the technology specific launcher to launch the application. These launchers do know exactly what is required to set it up and start the technology and the application. However, covering the launchers is out of scope for this post, so we will review them and their mechanics in a follow-up. The following method is a simplified way to launch a [[https://​sourceforge.net/​projects/​jvx/​|JVx]] application. Normally, you’d use the technology specific launcher to launch the application. These launchers do know exactly what is required to set it up and start the technology and the application. However, covering the launchers is out of scope for this post, so we will review them and their mechanics in a follow-up.
  
-===== The simplest ​JVx application: Just the GUI =====+===== The Simplest ​JVx Application: Just the GUI =====
  
-But first, we will start without anything. The most simple application you can create with [[https://​sourceforge.net/​projects/​jvx/​|JVx]] is an application which does open a single window and only works with in memory data (if at all). This can be easily achieved by “just starting” the application.+But first, we will start without anything. The most simple application you can create with [[https://​sourceforge.net/​projects/​jvx/​|JVx]] is an application which opens a single window and only works with in-memory data (if at all). This can be easily achieved by “just starting” the application.
  
 [[https://​blog.sibvisions.com/​2016/​12/​07/​jvx-reference-of-technologies-and-factories/​|The JVx GUI is a simple layer on top of the Technology]] which implements the actual functionality. So if we want to have a GUI we’ll need to initialize the factory before doing anything else: [[https://​blog.sibvisions.com/​2016/​12/​07/​jvx-reference-of-technologies-and-factories/​|The JVx GUI is a simple layer on top of the Technology]] which implements the actual functionality. So if we want to have a GUI we’ll need to initialize the factory before doing anything else:
Line 805: Line 805:
 UIFactoryManager.getFactoryInstance(SwingFactory.class);​ UIFactoryManager.getFactoryInstance(SwingFactory.class);​
 </​code>​ </​code>​
-With this little code we have initialized everything we need to create a simple Swing application. Now we can start to create and populate a window with something:+With this little codewe have initialized everything we need to create a simple Swing application. Now we can start to create and populate a window with something:
  
 <code java> <code java>
Line 817: Line 817:
 frame.eventWindowClosed().addListener(() -> System.exit(0));​ frame.eventWindowClosed().addListener(() -> System.exit(0));​
 </​code>​ </​code>​
-We can start to create and manipulate the GUI, in this case we are building a simple window with a label inside. Last but not least, we make sure that the JVM will exit when the window is closed.+We can start to create and manipulate the GUI. In this case we are building a simple window with a label inside. Last but not least, we make sure that the JVM will exit when the window is closed.
  
 A very good example and showcase for that is the [[https://​github.com/​sibvisions/​jvx.kitchensink|JVx Kitchensink]]. A very good example and showcase for that is the [[https://​github.com/​sibvisions/​jvx.kitchensink|JVx Kitchensink]].
  
-That’s it. That is the most simple way to start a [[https://​sourceforge.net/​projects/​jvx/​|JVx]] application. We can use all controls and we can use ''​%%MemDataBook%%''​s without any problem or limitation. ​And best of all, we can simply switch to another ​Technology ​by using another factory.+That’s it. That is the most simple way to start a [[https://​sourceforge.net/​projects/​jvx/​|JVx]] application. We can use all controlsand we can use ''​%%MemDataBook%%''​s without any problem or limitation. ​Best of all, we can simply switch to another ​technology ​by using another factory.
  
 ===== Anatomy of a remote JVx application ===== ===== Anatomy of a remote JVx application =====
This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information