Удар : пока я переносил свой старый контент блога, я нашел его 3 года назад. Это все еще выглядит в стиле фанк, поэтому я решил дать ему удар. Наслаждаться.
Некоторое время назад Javalobby опубликовал прекрасную статью о том, как кто-то создал доску сообщений о событиях, напоминающую доску отправлений в аэропорту или на вокзале.
Мне нужно было освежить свои навыки Java2D, поэтому я начал с чего-то простого, что было вдохновлено этой статьей: 16-сегментный символьный дисплей (как описано здесь ). Он должен использовать только Java2D (без изображений) и отображать AZ и 0-9.
После вечернего рисования на бумажной сетке это конечный результат:
Код разделен на 3 части: компонент с одним символом, компонент группы символов, способный отображать строку и определение алфавита.
Сначала я покажу односимвольный компонент:
public class SixteenSegmentDisplay extends JComponent { private java.util.List<Integer> lightedSegments; public static final int WIDTH = 29; public static final int HEIGHT = 46; private final double INACTIVE_COLOR_DARKEN_FRACTION = 0.4; private static final Image BACKGROUND_IMAGE = createBackgroundImage(); // Highlight Colors private static final java.awt.Color HIGHLIGHT_COLOR_TOP = new java.awt.Color(0x000000); private static final java.awt.Color HIGHLIGHT_COLOR_BOTTOM = new java.awt.Color(0x625C52); private Color activeSegmentColor = new Color(0xFF0000); private Color inactiveSegmentColor = darken(new Color(0xFF0000), INACTIVE_COLOR_DARKEN_FRACTION); private Color backgroundColor = Color.black; public SixteenSegmentDisplay() { lightedSegments = new ArrayList<Integer>(); } @Override public java.awt.Dimension getSize() { return new Dimension(WIDTH, HEIGHT); } @Override public java.awt.Dimension getPreferredSize() { return new Dimension(WIDTH, HEIGHT); } @Override public java.awt.Dimension getSize(java.awt.Dimension rv) { return new Dimension(WIDTH, HEIGHT); } public void setSegmentColor(Color segmentColor) { activeSegmentColor = segmentColor; inactiveSegmentColor = darken(segmentColor, INACTIVE_COLOR_DARKEN_FRACTION); } public void setBackgroundColor(Color backgroundColor) { this.backgroundColor = backgroundColor; } public void setCharacter(char character) { setLightedSegments(SixteenSegmentAlfabet.MAP.get(character)); } private void setLightedSegments(SixteenSegmentAlfabet character) { if (character != null && character.getSegments() != null) this.lightedSegments = Arrays.asList(character.getSegments()); else this.lightedSegments = new ArrayList<Integer>(0); this.repaint(); } private Color darken(Color c, double fragment) { Double newRed = fragment * c.getRed(); Double newBlue = fragment * c.getBlue(); Double newGreen = fragment * c.getGreen(); return new Color(newRed.intValue(), newGreen.intValue(), newBlue.intValue()); } @Override public void paint(Graphics g) { Graphics2D graphics = (Graphics2D) g.create(); graphics.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, java.awt.RenderingHints.VALUE_ANTIALIAS_ON); graphics.setRenderingHint(java.awt.RenderingHints.KEY_ALPHA_INTERPOLATION, java.awt.RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); graphics.setRenderingHint(java.awt.RenderingHints.KEY_COLOR_RENDERING, java.awt.RenderingHints.VALUE_COLOR_RENDER_QUALITY); paintBackground(graphics); // left top to top middle paintSegment(graphics, lightedSegments.contains(1), getPoints("2,2;3,1;14,1;15,2;14,3;3,3;2,2")); // top middle to right top paintSegment(graphics, lightedSegments.contains(2), getPoints("15,2;16,1;27,1;28,2;27,3;16,3;15,2")); // left top to left middle paintSegment(graphics, lightedSegments.contains(3), getPoints("2,2;3,3;3,22;2,23;1,22;1,3;2,2")); // top left to middle middle paintSegment(graphics, lightedSegments.contains(4), getPoints("4,4;5,4;13,19;13,21;12,21;4,6;4,4")); // top middle to middle middle paintSegment(graphics, lightedSegments.contains(5), getPoints("15,2;14,3;14,22;15,23;16,22;16,3;15,2")); // top right to middle middle paintSegment(graphics, lightedSegments.contains(6), getPoints("25,4;26,4;26,6;18,21;17,21;17,19;25,4")); // top middle to right middle paintSegment(graphics, lightedSegments.contains(7), getPoints("28,2;29,3;29,22;28,23;27,22;27,3;28,2")); // left middle to middle middle paintSegment(graphics, lightedSegments.contains(8), getPoints("2,23;3,22;14,22;15,23;14,24;3,24;2,23")); // middle middle to right middle paintSegment(graphics, lightedSegments.contains(9), getPoints("15,23;16,22;27,22;28,23;27,24;16,24;15,23")); // left middle to bottom left paintSegment(graphics, lightedSegments.contains(10), getPoints("2,23;3,24;3,43;2,44;1,43;1,24;2,23")); // left bottom to middle middle paintSegment(graphics, lightedSegments.contains(11), getPoints("13,27;13,25;12,25;4,40;4,42;5,42;13,27")); // bottom middle to middle middle paintSegment(graphics, lightedSegments.contains(12), getPoints("15,23;16,24;16,43;15,44;14,43;14,24;15,23")); // bottom right to middle middle paintSegment(graphics, lightedSegments.contains(13), getPoints("17,25;18,25;26,40;26,42;25,42;17,27;17,25")); // right middle to bottom right paintSegment(graphics, lightedSegments.contains(14), getPoints("28,23;29,24;29,43;28,44;27,43;27,24;28,23")); // bottpm left to bottom middle paintSegment(graphics, lightedSegments.contains(15), getPoints("2,44;3,43;14,43;15,4;14,45;3,45;2,44")); // bottom middle to bottom right paintSegment(graphics, lightedSegments.contains(16), getPoints("15,244;16,43;27,43;28,44;27,45;16,45;15,44")); } private void paintBackground(Graphics2D g) { g.drawImage(BACKGROUND_IMAGE, 0, 0, this); } private static final BufferedImage createBackgroundImage() { GraphicsConfiguration gfxConf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); final BufferedImage IMAGE = gfxConf.createCompatibleImage(WIDTH, HEIGHT, Transparency.OPAQUE); Graphics2D g2 = IMAGE.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); g2.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); final java.awt.geom.Point2D START_INNER_BACKGROUND = new java.awt.geom.Point2D.Float(0, 0); final java.awt.geom.Point2D STOP_INNER_BACKGROUND = new java.awt.geom.Point2D.Float(0, HEIGHT); final float[] FRACTIONS_INNER_BACKGROUND = { 0.0f, 1.0f }; final Color[] COLORS_INNER_BACKGROUND = { new Color(0x3D3A31), new Color(0x232520) }; final LinearGradientPaint GRADIENT_INNER_BACKGROUND = new LinearGradientPaint(START_INNER_BACKGROUND, STOP_INNER_BACKGROUND, FRACTIONS_INNER_BACKGROUND, COLORS_INNER_BACKGROUND); g2.setPaint(GRADIENT_INNER_BACKGROUND); g2.fill(new java.awt.geom.Rectangle2D.Float(0, 0, WIDTH, HEIGHT)); // Highlight g2.setColor(HIGHLIGHT_COLOR_TOP); g2.drawLine(0, 0, WIDTH, 0); g2.setColor(HIGHLIGHT_COLOR_BOTTOM); g2.drawLine(0, HEIGHT, WIDTH, HEIGHT); g2.dispose(); return IMAGE; } private void paintSegment(Graphics2D g, boolean active, Point... points) { if (points != null) { g.setColor(active ? activeSegmentColor : inactiveSegmentColor); Polygon polygon = new Polygon(); for (Point point : points) { polygon.addPoint(point.x, point.y); } g.fillPolygon(polygon); } } private static Point[] getPoints(String coded) { if(coded.length() == 0) { return null; } java.util.List<Point> pointList = new ArrayList<Point>(); String[] points = coded.split(";"); for (String point : points) { String[] pointCoordinates = point.split(","); pointList.add(new Point(Integer.parseInt(pointCoordinates[0]), Integer.parseInt(pointCoordinates[1]))); } return pointList.toArray(new Point[pointList.size()]); } }
public enum SixteenSegmentAlfabet { A(new char[]{'a', 'A'}, 1, 2, 3, 7, 8, 9, 10, 14), B(new char[]{'b', 'B'}, 1, 2, 5, 7, 9, 12, 14, 15, 16), C(new char[]{'c', 'C'}, 1, 2, 3, 10, 15, 16), D(new char[]{'d', 'D'}, 1, 2, 5, 7, 12, 14, 15, 16), E(new char[]{'e', 'E'}, 1, 2, 3, 8, 9, 10, 15, 16), F(new char[]{'f', 'F'}, 1, 2, 3, 8, 10), G(new char[]{'g', 'G'}, 1, 2, 3, 9, 10, 14, 15, 16), H(new char[]{'h', 'H'}, 3, 7, 8, 9, 10, 14), I(new char[]{'i', 'I'}, 1, 2, 5, 12, 15, 16), J(new char[]{'j', 'J'}, 7, 10, 14, 15, 16), K(new char[]{'k', 'K'}, 3, 6, 8, 10, 13), L(new char[]{'l', 'L'}, 3, 10, 15, 16), M(new char[]{'m', 'M'}, 3, 4, 6, 7, 10, 14), N(new char[]{'n', 'N'}, 3, 4, 7, 10, 13, 14), O(new char[]{'o', 'O'}, 1, 2, 3, 7, 10, 14, 15, 16), P(new char[]{'p', 'P'}, 1, 2, 3, 6, 8, 10), Q(new char[]{'q', 'Q'}, 1, 2, 3, 7, 10, 13, 14, 15, 16), R(new char[]{'r', 'R'}, 1, 2, 3, 7, 8, 9, 10, 13), S(new char[]{'s', 'S'}, 1, 2, 3, 8, 9, 14, 15, 16), T(new char[]{'t', 'T'}, 1, 2, 5, 12), U(new char[]{'u', 'U'}, 3, 7, 10, 14, 15, 16), V(new char[]{'v', 'V'}, 3, 6, 10, 11), W(new char[]{'w', 'W'}, 3, 7, 10, 11, 13, 14), X(new char[]{'x', 'X'}, 4, 6, 11, 13), Y(new char[]{'y', 'Y'}, 4, 6, 12), Z(new char[]{'z', 'Z'}, 1, 2, 6, 11, 15, 16), BLANK(new char[]{' '}, null), ZERO(new char[]{'0'}, 1, 2, 3, 4, 7, 10, 13, 14, 15, 16), ONE(new char[]{'1'}, 7, 14), TWO(new char[]{'2'}, 1, 2, 7, 8, 9, 10, 15, 16), THREE(new char[]{'3'}, 1, 2, 7, 9, 14, 15, 16), FOUR(new char[]{'4'}, 3, 7, 8, 9, 14), FIVE(new char[]{'5'}, 1, 2, 3, 8, 13, 15, 16), SIX(new char[]{'6'}, 1, 2, 3, 8, 9, 10, 14, 15, 16), SEVEN(new char[]{'7'}, 1, 2, 7, 14), EIGHT(new char[]{'8'}, 1, 2, 3, 7, 8, 9, 10, 14, 15, 16), NINE(new char[]{'9'}, 1, 2, 3, 7, 8, 9, 14, 15, 16); private final Integer[] segments; private final char[] characters; public static final Map<Character, SixteenSegmentAlfabet> MAP; static { MAP = new HashMap<Character, SixteenSegmentAlfabet>(36); for (SixteenSegmentAlfabet alfabet : SixteenSegmentAlfabet.values()) { for (char character : alfabet.characters) { MAP.put(character, alfabet); } } } SixteenSegmentAlfabet(char[] characters, Integer... segments) { this.characters = characters; this.segments = segments; } public Integer[] getSegments() { return segments; } }
blic class MultiCharacterDisplay extends JComponent { private static final int GAP = 5; private int segmentDisplayCount; private List<SixteenSegmentDisplay> segmentDisplays; public MultiCharacterDisplay(int segmentDisplayCount) { this(segmentDisplayCount, Color.red); } public MultiCharacterDisplay(int segmentDisplayCount, Color segmentColor) { this.segmentDisplayCount = segmentDisplayCount; segmentDisplays = new ArrayList<SixteenSegmentDisplay>(segmentDisplayCount); setLayout(new FlowLayout(FlowLayout.LEFT, GAP, 0)); for (int i = 0; i < segmentDisplayCount; i++) { SixteenSegmentDisplay display = new SixteenSegmentDisplay(); display.setSegmentColor(segmentColor); segmentDisplays.add(display); add(display); } } public void setText(String text) { if (text.length() > segmentDisplayCount) { text = text.substring(0, segmentDisplayCount); } int i = 0; for (char c : text.toCharArray()) { segmentDisplays.get(i++).setCharacter(c); } } public static void main(String[] args) { String text = args[0]; MultiCharacterDisplay display = new MultiCharacterDisplay(text.length(), Color.GREEN); display.setText(text); JFrame frame = new JFrame(); frame.setBackground(Color.black); frame.getContentPane().setBackground(Color.black); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.getContentPane().add(display); frame.pack(); frame.setVisible(true); } }