Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
UppHub
Status & Roadmap
FAQ
Authors & License
Forums
Funding U++
Search on this site











SourceForge.net Logo

SourceForge.net Logo

GitHub Logo

Discord Logo

U++ vs Java/Swing

To compare U++ with Java, we found simple Converter example. Note that this example was provided for Java tutorial, so it is perhaps not the best thing to use it for development effectiveness comparison. However, it still might serve well to get first hint about how well U++ does when compared to Java/Swing.

 

 

 

U++ version

Java/Swing version

Converter.cpp

#include <CtrlLib/CtrlLib.h>

 

#define LAYOUTFILE <Converter/converter.lay>

#include <CtrlCore/lay.h>

 

struct ConverterPane : WithConverterPaneLayout<StaticRect> {

    ConverterPane *slave;

    void AdjustSlave()

    {

        slave->slider <<= slave->value <<=

            IsNull(value) ? 0.0 : (double)~unit * (double)~value / (double)~slave->unit;

    }

    void ValueChanged()

    {

        slider <<= ~value;

        AdjustSlave();

    }

    void SliderChanged()

    {

        value <<= ~slider;

        AdjustSlave();

    }

    

    typedef ConverterPane CLASSNAME;

 

    ConverterPane()

    {

        CtrlLayout(*this);

        slider.Range(10000);

        slider <<= value <<= 0;

        value <<= THISBACK(ValueChanged);

        slider <<= THISBACK(SliderChanged);

        unit <<= THISBACK(AdjustSlave);

    }

};

 

struct Converter : TopWindow

{

    ConverterPane metric, us;

 

    typedef Converter CLASSNAME;

 

    Converter()

    {

        Title("Converter");

        Size sz = metric.GetLayoutSize();

        SetRect(0, 0, metric.GetSize().cx, metric.GetSize().cy * 2);

        Add(metric.HSizePos().TopPos(0, sz.cy));

        Add(us.HSizePos().BottomPos(0, sz.cy));

 

        metric.title = "Metric units";

        metric.unit.Add(0.01, "Centimeters");

        metric.unit.Add(1.0, "Meters");

        metric.unit.Add(1000.0, "Kilometers");

        metric.unit <<= 1.0;

 

        us.title = "U.S. units";

        us.unit.Add(0.0254, "Inches");

        us.unit.Add(0.305, "Feet");

        us.unit.Add(0.914, "Yards");

        us.unit.Add(1613.0, "Miles");

        us.unit <<= 0.305;

        

        us.slave = &metric;

        metric.slave = &us;

        

        metric.AdjustSlave();

    }

};

 

GUI_APP_MAIN

{

    Converter().Run();

}

 

converter.lay (designed using visual tool)

#ifdef LAYOUTFILE

 

LAYOUT(ConverterPaneLayout, 244, 76)

    ITEM(LabelBox, title, LeftPosZ(8, 228).TopPosZ(4, 64))

    ITEM(EditDoubleSpin, value, LeftPosZ(16, 144).TopPosZ(20, 19))

    ITEM(SliderCtrl, slider, LeftPosZ(16, 144).TopPosZ(40, 20))

    ITEM(DropList, unit, LeftPosZ(164, 64).TopPosZ(20, 19))

END_LAYOUT

 

#endif

 

 

 

Converter.java

import javax.swing.*;

import javax.swing.event.*;

import java.awt.*;

import java.awt.event.*;

import java.util.*;

 

public class Converter {

   ConversionPanel metricPanel, usaPanel;

   Unit[] metricDistances = new Unit[3];

   Unit[] usaDistances = new Unit[4];

   ConverterRangeModel dataModel = new ConverterRangeModel();

   JPanel mainPane;

 

   public Converter() {

       metricDistances[0] = new Unit("Centimeters", 0.01);

       metricDistances[1] = new Unit("Meters", 1.0);

       metricDistances[2] = new Unit("Kilometers", 1000.0);

       metricPanel = new ConversionPanel(this, "Metric System",

                                         metricDistances,

                                         dataModel);

 

       usaDistances[0] = new Unit("Inches", 0.0254);

       usaDistances[1] = new Unit("Feet", 0.305);

       usaDistances[2] = new Unit("Yards", 0.914);

       usaDistances[3] = new Unit("Miles", 1613.0);

       usaPanel = new ConversionPanel(this, "U.S. System",

                                      usaDistances,

                                      new FollowerRangeModel(dataModel));

 

       mainPane = new JPanel();

       mainPane.setLayout(new GridLayout(2,1,5,5));

       mainPane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));

       mainPane.add(metricPanel);

       mainPane.add(usaPanel);

       resetMaxValues(true);

   }

 

   public void resetMaxValues(boolean resetCurrentValues) {

       double metricMultiplier = metricPanel.getMultiplier();

       double usaMultiplier = usaPanel.getMultiplier();

       int maximum = ConversionPanel.MAX;

 

       if (metricMultiplier > usaMultiplier) {

           maximum = (int)(ConversionPanel.MAX *

                     (usaMultiplier/metricMultiplier));

       }

 

       dataModel.setMaximum(maximum);

 

       if (resetCurrentValues) {

           dataModel.setDoubleValue(maximum);

       }

   }

 

   public static void main(String[] args) {

       Converter converter = new Converter();

 

       JFrame f = new JFrame("Converter");

       f.addWindowListener(new WindowAdapter() {

           public void windowClosing(WindowEvent e) {

               System.exit(0);

           }

       });

 

       f.setContentPane(converter.mainPane);

 

       f.pack();

       f.setVisible(true);

   }

}

 

 

ConversionPanel.java

import javax.swing.*;

import javax.swing.event.*;

import java.awt.*;

import java.awt.event.*;

import java.util.*;

import java.text.NumberFormat;

 

public class ConversionPanel extends JPanel {

   DecimalField textField;

   JComboBox unitChooser;

   JSlider slider;

   ConverterRangeModel sliderModel;

   Converter controller;

   Unit[] units;

   String title;

   final static int MAX = 10000;

 

   ConversionPanel(Converter myController, String myTitle,

                   Unit[] myUnits,

                   ConverterRangeModel myModel) {

       setBorder(BorderFactory.createCompoundBorder(

                       BorderFactory.createTitledBorder(myTitle),

                       BorderFactory.createEmptyBorder(5,5,5,5)));

 

       controller = myController;

       units = myUnits;

       title = myTitle;

       sliderModel = myModel;

 

       NumberFormat numberFormat = NumberFormat.getNumberInstance();

       numberFormat.setMaximumFractionDigits(2);

       textField = new DecimalField(0, 10, numberFormat);

       textField.setValue(sliderModel.getDoubleValue());

       textField.addActionListener(new ActionListener() {

           public void actionPerformed(ActionEvent e) {

               sliderModel.setDoubleValue(textField.getValue());

           }

       });

 

       unitChooser = new JComboBox();

       for (int i = 0; i < units.length; i++) {

           unitChooser.addItem(units[i].description);

       }

       unitChooser.setSelectedIndex(0);

       sliderModel.setMultiplier(units[0].multiplier);

       unitChooser.addActionListener(new ActionListener() {

           public void actionPerformed(ActionEvent e) {

               int i = unitChooser.getSelectedIndex();

               sliderModel.setMultiplier(units[i].multiplier);

               controller.resetMaxValues(false);

           }

       });

 

       slider = new JSlider(sliderModel);

       sliderModel.addChangeListener(new ChangeListener() {

           public void stateChanged(ChangeEvent e) {

              textField.setValue(sliderModel.getDoubleValue());

           }

       });

 

       JPanel unitGroup = new JPanel() {

           public Dimension getMinimumSize() {

               return getPreferredSize();

           }

           public Dimension getPreferredSize() {

               return new Dimension(150,

                      super.getPreferredSize().height);

           }

           public Dimension getMaximumSize() {

               return getPreferredSize();

           }

       };

       unitGroup.setBorder(BorderFactory.createEmptyBorder(

                                               0,0,0,5));

       unitGroup.setLayout(new BoxLayout(unitGroup,

                                         BoxLayout.Y_AXIS));

       unitGroup.add(textField);

       unitGroup.add(slider);

 

       setLayout(new BoxLayout(this, BoxLayout.X_AXIS));

       add(unitGroup);

       add(unitChooser);

       unitGroup.setAlignmentY(TOP_ALIGNMENT);

       unitChooser.setAlignmentY(TOP_ALIGNMENT);

   }

 

   public double getMultiplier() {

       return sliderModel.getMultiplier();

   }

 

   public double getValue() {

       return sliderModel.getDoubleValue();

   }

}

 

ConverterRangeModel.java

import javax.swing.*;

import javax.swing.event.*;

 

public class ConverterRangeModel implements BoundedRangeModel {

   protected ChangeEvent changeEvent = null;

   protected EventListenerList listenerList = new EventListenerList();

 

   protected int maximum = 10000;

   protected int minimum = 0;

   protected int extent = 0;

   protected double value = 0.0;

   protected double multiplier = 1.0;

   protected boolean isAdjusting = false;

 

   public ConverterRangeModel() {

   }

 

   public double getMultiplier() {

       return multiplier;

   }

 

   public void setMultiplier(double multiplier) {

       this.multiplier = multiplier;

       fireStateChanged();

   }

 

   public int getMaximum() {

       return maximum;

   }

 

   public void setMaximum(int newMaximum) {

       setRangeProperties(value, extent, minimum, newMaximum, isAdjusting);

   }

 

   public int getMinimum() {

       return (int)minimum;

   }

 

   public void setMinimum(int newMinimum) {

       System.out.println("In ConverterRangeModel setMinimum");

   }

 

   public int getValue() {

       return (int)getDoubleValue();

   }

 

   public void setValue(int newValue) {

       setDoubleValue((double)newValue);

   }

 

   public double getDoubleValue() {

       return value;

   }

 

   public void setDoubleValue(double newValue) {

       setRangeProperties(newValue, extent, minimum, maximum, isAdjusting);

   }

 

   public int getExtent() {

       return (int)extent;

   }

 

   public void setExtent(int newExtent) {

   }

 

   public boolean getValueIsAdjusting() {

       return isAdjusting;

   }

 

   public void setValueIsAdjusting(boolean b) {

       setRangeProperties(value, extent, minimum, maximum, b);

   }

 

   public void setRangeProperties(int newValue,

                                  int newExtent,

                                  int newMin,

                                  int newMax,

                                  boolean newAdjusting) {

       System.out.println("In ConverterRangeModel setRangeProperties");

       setRangeProperties((double)newValue,

                          newExtent,

                          newMin,

                          newMax,

                          newAdjusting);

   }

 

   public void setRangeProperties(double newValue,

                                  int unusedExtent,

                                  int unusedMin,

                                  int newMax,

                                  boolean newAdjusting) {

       if (newMax <= minimum) {

           newMax = minimum + 1;

           if (DEBUG) {

               System.out.println("maximum raised by 1 to " + newMax);

           }

       }

       if (Math.round(newValue) > newMax) { //allow some rounding error

           newValue = newMax;

       }

 

       boolean changeOccurred = false;

       if (newValue != value) {

           value = newValue;

           changeOccurred = true;

       }

       if (newMax != maximum) {

           maximum = newMax;

           changeOccurred = true;

       }

       if (newAdjusting != isAdjusting) {

           maximum = newMax;

           isAdjusting = newAdjusting;

           changeOccurred = true;

       }

 

       if (changeOccurred) {

           fireStateChanged();

       }

   }

 

   /*

    * The rest of this is event handling code copied from

    * DefaultBoundedRangeModel.

    */

   public void addChangeListener(ChangeListener l) {

       listenerList.add(ChangeListener.class, l);

   }

 

   public void removeChangeListener(ChangeListener l) {

       listenerList.remove(ChangeListener.class, l);

   }

 

   protected void fireStateChanged() {

       Object[] listeners = listenerList.getListenerList();

       for (int i = listeners.length - 2; i >= 0; i -=2 ) {

           if (listeners[i] == ChangeListener.class) {

               if (changeEvent == null) {

                   changeEvent = new ChangeEvent(this);

               }

               ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);

           }

       }

   }

}

 

DecimalField.java

import javax.swing.*;

import javax.swing.text.*;

 

import java.awt.Toolkit;

import java.text.*;

 

public class DecimalField extends JTextField {

   private NumberFormat format;

 

   public DecimalField(double value, int columns, NumberFormat f) {

       super(columns);

       setDocument(new FormattedDocument(f));

       format = f;

       setValue(value);

   }

 

   public double getValue() {

       double retVal = 0.0;

 

       try {

           retVal = format.parse(getText()).doubleValue();

       } catch (ParseException e) {

           Toolkit.getDefaultToolkit().beep();

           System.err.println("getValue: could not parse: " + getText());

       }

       return retVal;

   }

 

   public void setValue(double value) {

       setText(format.format(value));

   }

}

 

FollowerRangeModel.java

import javax.swing.*;

import javax.swing.event.*;

 

public class FollowerRangeModel extends ConverterRangeModel

                               implements ChangeListener {

   ConverterRangeModel dataModel;

 

   public FollowerRangeModel(ConverterRangeModel dataModel) {

       this.dataModel = dataModel;

       dataModel.addChangeListener(this);

   }

 

   public void stateChanged(ChangeEvent e) {

       fireStateChanged();

   }

 

   public int getMaximum() {

       int modelMax = dataModel.getMaximum();

       double multiplyBy = dataModel.getMultiplier()/multiplier;

       return (int)(modelMax * multiplyBy);

   }

 

   public void setMaximum(int newMaximum) {

       dataModel.setMaximum((int)(newMaximum *

                    (multiplier/dataModel.getMultiplier())));

   }

 

   public int getValue() {

       return (int)getDoubleValue();

   }

 

   public void setValue(int newValue) {

       setDoubleValue((double)newValue);

   }

 

   public double getDoubleValue() {

       return dataModel.getDoubleValue()

              * dataModel.getMultiplier()

              / multiplier;

   }

 

   public void setDoubleValue(double newValue) {

       dataModel.setDoubleValue(

                    newValue * multiplier

                    / dataModel.getMultiplier());

   }

 

   public int getExtent() {

       return super.getExtent();

   }

 

   public void setExtent(int newExtent) {

       super.setExtent(newExtent);

   }

 

   public void setRangeProperties(int value,

                                  int extent,

                                  int min,

                                  int max,

                                  boolean adjusting) {

       double multiplyBy = multiplier/dataModel.getMultiplier();

       dataModel.setRangeProperties(value*multiplyBy,

                                    extent, min,

                                    (int)(max*multiplyBy),

                                    adjusting);

   }

}

 

FormattedDocument.java

import javax.swing.*;

import javax.swing.text.*;

 

import java.awt.Toolkit;

import java.text.*;

import java.util.Locale;

 

public class FormattedDocument extends PlainDocument {

   private Format format;

 

   public FormattedDocument(Format f) {

       format = f;

   }

 

   public Format getFormat() {

       return format;

   }

 

   public void insertString(int offs, String str, AttributeSet a)

       throws BadLocationException {

 

       String currentText = getText(0, getLength());

       String beforeOffset = currentText.substring(0, offs);

       String afterOffset = currentText.substring(offs, currentText.length());

       String proposedResult = beforeOffset + str + afterOffset;

 

       try {

           format.parseObject(proposedResult);

           super.insertString(offs, str, a);

       } catch (ParseException e) {

           Toolkit.getDefaultToolkit().beep();

           System.err.println("insertString: could not parse: "

                              + proposedResult);

       }

   }

 

   public void remove(int offs, int len) throws BadLocationException {

       String currentText = getText(0, getLength());

       String beforeOffset = currentText.substring(0, offs);

       String afterOffset = currentText.substring(len + offs,

                                                  currentText.length());

       String proposedResult = beforeOffset + afterOffset;

 

       try {

           if (proposedResult.length() != 0)

               format.parseObject(proposedResult);

           super.remove(offs, len);

       } catch (ParseException e) {

           Toolkit.getDefaultToolkit().beep();

           System.err.println("remove: could not parse: " + proposedResult);

       }

   }

}

 

Unit.java

public class Unit {

   String description;

   double multiplier;

 

   Unit(String description, double multiplier) {

       super();

       this.description = description;

       this.multiplier = multiplier;

   }

 

   public String toString() {

       String s = "Meters/" + description + " = " + multiplier;

       return s;

   }

}

 

 

References

http://www.ictp.trieste.it/~manuals/programming/Java/tutorial/uiswing/overview/anatomy.html - original Java source code of Converter, currently unavailable (2019)

Do you want to contribute?