{"id":459,"date":"2015-09-23T14:00:33","date_gmt":"2015-09-23T12:00:33","guid":{"rendered":"http:\/\/lukas.kurth.rocks\/blog\/?p=459"},"modified":"2015-09-23T14:00:33","modified_gmt":"2015-09-23T12:00:33","slug":"matrix-prozess-monitor","status":"publish","type":"post","link":"https:\/\/lukas.kurth.rocks\/blog\/2015\/09\/23\/matrix-prozess-monitor\/","title":{"rendered":"Matrix Prozess Monitor"},"content":{"rendered":"<p>Hey Leute,<\/p>\n<p style=\"text-align: justify;\">lange nichts mehr von mir gegeben. Habe die letzten Monate so vor mich her programmiert. Zwischenzeitlich hatten wir hier auch einen Praktikanten, der mir bei meinem Java-Projekt weitergeholfen hat. So konnte ich meine etwas \u00fcberladene Swing-GUI beiseite legen und mit dem Spring Framework eine Seite gestalten (ist bei Applikationen die auf dem Server laufen eh zu empfehlen \ud83d\ude42 ).<\/p>\n<p style=\"text-align: justify;\">Jetzt nachdem der Praktikant nicht mehr da ist g\u00e4be es zwar noch ein paar Sachen die angepasst werden m\u00fcssten, aber ich komme klar \ud83d\ude09<\/p>\n<p style=\"text-align: justify;\">Die Tage gab es dann mal wieder eine rege Diskussion zu Matrix (dem Film), was denn m\u00f6glich ist und was \u00fcberhaupt mit Matrix gemeint ist (es ist wirklich nur ein Film Leute \ud83d\ude09 ). Allerdings finde ich die Idee mit dem, wie soll man ich sonst nennen, <em><strong>&#8222;Matrix-Regen&#8220;<\/strong><\/em> gar nicht mal schlecht. Richtig angeordnet und richtig gelesen, k\u00f6nnte er viele Informationen enthalten. Diese Informationen lassen sich dann auch schneller wiedergeben als nur simpler Text.<\/p>\n<p style=\"text-align: justify;\">Ein Programm habe ich ja, fehlt also nur der Regen. Als Basis habe ich mal den <a href=\"https:\/\/kenai.com\/projects\/trident\/sources\/source\/content\/src\/test\/swing\/MatrixRain.java\" target=\"_blank\">Code von Kenai<\/a> zu Grunde genommen. Hier wird allerdings nur 40 mal der addDrop() ausgef\u00fchrt und dann so lange selbst aufgerufen bis man das Programm beendet.<\/p>\n<p style=\"text-align: justify;\">Um mit dem Programm zu arbeiten also erst einmal eine Interface-Klasse gebastelt, bei mir sieht diese in etwa so aus:<\/p>\n<p style=\"text-align: justify;\"><!--more--><\/p>\n<pre class=\"\">import java.awt.*;\r\nimport java.util.concurrent.CopyOnWriteArrayList;\r\n\r\n\/**\r\n * Interface between Monitor and other javaClasses\r\n *\r\n * @author lkurth on 23.09.2015\r\n * @since 1.2\r\n *\/\r\n\r\npublic class MonitorInterface {\r\n    private static MonitorInterface instance;\r\n    private CopyOnWriteArrayList&lt;Color[]&gt; dropList =  new CopyOnWriteArrayList&lt;&gt;();\r\n\r\n    \/**\r\n     * Adding a drop to the monitoring service\r\n     *\r\n     * @param type    the type of the message:&lt;ul&gt;\r\n     *                      &lt;li&gt;e - for errors&lt;\/li&gt;\r\n     *                      &lt;li&gt;w - for warnings&lt;\/li&gt;\r\n     *                      &lt;li&gt;i - for information&lt;\/li&gt;\r\n     *                      &lt;li&gt;d - for debug&lt;\/li&gt;\r\n     *                      &lt;li&gt;n - for normal \/ default&lt;\/li&gt;&lt;\/ul&gt;\r\n     *\/\r\n    public void addDrop(char type) {\r\n        Color color1, color2;\r\n\r\n        switch (type) {\r\n            case 'e':   \/\/ errors\r\n                \/\/color1 = new Color(255, 175, 175); \/\/ pink\r\n                color1 = new Color(255, 0, 0); \/\/ brighter red\r\n                color2 = new Color(144, 0, 0); \/\/ darker red\r\n                break;\r\n            case 'w':   \/\/ warnings\r\n                color1 = new Color(255, 200, 0); \/\/ yellow \/ orange\r\n                color2 = new Color(255, 80, 0); \/\/ orange\r\n                break;\r\n            case 'i':   \/\/ information\r\n                color1 = new Color(0, 255, 255); \/\/ cyan\r\n                color2 = new Color(0, 0, 255); \/\/ blue\r\n                break;\r\n            case 'd':   \/\/ debug\r\n                color1 = new Color(128, 128, 128); \/\/ grey\r\n                color2 = new Color(78, 78, 78); \/\/ darker grey\r\n                break;\r\n            case 'n':   \/\/ normal and default\r\n            default:\r\n                color1 = new Color(255, 255, 255); \/\/ white\r\n                color2 = new Color(0, 255, 0); \/\/ green\r\n        }\r\n\r\n        \/\/ adding color to the list\r\n        Color[] ca = {color1, color2};\r\n        dropList.add(ca);\r\n    }\r\n\r\n    \/**\r\n     * Gets the complete {@link #dropList DropList}\r\n     *\r\n     * @return the complete {@link #dropList DropList} as {@link java.util.concurrent.CopyOnWriteArrayList CopyOnWriteArrayList}.\r\n     * Though {@link java.util.ArrayList ArrayList} may produce {@link java.util.ConcurrentModificationException ConcurrentModificationException} while accessing it.\r\n     *\r\n     * @see #emptyList\r\n     * @see java.util.concurrent.CopyOnWriteArrayList\r\n     * @see java.util.ArrayList\r\n     *\/\r\n    CopyOnWriteArrayList&lt;Color[]&gt; getList() {\r\n        return dropList;\r\n    }\r\n\r\n    \/**\r\n     * Just emptying the {@link #dropList DropList}.\r\n     *\/\r\n    void emptyList() {\r\n        dropList.clear();\r\n    }\r\n\r\n    \/**\r\n     * @return an instance of the interface\r\n     *\/\r\n    public static MonitorInterface getInstance() {\r\n        if (instance == null)\r\n            instance = new MonitorInterface();\r\n\r\n        return instance;\r\n    }\r\n}<\/pre>\n<p style=\"text-align: justify;\">Hier\u00a0wird dann f\u00fcr jeden \u00fcbergebenen Drop eine Farb-Kombination in einer ArrayList gespeichert und bei Bedarf vom eigentlichen &#8222;Monitor-Thread&#8220; ausgelesen und verarbeitet.<\/p>\n<p style=\"text-align: justify;\">Den Monitor (Matrix.java) habe ich dann wie folgt ge\u00e4ndert:<\/p>\n<ul>\n<li style=\"text-align: justify;\">Zwei Variablen f\u00fcr die Farbe deklariert und bei der Interpolation hinterlegt<\/li>\n<li style=\"text-align: justify;\">Die while Schleife im Matrix-Panel auskommentiert (m\u00f6glicherweise brauche ich es doch noch) und einen Thread hinzugef\u00fcgt (zum Aufrufen und Auswerten vom Interface).<\/li>\n<li style=\"text-align: justify;\">Eine zweite addDrop() Funktion erstellt zum \u00e4ndern der Farben<\/li>\n<\/ul>\n<p>Abge\u00e4ndert sieht er in meinem Fall also so aus:<\/p>\n<pre class=\"lang:java decode:true \" title=\"Monitor.java\">import org.pushingpixels.trident.Timeline;\r\nimport org.pushingpixels.trident.TimelineScenario;\r\nimport org.pushingpixels.trident.swing.SwingRepaintTimeline;\r\n\r\nimport javax.swing.*;\r\nimport java.awt.*;\r\nimport java.awt.event.ComponentAdapter;\r\nimport java.awt.event.ComponentEvent;\r\nimport java.io.InputStream;\r\nimport java.util.*;\r\nimport java.util.List;\r\nimport java.util.Timer;\r\nimport java.util.concurrent.CopyOnWriteArrayList;\r\n\r\n\/**\r\n * This class is created in memory of Matrix.java\r\n * It will be used to display current processes.\r\n *\r\n * @author lkurth on 23.09.2015\r\n * @since 1.2\r\n *\/\r\n\r\npublic class Monitor {\r\n    private static Font font;\r\n    private static Color fc1 = new Color(255, 255, 255); \/\/ from this color\r\n    private static Color fc2 = new Color(0, 255, 0); \/\/ into this\r\n\r\n    public static class Letter {\r\n        private final int x;\r\n        private final int y;\r\n        private Color color;\r\n        private float opacity;\r\n        private final char c;\r\n\r\n        public Letter(int x, int y, char c) {\r\n            this.x = x;\r\n            this.y = y;\r\n            this.c = c;\r\n            this.color = Color.white;\r\n            this.opacity = 0.0f;\r\n        }\r\n\r\n        @SuppressWarnings(\"unused\")\r\n        public void setOpacity(float opacity) {\r\n            this.opacity = opacity;\r\n        }\r\n\r\n        @SuppressWarnings(\"unused\")\r\n        public void setColor(Color color) {\r\n            this.color = color;\r\n        }\r\n\r\n        public void paint(Graphics g) {\r\n            if (this.opacity == 0.0f)\r\n                return;\r\n\r\n            Graphics2D g2d = (Graphics2D) g.create();\r\n            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,\r\n                    RenderingHints.VALUE_TEXT_ANTIALIAS_ON);\r\n            g2d.setFont(font);\r\n            g2d.setColor(this.color);\r\n            g2d.setComposite(AlphaComposite.SrcOver.derive(this.opacity));\r\n            g2d.drawString(\"\" + this.c, this.x, this.y);\r\n\r\n            g2d.dispose();\r\n        }\r\n    }\r\n\r\n    public static class Drop {\r\n        private final java.util.List&lt;Letter&gt; letters;\r\n\r\n        public Drop() {\r\n            this.letters = new ArrayList&lt;&gt;();\r\n        }\r\n\r\n        public TimelineScenario getScenario(int x) {\r\n            TimelineScenario result = new TimelineScenario.Parallel();\r\n            Random randomizer = new Random();\r\n            \/\/ how many letters will there be?\r\n            int totalLetterCount = 5 + randomizer.nextInt(20); \/\/ length in general (line)\r\n            \/\/int totalLetterCount = 30;\r\n            int initialDelay = randomizer.nextInt(1000);\r\n            int duration = 1000 + randomizer.nextInt(100); \/\/ tail\r\n            for (int i = 0; i &lt; totalLetterCount; i++) {\r\n                int y = font.getSize() * i;\r\n                \/\/ choose random katakana letter\r\n                \/\/ int letterIndex = (int) (0x30A0 + Math.random()\r\n                \/\/ * (0x30FF - 0x30A0));\r\n                int start = 33;\r\n                int delta = 95;\r\n                char c = 0;\r\n                while (c == 0 || c == ' ' || c == '\\u007F') \/\/ no spaces in line\r\n                    c = (char) (start + Math.random() * delta);\r\n                \/\/ System.out.print(c + \",\"); \/\/ see whats coming ;-)\r\n                Letter l = new Letter(x, y, c);\r\n                this.letters.add(l);\r\n                Timeline t = new Timeline(l);\r\n                t.addPropertyToInterpolate(\"opacity\", 1.0f, 0.0f);\r\n                t.addPropertyToInterpolate(\"color\", fc1, fc2); \/\/ white, green\r\n                t.setDuration(duration);\r\n                t.setInitialDelay(initialDelay + i * 120);\r\n                result.addScenarioActor(t);\r\n            }\r\n            return result;\r\n        }\r\n\r\n        \/\/ paint the letter\r\n        public void paint(Graphics g) {\r\n            for (Letter l : this.letters)\r\n                l.paint(g);\r\n        }\r\n    }\r\n\r\n    \/**\r\n     * This is the main class of the Monitor.java.\r\n     * The thread reading the drops is placed inside of the {@link java.awt.event.ComponentListener ComponentListener}\r\n     *\/\r\n    public static class MatrixPanel extends JPanel {\r\n        private final List&lt;Drop&gt; drops;\r\n\r\n        public MatrixPanel() {\r\n            try {\r\n                InputStream is = MxRain.class.getClassLoader()\r\n                        .getResourceAsStream(\"fonts\/katakana.ttf\");\r\n                Font kf = Font.createFont(Font.TRUETYPE_FONT, is);\r\n                int fontSize = 14;\r\n                \/\/ Font kf = new Font(\"monospaced\", Font.PLAIN, fontSize); \/\/ if katakana.ttf can't be used\r\n                font = kf.deriveFont(Font.BOLD, fontSize);\r\n            } catch (Exception exc) {\r\n                exc.printStackTrace();\r\n            }\r\n\r\n            Timeline repaint = new SwingRepaintTimeline(this);\r\n            repaint.playLoop(Timeline.RepeatBehavior.LOOP);\r\n\r\n            this.drops = new ArrayList&lt;&gt;();\r\n            this.addComponentListener(new ComponentAdapter() {\r\n                @Override\r\n                public void componentResized(ComponentEvent e) {\r\n                    \/* this will add a specific number (40) of repeating drops * \/\r\n                    while (drops.size() &lt; 40)\r\n                        addDrop();\r\n                    \/**\/\r\n\r\n                    \/\/ start a task to check for monitor colors (arrayList)\r\n                    MonitorInterface mii = MonitorInterface.getInstance();\r\n                    TimerTask monitorTask = new TimerTask() {\r\n                        @Override\r\n                        public void run() {\r\n                            if (mii.getList().size() &gt; 0) {\r\n                                CopyOnWriteArrayList&lt;Color[]&gt; colors = mii.getList();\r\n                                for (Color[] cl : colors)\r\n                                    addDrop(cl[0], cl[1]);\r\n                                mii.emptyList();\r\n                            }\r\n                        }\r\n                    };\r\n                    Timer timer = new Timer(\"Monitor Timer\");\r\n                    timer.scheduleAtFixedRate(monitorTask, 30, 500); \/\/ check every x seconds\r\n                }\r\n            });\r\n        }\r\n        \r\n        \/**\r\n         * this synchronized method was used to add its own drop in a loop (matrix like).\r\n         * now it just adds it once and removes when the callback method is called.\r\n         *\/\r\n        private synchronized void addDrop() {\r\n            final Drop drop = new Drop();\r\n            TimelineScenario scenario = drop.getScenario(new Random()\r\n                    .nextInt(getWidth()));\r\n            scenario.addCallback(() -&gt; {\r\n                synchronized (MatrixPanel.this) {\r\n                    drops.remove(drop);\r\n                    \/\/addDrop(); \/\/ not adding again (loop)\r\n                }\r\n            });\r\n            this.drops.add(drop);\r\n            scenario.play();\r\n        }\r\n\r\n        \/**\r\n         * sets the color\r\n         * \r\n         * @param color1    the first color\r\n         * @param color2    the color to fade into\r\n         *                  \r\n         * @see #addDrop()\r\n         *\/\r\n        protected void addDrop(Color color1, Color color2) {\r\n            if (color1 != null &amp;&amp; color2 != null) {\r\n                fc1 = color1;\r\n                fc2 = color2;\r\n            }\r\n\r\n            addDrop();\r\n        }\r\n\r\n        @Override\r\n        protected void paintComponent(Graphics g) {\r\n            g.setColor(Color.black);\r\n            g.fillRect(0, 0, getWidth(), getHeight());\r\n\r\n            synchronized (this) {\r\n                for (Drop drop : this.drops)\r\n                    drop.paint(g);\r\n            }\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p style=\"text-align: justify;\">Entgegen der Meldung der IDE (zumindest bei IDEA)\u00a0werden die beiden\u00a0Funktionen der Klasse Letter doch verwendet. Wie sie verwendet werden kann die\u00a0IDE\u00a0nur nicht wissen\/ahnen.<\/p>\n<p style=\"text-align: justify;\">Nun kann \u00fcber das Interface jedes Mal ein drop hinzugef\u00fcgt werden. Beispielsweise an allen Stellen, an denen ein Fehler auftritt (try, catch, exceptions). Dazu einfach nur folgenden Code an die beliebige Stelle einf\u00fcgen:<\/p>\n<pre class=\"toolbar:2 lang:java decode:true\">monitor.addDrop('e');<\/pre>\n<p style=\"text-align: justify;\"><span style=\"text-decoration: underline;\"><strong>Bemerkung<\/strong><\/span>: Wenn man das Spring Framework verwendet (oder irgendein anderes Framework, welches die Nutzung einer GUI eigentlich \u00fcberfl\u00fcssig macht, kann dies mit folgenden Zeilen umgehen:<\/p>\n<pre class=\"lang:java decode:true\" title=\"Headless\">\/\/ to show a gui we have to be headless ;P\r\nSystem.setProperty(\"java.awt.headless\", \"false\");\r\n\/\/ create Matrix process monitor\r\nif (!java.awt.GraphicsEnvironment.isHeadless())\r\n    SwingUtilities.invokeLater(() -&gt; {\r\n        \/\/ code here\r\n    });<\/pre>\n<p>Ob Nick damit etwas zu tun hat? ;P<\/p>\n<p>Also ich mag den Prozess Monitor. Vielleicht kann ich ihn ja noch etwas ausbauen. Bis dahin&#8230;<\/p>\n<p>Viel Spa\u00df<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey Leute, lange nichts mehr von mir gegeben. Habe die letzten Monate so vor mich her programmiert. Zwischenzeitlich hatten wir hier auch einen Praktikanten, der mir bei meinem Java-Projekt weitergeholfen hat. So konnte ich meine etwas \u00fcberladene Swing-GUI beiseite legen und mit dem Spring Framework eine Seite gestalten (ist bei Applikationen die auf dem Server [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,5,17,9,13],"tags":[266,254,261,265,255,256,250,270,262,273,257,275,116,271,253,267,249,272,258,264,274,269,259,260,252,263,251,206,268],"class_list":["post-459","post","type-post","status-publish","format-standard","hentry","category-allgemein","category-it","category-java","category-programmierung","category-tips","tag-arraylist","tag-code","tag-color","tag-copyonwritearraylist","tag-drop","tag-droplist","tag-film","tag-font","tag-green","tag-headless","tag-interface","tag-invokelater","tag-java","tag-katakana","tag-kenai","tag-letter","tag-matrix","tag-mii","tag-monitor","tag-neo","tag-nick","tag-paint","tag-process","tag-prozess","tag-rain","tag-red","tag-regen","tag-thread","tag-unused"],"_links":{"self":[{"href":"https:\/\/lukas.kurth.rocks\/blog\/wp-json\/wp\/v2\/posts\/459","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lukas.kurth.rocks\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lukas.kurth.rocks\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lukas.kurth.rocks\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lukas.kurth.rocks\/blog\/wp-json\/wp\/v2\/comments?post=459"}],"version-history":[{"count":16,"href":"https:\/\/lukas.kurth.rocks\/blog\/wp-json\/wp\/v2\/posts\/459\/revisions"}],"predecessor-version":[{"id":475,"href":"https:\/\/lukas.kurth.rocks\/blog\/wp-json\/wp\/v2\/posts\/459\/revisions\/475"}],"wp:attachment":[{"href":"https:\/\/lukas.kurth.rocks\/blog\/wp-json\/wp\/v2\/media?parent=459"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lukas.kurth.rocks\/blog\/wp-json\/wp\/v2\/categories?post=459"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lukas.kurth.rocks\/blog\/wp-json\/wp\/v2\/tags?post=459"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}