How to build Java application with WinForms interface

Javonet WinForms Calculator Window
Javonet WinForms Calculator Window
Javonet Quick Start Guide

For more information how to use Javonet in common scenerios like creating objects, invoking methods, getting/setting fields, subscribing events and others please refer to our Javonet Quick Start Guide

Overview

This sample show how to build .NET WinForms window from Java code. If you look for a solution how to embed existing .NET WinForms or WPF user control within Java AWT, Swing or JavaFX window check our guide here: Embedding .NET User Controls in Java

Download Sample Project

Use the links below to download full source code and binaries of the sample project created in this tutorial:
Download Source Code and Binaries

Introduction

In this tutorial you will learn how to build Java application with WinForms interface, how to extend .NET class in Java and how to build custom strongly-typed wrapper for .NET object. Javonet allows you to create WinForms window the same way as you would do it in .NET by extending “Form” class. Using built-in events bridge you can subscribe to .NET events and provide fully functional interactive interface.

Use cases

This solution might be helpful in each situation where you have business logic implemented in Java and just wants to expose the user interface using .NET, when you plan to migrate your Java application to .NET or if you have another system built on Java which forces you to develope user logic in Java but you would like to levarage possiblities of WinForms interace.

Prerequisites

To build Java application with WinForms interface all you need is Javonet developer license and Javonet desktop license for each end-user workstation.

Step by step instruction

1) Before using Javonet it’s good practice to prepare Javonet XML configuration file first. XML configuration file allows us to provide license details, apartment state and assemblies to be referenced in easy to access and modify way. Using XML config files it’s not required to activate or configure Javonet from code, just by first usage of Javonet API it will configure itself automatically.

Our XML configuration file will look like the one presented below. We will use two .NET libraries from .NET framework, therefore in the “reference” section we add “System.Windows.Forms” and “System.Drawing”. Notice that we provide just name of the library not the full path, this way Javonet will use library located in GAC.

<!--?xml version="1.0" encoding="ISO-8859-1" ?-->
<javonet>
<references>
    <reference>System.Windows.Forms</reference>
    <reference>System.Drawing</reference>
</references>
<activation>
    <username>YOUR NAME</username>
    <email>[email protected]</email>
    <licencekey>YOUR-LICENSE-KEY</licencekey>
</activation>
<settings>
    <apartmentState>STA</apartmentState> <!--Remember to set apartment state to STA-->
    <framework>v40</framework> <!--To use STA you must load .NET 4.0 or 4.5 but you can still use .NET 3.5 DLLs-->
</settings>
</javonet>

One of the most important change is ApartmentState, this value indicates in what kind of apartment state our .NET process main thread will be running, to create WinForms window it should be set to STA (Single Thread Application).

Save the XML presented above in “javonet.xml” file.

2) Now we can create our Java Project in Eclipse using menu “File > Java Project”. Give the name “JavonetWinformsApp” and press “Finish”.

3) When our application is ready we have to copy “javonet.jar” and “javonet.xml” (prepared in first step) to our new project. Next right click on your project go to “New > Class” and in the “New Java Class” window provide name “JavonetWinformsAppMain” and check field “public static void main(String[] args)” so the default entry method will be created. Next create another Java Class without “main” method, called “CalculatorForm” this class we will use to extend “Form” and implement our WinForms form logic. Our project should look like this:

WinForms Sample Project
WinForms Sample Project
4) Next step is to add “javonet.jar” file reference to our project. Right click on the project choose “Build Path > Configure Build Path” and in the new window go to “Add JARs” and choose “javonet.jar” from the our project. Accept all windows and close until you will get back to the project view.

New item in our project should appear called “Referenced Libraries” with javonet library inside.

5) Now we can build our application. We will start with CalculatorForm. The first step is to tell Javonet that our class “CalculatorForm” will be extending .NET “Form” class. To do it extend NObject class and add default constructor in which you will call base constructor providing type of .NET class to be extended.

public class CalculatorForm extends NObject {  
  public CalculatorForm() throws JavonetException   {
    super("System.Windows.Forms.Form");
  }
}

Because during initialization of base .NET type any .NET exception can occure our constructor must declare that it can throw JavonetException which wraps any .NET side exception. As you see in call to base constructor by “super” operator we pass as argument string constant with full name of .NET type which will be extended by our Java class. From now our CalculatorForm class can access any protected and public fields and methods of “Form” class using Javonet notation. In this class we will implement our interface design and logic.

Let’s create standard “InitializeComponents” method where we will specify details about our window design. This method will be called from our constructor:

public class CalculatorForm extends NObject {
  private NObject tbDisplay;
  
  public CalculatorForm() throws JavonetException
  {
    super("System.Windows.Forms.Form");
    InitializeComponents();
  }
  
  private void InitializeComponents() throws JavonetException
  {
    this.set("Text", "Javonet Calculator");
    this.set("Width", 266);
    
    tbDisplay=Javonet.New("System.Windows.Forms.TextBox");
    tbDisplay.set("Width", 250);
    tbDisplay.set("Height", 100);
    tbDisplay.set("Text", "0");
    tbDisplay.set("TextAlign", new NEnum("System.Windows.Forms.HorizontalAlignment","Right"));
    NObject font = Javonet.New("System.Drawing.Font","Verdana", 24F);
    tbDisplay.set("Font", font);

    this.getRef("Controls").invoke("Add", tbDisplay);
  }
}

Now our code works pretty the same as .NET WinForms window definitione. We have added “tbDisplay” TextBox variable on class level (as it is instance of .NET object we hold it in NObject variable). Next we added “InitializeComponents” method which we call from constructor. In this method we call set on local “Text” and “Width” fields of our .NET window and we initialize new instance of TextBox for which we set several properties and font. Please notice that we use .NET enum field to specify HorizontalAlignment of our text and we also initialize .NET font object which we pass as reference to “Font” field on our TextBox object. At the end we get Controls property of our Form and invoke “Add” method passing our TextBox instance as argument.

Now we are almost ready to run our first WinForms window. The only missing part is “ShowDialog” or “Show” method which we can wrap in our “CalculatorForm” class so it will be accessible as strongly-types method in our Java application. This is good example of preparing custom wrapper classes if you would like to expose .NET objects in strongly-typed manner for your Java applications. Such wrapping method should look like this:

public void ShowDialog() throws JavonetException
{
  this.invoke("ShowDialog");
}

Our wrapping method is called the same as .NET counterpart and accepts exactly the same arguments (in this case no arguments). Now any other class in our Java application can call “ShowDialog” method on our Form like it was regular Java method. This one we will use in our main method at startup of our application:

public class JavonetWinformsAppMain {
  public static void main(String[] args) throws JavonetException {
    CalculatorForm frmMain = new CalculatorForm();
    frmMain.ShowDialog();
  }
}

The final result of executing our application should be as follows:
Javonet WinForms Calculator Form
Javonet WinForms Calculator Form

And that’s it we have real WinForms window initiated by Java application by extending .NET Form class in Java. Now we can add some buttons and event listeners to handle click events. We will declare buttons variables as NObject field on class level and initialize them in our “InitializeComponents” method:

  button1=Javonet.New("System.Windows.Forms.Button");
  button1.set("Height", 50);
  button1.set("Width", 50);
  button1.set("Top", 50);
  button1.set("Text", "1");
  button1.addEventListener("Click", new NEventListener() {
    public void eventOccurred(Object[] arguments) {
      button1_Click((NObject)arguments[0],(NObject)arguments[1]);
    }
  });
  this.getRef("Controls").invoke("Add", button1);

Here you can see how our button initialization looks like. We initialize new Button object, set some properties and add new Event Listener for “Click” event. There are several different ways for subscribing .NET events about which you can read more in our Quick Start Guide. This example uses anonymous class. While .NET event occurs our “eventOccurred” method is called. As you see .NET event arguments are delivered in Object array but we split them into regular arguments in our event handler method “button1_Click”. As arguments are “Object sender, EventArgs e” so both are .NET instances our event handler accepts as arguments two NObject variables. Our event handler method looks like this:

private void button1_Click(NObject sender, NObject e)
{
  NumberPressed(1);
}

Implementation of “NumberPressed” method is simply displaying pressed numer and performing some simple calculation:

private void NumberPressed(Integer number)
{
  try {
    String current = tbDisplay.get("Text");

    if (current.equals(operation) || current.equals("0"))
      current="";
    tbDisplay.set("Text", current+number.toString());
  } catch (JavonetException e) {
    e.printStackTrace();
  }
}

Now our application has new button “1” and after pressing this button the digit “1” is appended to our display. Now we can specify rest of the controls and finalize our calculator application written in Java with WinForms interface. On the image below you can see the final result. For full application source code please download our full sample.
Javonet WinForms Calculator Window
Javonet WinForms Calculator Window

Download Sample Project

Use the links below to download full source code and binaries of the sample project created in this tutorial:
Download Source Code and Binaries