Tag: Java

  • No Main Class Found

    If Java comes up with the error message like “no main class found” you might have a problem like many many others before (as a google query reveals). Usually, the problem comes from one of the following issues:
    (more…)

  • Wegpunkte mit JXMapKit zeichnen

    Im Artikel “Erste Schritte mit JavaX JXMapKit” habe ich schon kurz beschrieben, wie man mit NetBeans und SwingX-WS schnell und einfach eine Kartendarestllung á la GoogleMaps in Java bauen kann.

    Wenn man nicht nur eine Karte anzeigen sondern auch Punkte einzeichnen will, hat man die Möglichkeiten, per jXMapKit.setAddressLocation(new GeoPosition(lat, lon)); die Koordinaten setzen, zeichnen und die Karte dorthin zentrieren. Allerdings wird die Karte damit auch immer gleich zentriert und vor allem kann man nur einen einzelnen Punkt setzen.

    Mehrere Wegpunkte setzt man mithilfe des WaypointPainters:

    Set set = new HashSet();
    WaypointPainter waypointPainter = new WaypointPainter();
    waypointPainter.setWaypoints(set);
    set.add(new Waypoint(47.76098, 11.55932));
    jXMapKit.getMainMap().setOverlayPainter(waypointPainter);
    repaint();

    Das repaint() am Ende sollte immer erfolgen, wenn neue Punkte in das Set gesetzt werden, damit die Änderung auch sofort sichtbar ist. Andernfalls muss man die Karte etwas verschieben um ein repaint zu erzwingen. Will man jetzt noch die Darstellung der Wegpunkte verändern, muss man sich noch mit dem WaypointRenderer beschäftigen.

  • Java Heap-Implementierung / Avoid too much sorting II

    Im Artikel Avoid too much sorting habe ich ja schon kurz skizziert, dass man es generell vermeiden sollte seine Daten unnötig oft zu sortieren, weil das einfach (je nachdem wie oft der entsprechende Code aufgerufen wird) ziemlich in die Rechenzeit gehen kann.

    Manchmal muss man seine Daten aber eben sortiert halten. – Dann sollte man sich aber überlegen, ob man wirklich die ganzen Daten sortieren muss, oder ob es nicht einfach reicht, immer das kleinste/größte Element einer Menge zu bekommen. Ein gutes Beispiel ist zum Beispiel der altbekannte Dijkstra-Algorithmus. Dort benötigt man in jeder Iteration z.B. den Weg mit den bisher kleinsten Kosten.

    Das schreit ja schon nach Sortieren. Bzw. eigentlich sollte einem da gleich die Heap-Datenstruktur einfallen, da dort alle Operaionen maximal in O(log n) erledigt sind, und nicht (wie beim Sortieren) in bis zu O(n²). Das schöne daran ist, dass es das in Java auch schon gibt, da heißt es nur nicht Heap (da man dabei vermutlich zu sehr an die Speicherverwaltung denken könnte), sondern PriorityQueue.

    Wenn man jetzt aber Objekte sortieren will die nicht per se Comparable sind, benötigt man noch eine kleine Comparator-Implementierung mit einem SimpleEntry, damit man einem beliebigem Objekt auch seine Kosten zuweisen kann. Klingt jetzt recht aufwändig – ist es aber bei weitem nicht:

    import java.util.AbstractMap.SimpleEntry;
    import java.util.Comparator;
    import java.util.PriorityQueue;
    
    public class Test {
        public static void main(String[] args) {
            PriorityQueue<SimpleEntry> heap =
                    new PriorityQueue<SimpleEntry>(10, new FooCmp());
            heap.add(new SimpleEntry(1d, new Foo(1)));
            heap.add(new SimpleEntry(5d, new Foo(2)));
            heap.add(new SimpleEntry(2d, new Foo(3)));
            while (!heap.isEmpty()) {
                System.out.println(heap.poll().getValue().i);
            }
        }
    }
    
    class FooCmp implements Comparator<SimpleEntry> {
        @Override
        public int compare(SimpleEntry o1, SimpleEntry o2) {
            return Double.compare(o1.getKey(), o2.getKey());
        }
    }
    
    class Foo {
        int i;
        Foo(int i) { this.i = i; }
    }
  • How to use TableModels and ListModel with NetBeans GUI Builder

    A default JTable or JList comes with it’s own pre initalized model. Okay – but: how can we modify this model? Which type of model is usually pre initialized?
    In the following I’ll just list some of the may possible ways to work with tables and lists and the NetBeans Gui Builder:
    (more…)

  • Escape analysis, Lock Coarsening und Biased locking

    Die Ausgabe 179 des “The Java Specialists’ Newsletter” stellt ein paar interessante – wenn auch noch experimentelle – Features der Server-VM vor:

    Escape analysis: Damit kann die JVM prüfen, ob ein Objekt einen bestimmten Scope nicht verlässt (z.B. nur in einer Methode verwendet wird) und dieses Objekt dann direkt auf dem Stack anlegen.

    Lock Coarsening: Fordert ein Thread aufeinanderfolgend mehrere Locks auf ein Objekt an und gibt sie dann wieder frei (wie z.B. bei der Verwendung von Vector), kann die JVM diese wiederholten, teuren Anfragen zu einem lock/release zusammenfassen,

    Biased locking: Wird ein Objekt von nur einem Thread ge’lock’ed, kann auf die Sperre ebenso verzichtet werden.

    Im The Java Specialists’ Newsletter werden einige eindrucksvolle MicroBenchmarks gezeigt, die einiges an Performance bringen können. Aber: es sind nur MicroBenchmarks, die den Effekt sehr gut zeigen. In komplexen Applikationen kann der Benefit natürlich deutlich schlechter ausfallen. Soweit ich das aus anderen Seiten gelesen habe, sind die Optionen derzeit noch als experimentell zu betrachten – aber sie sind schon ein schöner Vorgeschmack.

    Ein sehr schönes Statement im Zusammenhang mit Performance Tuning, das den Nagel auf den Kopf trifft: “Assumption is the mother of all f* ups”. Der Spruch drückt sehr schön das aus, was ich bei Performance-Optimierungen immer wieder sage: Erst Messen, dann Tunen. Und niemals Tunen ohne zu Messen. Andernfalls kann man schnell mal Stunden damit zubringen, ein Programmstück auf 5% Ausführungszeit zu drücken … das aber in der Gesamtausführung nahezu keine Zeit verbraucht – womit die Verbesserung quasi nicht existent ist. Oder schlimmer: man denkt, ein Programmteil wäre langsam, optimiert aber erfolglos an der Ursache vorbei.

    Relevante Links:

    http://profiler.netbeans.org/
  • Avoid too much sorting

    “Java is slow” is the sentence that I heard very often when I began studying computer science – and I forunately never really believed it. But why the predjudice? Well Java CAN be slow if it’s just handeled wrong. Often it’s just convenience of just the missing knowledge of implemntations that makes code slow, so I’ll try to post once in a while whenever I come across such code parts in my hobby programming or at my programmings at work.

    So my first issue is about sorting and autoboxing: About last week we profiled some code that felt just sloooow. It turned out that we lost most of the time within a certain loop that was executed very often. The critical part of the code was (stripped from all other stuff) like this :

    ArrayList<Double> list = new ArrayList<Double>(20); // keep 20 smallest calculated values
    while (condition) {
      double value = calculate(args);
      if (list.size < 20 || value < list.get(19)){
        list.add(value);
        Collections.sort(list)
      }
      // strip elements if size is > 20
    }

    So what’s the issue here?

    1. condition holds true for a LOT of iterations (well, can’t change this)
    2. the list is small (just 20) BUT it is to be sorted completely for each insert
    3. could autoboxing be an issue here?

    Okay, what did we change?

    We changed the ArrayList to a SortedDoubleArray (an implementation that I coded some time ago) that inserts the value already in the correct place using Arrays#binaraySearch() and System.arrayCopy(). As I wasn’t quite sure whether or not autoboxing could be an issue here, I created a copy of the class that operates on Doubles instead of the double primitives.

    The Test

    In order to compare the 3 methods (using Collections.sort(), and the SortedArrays using double and Double), I inserted 1,000,000 random double values into the structures and measured the times. The results are:

    • Collection.sort(): 2907 ms (=100%)
    • SortedDoubleArray (with Double-autoboxed values):  93 ms (~3%)
    • SortedDoubleArray (with double primitives):  94 ms (~3%)

    Conclusion

    • Using Collections.sort() is convenient and in most cases absolutely okay! But if you use it in critical locations within the code (for example in loops that are executed very often), you might want to check if there isn’t a better solution.
    • Autoboxing does not hurt in our case

    But never forget: Profile first, then tune. Otherwise you might tune code that has almost no impact to the overall execution time (for example, if the for-loop above is just executed 10 times).  And just change one issue after the other and perform measurements between each step so that you can identify the changes with the most impact.
    If you have no profiler at hand, you might want to try the NetBeans profier.

    value
  • How to load images in Java

    Every once in a while there is a question on the NetBeans mailinglist about how to load an image (or other ressource, like a text file) relative to the executing JAR.

    The Java Tutorial gives the answer in the chapter “How to use Icons“:

    java.net.URL imgURL = getClass().getResource("inSamePackage.png");
    java.net.URL imgURL = getClass().getResource("/de/foo/otherPackage.png");

    (more…)

  • How to display images with rounded Corners / Borders

    Bilder in Java darzustellen ist keine große Kunst, dazu gibt es auch ein Tutorial von Sun. Etwas schöner wären aber abgerundete Ecken. Und noch schöner wäre es, wenn wir einfach eine kleine Componente hätten die das alles selber macht, die wiederverwendbar wäre und die im GUI-Editor einfach zu bedienen wäre. Gesagt getan.

    Die Anforderung ist also eine Gui Componente, die im Gui Editor (NetBeans in meinem Falle) wiederverwendbar ist (also ein JavaBean), der man ein Bild übergeben kann und bei der die Ecken abgerundet sind. Wenn möglich, wollen wir sogar noch einen Rahmen setzen können. Ein kurzer Blick auf die Seite “Painting in AWT and Swing” zeigt, dass wir paintComponent() überschreiben sollten. Die Componente soll sich der Einfachheit halber der Größe des Bildes automatisch anpassen.

    Die fertige Klasse sieht dann so aus:

    public class ThumbPanel extends JPanel {
    
        protected BufferedImage image = null;
        public static final String PROP_IMAGE = "image";
        protected int roundness = 10;
        public static final String PROP_ROUNDNESS = "roundness";
    
        public ThumbPanel() {
            init();
        }
    
        private void init() {
            setOpaque(false);
        }
    
        protected void update() {
            if (image != null) {
                setSize(image.getWidth(), image.getHeight());
                setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
            }
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            if (image == null) {
                return;
            }
            g.setClip(new RoundRectangle2D.Double(0, 0, image.getWidth(), image.getHeight(), roundness, roundness));
            g.drawImage(image, 0, 0, null);
            g.setClip(null);
        }
    
        public int getRoundness() {
            return roundness;
        }
    
        public void setRoundness(int roundness) {
            int oldRoundness = this.roundness;
            this.roundness = roundness;
            firePropertyChange(PROP_ROUNDNESS, oldRoundness, roundness);
            update();
        }
    
        public BufferedImage getImage() {
            return image;
        }
    
        public void setImage(BufferedImage image) {
            BufferedImage oldImage = this.image;
            this.image = image;
            firePropertyChange(PROP_IMAGE, oldImage, image);
            update();
        }
    }

    Getter und Setter sind selbsterklärend. Update() passt die Komponente der aktuellen Größe an. Ein Null-Images possiert in meinem Anwendungsfall nicht, wäre aber offenbar kein Problem das anzupassen. PaintComponent() setzt die Clip-Eigenschaft und malt dann das Bild auf die Komponente – fertig! Das ganze sieht dann so aus:

    rounded corners ISo weit so gut. Nun will man aber vielleicht noch einen Rahmen (=Border) dazufügen. Standard Borders sehen dabei nicht ganz so praktikabel aus, da sie an den Ecken abgeschnitten werden. Also muss wohl oder übel eine eigene Border her. Schön wäre ein Rahmen, bei dem man Farbe, Dicke und Rundung einstellen kann. Der Versuch, die LineBorder zu extenden war nicht wirklich von Erfolg gekrönt, da man dabei Dicke und Rundung nicht separat einstellen kann.

    Also selber malen. Linien mit RoundRectangle2Ds zu zeichnen, wollte nie so wirklich schön werden. Insbesondere sobald die Dicke > 1 Pixel sein sollte. Alternative: Roundrect fill und innen wieder Clip’en.  Nur dumm, dass sich das Clip dann auch auf das Bild übertragen hatte. Also per AlphaComposite das Innere einfach ausschneiden. Damit auch bei mehrfachen repaints, nicht immer ein BufferedImage für den Rahmen erzeugt werden muss, wird das Ergebnis einfach gecached. Die ganze klasse sieht dann so aus:

    public class MyRoundBorder implements Border {
    
        private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
        protected int roundness = 10;
        public static final String PROP_ROUNDNESS = "roundness";
        protected Color color = Color.BLACK;
        public static final String PROP_COLOR = "color";
        protected int thickness = 1;
        public static final String PROP_THICKNESS = "thickness";
        // buffer the created image because recreating a complete image could waste precious time
        protected SoftReference cache = new SoftReference(null);
        protected Rectangle oldR = new Rectangle();
        protected Rectangle oldC = new Rectangle();
    
        public MyRoundBorder() {
        }
    
        public MyRoundBorder(int roundness, Color color, int thickness) {
            this.roundness = roundness;
            this.color = color;
            this.thickness = thickness;
        }
    
        public int getThickness() {
            return thickness;
        }
    
        public void setThickness(int thickness) {
            int oldThickness = this.thickness;
            this.thickness = thickness;
            propertyChangeSupport.firePropertyChange(PROP_THICKNESS, oldThickness, thickness);
            cache = new SoftReference(null);
        }
    
        public Color getColor() {
            return color;
        }
    
        public void setColor(Color color) {
            Color oldColor = this.color;
            this.color = color;
            propertyChangeSupport.firePropertyChange(PROP_COLOR, oldColor, color);
            cache = new SoftReference(null);
        }
    
        public int getRoundness() {
            return roundness;
        }
    
        public void setRoundness(int roundness) {
            int oldRoundness = this.roundness;
            this.roundness = roundness;
            propertyChangeSupport.firePropertyChange(PROP_ROUNDNESS, oldRoundness, roundness);
            cache = new SoftReference(null);
        }
    
        public void addPropertyChangeListener(PropertyChangeListener listener) {
            propertyChangeSupport.addPropertyChangeListener(listener);
        }
    
        public void removePropertyChangeListener(PropertyChangeListener listener) {
            propertyChangeSupport.removePropertyChangeListener(listener);
        }
    
        @Override
        public void paintBorder(Component c, Graphics g1, int x, int y, int width, int height) {
            Graphics2D g = (Graphics2D) g1;
    
            BufferedImage buffered = cache.get();
            Rectangle newR = new Rectangle(x, y, width, height);
            if (buffered == null || !c.getBounds().equals(oldC) || !oldR.equals(newR)) {
                buffered = new BufferedImage(c.getWidth(), c.getHeight(), BufferedImage.TYPE_INT_ARGB);
                Graphics2D tmpg = buffered.createGraphics();
                tmpg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                tmpg.setClip(g1.getClip());
                tmpg.setColor(color);
                // fill area
                tmpg.fillRoundRect(x, y, width, height, roundness, roundness);
                // cut out inner
                tmpg.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OUT));
                tmpg.fillRoundRect(x + thickness, y + thickness, width - (2 * thickness), height - (2 * thickness), roundness, roundness);
                tmpg.dispose();
    
                cache = new SoftReference(buffered);
                c.getBounds(oldC);
                oldR = newR;
            }
            // draw border upon image
            g.drawImage(buffered, 0, 0, null);
        }
    
        @Override
        public Insets getBorderInsets(Component c) {
            return new Insets(thickness, thickness, thickness, thickness);
        }
    
        @Override
        public boolean isBorderOpaque() {
            return true;
        }
    }

    Die Getter/Setter sind wieder dazu da, eine schöne JavaBean zu bauen, damit die Border auch im GUI Editor einfach zu verwenden ist.

    Da normale Borders verwendet werden können, kann natürlich auch eine CompoundBorder verwendet werden – um zum Beispiel anzuzeigen, wenn ein Bild selektiert ist (dann zB mit zusätzlichem weißen Innenrahmen), was dann so aussieht (links einfach, rechts Compond):

    CompoundBorder II