`
xdoc
  • 浏览: 296273 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

超轻量Swing仪表盘组件

阅读更多
XDoc发布了8.2.5版本,新版本中增加了扩展组件:刻度盘,用于动态图示化展示数据
现在将它封装成一个Swing组件与大家分享,大家可以稍做调整画出更漂亮的仪表盘
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
 * 刻度盘
 * @author xdoc
 */
public class Tick extends JComponent {
    private static final int VALUE_FONT_SIZE = 18;
    private double from = 0;
    private double to = 10;
    private String type = "line";
    private double major = 1;
    private double minor = 0.1;
    private String value = "";
    private String unit = "";
    public double getFrom() {
        return from;
    }
    public Tick() {
        super();
        this.setPreferredSize(new Dimension(60, 60));
        this.setBackground(Color.WHITE);
    }
    public void setFrom(double from) {
        this.from = from;
    }
    public double getMajor() {
        return major;
    }
    public void setMajor(double major) {
        this.major = major;
    }
    public double getMinor() {
        return minor;
    }
    public void setMinor(double minor) {
        this.minor = minor;
    }
    public double getTo() {
        return to;
    }
    public void setTo(double to) {
        this.to = to;
    }
    public String getType() {
        return type;
    }
    /**
     * 直尺
     */
    public static final String LINE = "line";
    /**
     * 120度圆环
     */
    public static final String RING_120 = "ring120";
    public static final String RING_180 = "ring180";
    public static final String RING_240 = "ring240";
    /**
     * 圆盘
     */
    public static final String CIRCLE = "circle";
    public void setType(String type) {
        this.type = type;
    }
    public String getUnit() {
        return unit;
    }
    public void setUnit(String unit) {
        this.unit = unit;
    }
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
    public void paintComponent(Graphics g) {
        double w = this.getWidth();
        double h = this.getHeight();
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setColor(this.getBackground());
        g2.fillRect(0, 0, (int) w, (int) h);
        g2.setColor(this.getForeground());
        g2.setStroke(new BasicStroke(1));
        int fontSize = 14;
        g2.setFont(new Font(Font.SERIF, Font.PLAIN, fontSize));
        if (major <= 0) {
            major = to - from;
        }
        if (to > from) {
            if (type.startsWith("ring") || type.equals("circle")) {
                double angle;
                double angleStart;
                if (type.equals("circle")) {
                    angle = 360;
                    angleStart = Math.PI / 2;
                } else {
                    angle = toDouble(type.substring(4));
                    angleStart = (180 + (angle - 180) / 2) / 180 * Math.PI;
                }
                double r = angle <= 180 ? Math.min(w / 2, h) : Math.min(w / 2, h / 2);
                double voff = angle <= 180 ? 0 : r;
                double dunit = (angle / 180 * Math.PI) / (to - from);
                for (int i = 0; i <= (to - from) / major; i++) {
                    g2.draw(new Line2D.Double(Math.cos(angleStart - i * major * dunit) * r + w / 2, h - voff - Math.sin(angleStart - i * major * dunit) * r,
                            Math.cos(angleStart - i * major * dunit) * r * 0.75 + w / 2, h - voff - Math.sin(angleStart - i * major * dunit) * r * 0.75));
                    if (minor > 0 && i < (to - from) / major) {
                        for (int j = 1; j < major / minor; j++) {
                            if (i * major + j * minor < to - from) {
                                g2.draw(new Line2D.Double(Math.cos(angleStart - (i * major + j * minor) * dunit) * r + w / 2, h - voff - Math.sin(angleStart - (i * major + j * minor) * dunit) * r,
                                        Math.cos(angleStart - (i * major + j * minor) * dunit) * r * 0.875 + w / 2, h - voff - Math.sin(angleStart - (i * major + j * minor) * dunit) * r * 0.875));
                            }
                        }
                    }
                }
                if (value.length() > 0) {
                    double val = toDouble(value);
                    GeneralPath p = new GeneralPath();
                    p.moveTo(Math.cos(angleStart - (val - from) * dunit) * r * 0.875 + w / 2, h - voff - Math.sin(angleStart - (val - from) * dunit) * r * 0.875);
                    p.lineTo(Math.cos(angleStart - (val - from) * dunit + Math.PI * 0.5) * 2 + w / 2, h - voff - Math.sin(angleStart - (val - from) * dunit + Math.PI * 0.5) * 2);
                    p.lineTo(Math.cos(angleStart - (val - from) * dunit - Math.PI * 0.5) * 2 + w / 2, h - voff - Math.sin(angleStart - (val - from) * dunit - Math.PI * 0.5) * 2);
                    p.closePath();
                    g2.fill(p);
                }
            } else {
                if (w > h) {
                    double dunit = w / (to - from);
                    for (int i = 0; i <= (to - from) / major; i++) {
                        g2.draw(new Line2D.Double(i * major * dunit, 0, i * major * dunit, h - fontSize));
                        if (i < (to - from) / major && minor > 0) {
                            for (int j = 1; j < major / minor; j++) {
                                g2.draw(new Line2D.Double((i * major + j * minor) * dunit, 0, (i * major + j * minor) * dunit, (h - fontSize) / 2));
                            }
                        }
                    }
                    if (value.length() > 0) {
                        double val = toDouble(value);
                        GeneralPath p = new GeneralPath();
                        p.moveTo((val - from) * dunit, (h - fontSize) / 2);
                        p.lineTo((val - from) * dunit - 4, h - fontSize);
                        p.lineTo((val - from) * dunit + 4, h - fontSize);
                        p.closePath();
                        g2.fill(p);
                    }
                } else {
                    int max = (int) Math.max(getStrBounds(g2, format(from)).getWidth(), getStrBounds(g2, format(to)).getWidth());
                    double dunit = h / (to - from);
                    for (int i = 0; i <= (to - from) / major; i++) {
                        g2.draw(new Line2D.Double(0, h - i * major * dunit, w - max, h - i * major * dunit));
                        if (i < (to - from) / major && minor > 0) {
                            for (int j = 1; j < major / minor; j++) {
                                g2.draw(new Line2D.Double(0, h - (i * major + j * minor) * dunit, (w - max) / 2, h - (i * major + j * minor) * dunit));
                            }
                        }
                    }
                    if (value.length() > 0) {
                        double val = toDouble(value);
                        GeneralPath p = new GeneralPath();
                        p.moveTo((w - max) / 2, h - (val - from) * dunit);
                        p.lineTo(w - max, h - (val - from) * dunit - 4);
                        p.lineTo(w - max, h - (val - from) * dunit + 4);
                        p.closePath();
                        g2.fill(p);
                    }
                }
            }
        }
        if (to > from) {
            if (major > 0) {
                if (type.startsWith("ring") || type.equals("circle")) {
                    double angle;
                    double angleStart;
                    if (type.equals("circle")) {
                        angle = 360;
                        angleStart = Math.PI / 2;
                    } else {
                        angle = toDouble(type.substring(4));
                        angleStart = (180 + (angle - 180) / 2) / 180 * Math.PI;
                    }
                    double r = angle <= 180 ? Math.min(w / 2, h) : Math.min(w / 2, h / 2);
                    double voff = angle <= 180 ? 0 : r;
                    double dunit = (angle / 180 * Math.PI) / (to - from);
                    int xoff = 0;
                    int yoff = 0;
                    double strAngle;
                    for (int i = type.equals("circle") ? 1 : 0; i <= (to - from) / major; i++) {
                        String str;
                        str = format(from + i * major);
                        strAngle = (angleStart - i * major * dunit + Math.PI * 2) % (Math.PI * 2);
                        xoff = 0;
                        yoff = 0;
                        if (strAngle >= 0 && strAngle < Math.PI * 0.25) {
                            xoff = (int) -getStrBounds(g2, str).getWidth();
                            yoff = fontSize / 2;
                            if (strAngle == 0 && angle == 180) {
                                yoff = 0;
                            }
                        } else if (near(strAngle, Math.PI * 0.5)) {
                            xoff = (int) -getStrBounds(g2, str).getWidth() / 2;
                            yoff = fontSize;
                        } else if (strAngle >= Math.PI * 0.25 && strAngle < Math.PI * 0.5) {
                            xoff = (int) -getStrBounds(g2, str).getWidth();
                            yoff = fontSize;
                        } else if (strAngle >= Math.PI * 0.5 && strAngle < Math.PI * 0.75) {
                            yoff = fontSize;
                        } else if (strAngle >= Math.PI * 0.75 && strAngle < Math.PI) {
                            yoff = fontSize / 2;
                        } else if (near(strAngle, Math.PI)) {
                            xoff = 1;
                            yoff = fontSize / 2;
                            if (angle == 180) {
                                yoff = 0;
                            }
                        } else if (strAngle >= Math.PI && strAngle < Math.PI * 1.25) {
                            yoff = fontSize / 4;
                        } else if (near(strAngle, Math.PI * 1.5)) {
                            xoff = (int) -getStrBounds(g2, str).getWidth() / 2;
                        } else if (strAngle >= Math.PI * 1.5 && strAngle < Math.PI * 2) {
                            xoff = (int) -getStrBounds(g2, str).getWidth();
                        }
                        g2.drawString(str, (int) (Math.cos(strAngle) * r * 0.75 + w / 2) + xoff, (int) (h - voff - Math.sin(strAngle) * r * 0.75) + yoff);
                    }
                    g2.setFont(new Font("", Font.BOLD, VALUE_FONT_SIZE));
                    if (value.length() > 0) {
                        voff = angle <= 180 ? 10 : r - fontSize / 2;
                        drawValue(g2, value + unit, (int) (w / 2 - getStrBounds(g2, value).getWidth() / 2), (int) (h - voff));
                    }
                } else {
                    if (w > h) {
                        double dunit = w / (to - from);
                        int off = 0;
                        String str;
                        for (int i = 0; i <= (to - from) / major; i++) {
                            str = format(from + i * major);
                            if (i == 0) {
                                str += unit;
                                off = 0;
                            } else if (i == (to - from) / major) {
                                off = (int) -getStrBounds(g2, str).getWidth();
                            } else {
                                off = (int) (-getStrBounds(g2, str).getWidth() / 2);
                            }
                            g2.drawString(str, (int) (i * major * dunit) + off, (int) (h - 2));
                        }
                        if (value.length() > 0) {
                            double val = toDouble(value);
                            value = format(val);
                            if (val == from) {
                                off = 0;
                            } else if (val == to) {
                                off = (int) -getStrBounds(g2, value + unit).getWidth();
                            } else {
                                off = (int) (-getStrBounds(g2, value + unit).getWidth() / 2);
                            }
                            if ((h - fontSize) / 2 >= fontSize) {
                                drawValue(g2, value + unit, (int) ((val - from) * dunit) + off, (int) ((h - fontSize) / 2));
                            } else {
                                drawValue(g2, value + unit, (int) ((val - from) * dunit) + off, fontSize);
                            }
                        }
                    } else {
                        double dunit = h / (to - from);
                        int max = (int) Math.max(getStrBounds(g2, format(from)).getWidth(), getStrBounds(g2, format(to)).getWidth());
                        int off = 0;
                        for (int i = 0; i <= (to - from) / major; i++) {
                            if (i == 0) {
                                off = 0;
                            } else if (i == (to - from) / major) {
                                off = fontSize;
                            } else {
                                off = fontSize / 2;
                            }
                            g2.drawString(format(from + i * major), (int) (w - max + 1), (int) (h - i * major * dunit) + off);
                        }
                        if (unit.length() > 0) {
                            g2.drawString(unit, (int) ((w - max) / 2 + 1), (int) (h - fontSize));
                        }
                        if (value.length() > 0) {
                            double val = toDouble(value);
                            value = format(val);
                            if (val == 0) {
                                off = 0;
                            } else if (val == to) {
                                off = VALUE_FONT_SIZE;
                            } else {
                                off = VALUE_FONT_SIZE / 2;
                            }
                            drawValue(g2, value + unit, (int) ((w - getStrBounds(g2, value + unit).getWidth()) / 2), (int) (h - (val - from) * dunit + off));
                        }
                    }
                }
            }
        }
    }
    private void drawValue(Graphics2D g2, String value, int x, int y) {
        g2.setFont(new Font(Font.SERIF, Font.BOLD, VALUE_FONT_SIZE));
        g2.drawString(value, x, y);
    }
    private String format(double d) {
        if ((int) d == d) {
            return String.valueOf((int) d);
        } else {
            return String.valueOf(d);
        }
    }
    private double toDouble(String string) {
        try {
            return Double.valueOf(string);
        } catch (Exception e) {
            return 0;
        }
    }
    private boolean near(double d1, double d2) {
        return Math.round(d1 * 1000000) == Math.round(d2 * 1000000);
    }
    private static Rectangle2D getStrBounds(Graphics2D g, String str) {
        Font f = g.getFont();
        Rectangle2D rect = f.getStringBounds(str, g.getFontRenderContext());
        if (rect.getHeight() < f.getSize()) {
            rect.setFrame(rect.getX(), rect.getY(), rect.getWidth(), f.getSize() + 1);
        }
        return rect;
    }
    public static void main(String[] args) {
        try {
            JFrame f = new JFrame("刻度盘测试");
            Container p = f.getContentPane();
            Tick tick;
            tick = new Tick();
            tick.setType(Tick.LINE);
            tick.setValue("3");
            tick.setUnit("CM");
            p.add(tick, BorderLayout.NORTH);
            tick = new Tick();
            tick.setType(Tick.LINE);
            p.add(tick, BorderLayout.WEST);
            JPanel panel = new JPanel(new GridLayout(2, 2));
            tick = new Tick();
            tick.setForeground(Color.BLUE);
            tick.setType(Tick.RING_120);
            tick.setValue("3.5");
            tick.setUnit("A");
            panel.add(tick);
            tick = new Tick();
            tick.setType(Tick.RING_180);
            tick.setValue("6");
            tick.setUnit("V");
            panel.add(tick);
            tick = new Tick();
            tick.setType(Tick.RING_240);
            tick.setValue("3");
            tick.setUnit("Kg");
            panel.add(tick);
            tick = new Tick();
            tick.setType(Tick.CIRCLE);
            tick.setValue("3");
            tick.setUnit("Kg");
            tick.setBackground(Color.BLACK);
            tick.setForeground(Color.WHITE);
            panel.add(tick);
            p.add(panel, BorderLayout.CENTER);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setSize(640, 480);
            f.setVisible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}




虽然很简单,但放入XDoc中小虫就变小龙了,看看在XDoc中的表现吧:


  • 大小: 59.7 KB
  • 大小: 72.9 KB
  • 大小: 81 KB
分享到:
评论

相关推荐

    fastn, 创建超轻量用户界面组件.zip

    fastn, 创建超轻量用户界面组件 fastN创建超轻量用户界面组件 例如的主页,尝试它,例如示例应用程序用法创建fastN组件所需的绝对最小值:使用默认的DOM组件初始化 fastN:var fastn = require('fastn')

    中文检测超轻量训练模型

    随着人们对于高效、便捷中文字符处理的需求日益增长,特别是在移动设备和嵌入式系统等计算资源受限的场景中,对超轻量中文检测模型的需求显得尤为重要。这促使了专门的中文检测超轻量训练模型的诞生。 中文检测超轻...

    中文识别超轻量推理模型

    标题中的“中文识别超轻量推理模型”是指用于识别中文字符的一种高效、小型化的机器学习模型,主要用于文本检测和识别任务。在当前的AI领域,这样的模型被广泛应用于各种场景,如智能办公、文档处理、图像扫描等,...

    超轻量日志类

    "超轻量日志类"是一个专为C++设计的轻便型日志处理库,旨在提供高效且低开销的日志记录功能。在这个话题下,我们将深入探讨C++的日志实现、Visual Studio (VS) 集成以及轻量化设计的考量。 首先,让我们了解C++中的...

    一款超轻量、高性能、跨平台的嵌入式脚本语言,可以运行在Windows、Linux、MCU上

    一款超轻量、高性能、跨平台的嵌入式脚本语言,可以运行在Windows、Linux、MCU上。致力于打造一款开源、高效、强大的编程语言一款超轻量、高性能、跨平台的嵌入式脚本语言,可以运行在Windows、Linux、MCU上。致力于...

    基于AIO的超轻量HTTP服务器实现

    标题 "基于AIO的超轻量HTTP服务器实现" 指的是使用异步I/O(Asynchronous Input/Output,简称AIO)模型构建一个轻量级的HTTP服务器。AIO在Java中通常指的是NIO.2(New I/O 2),它提供了非阻塞I/O操作,能够更有效地...

    中文识别超轻量训练模型

    标题中的“中文识别超轻量训练模型”是指一种专门用于识别中文字符的深度学习模型,其特点是模型体积小,计算效率高,适用于资源有限的设备上进行实时或近实时的文字识别任务。这样的模型通常采用深度学习框架,如...

    中文检测超轻量推理模型

    标题中的“中文检测超轻量推理模型”是指一种专门用于识别和检测中文文本的轻量化机器学习或深度学习模型,这种模型在处理中文文本时,能够进行高效的推理和分析。在现代信息技术中,这种模型被广泛应用在自然语言...

    PaddleHub一键OCR中文识别(超轻量8.1M模型,火爆.doc

    总的来说,PaddleHub的一键OCR中文识别功能在CentOS 7上部署需要安装和配置多个组件,包括Python环境、依赖库以及可能的反向代理服务器。通过遵循上述步骤,你可以成功地在Linux服务器上搭建起一个高效的中文OCR识别...

    predicty:超轻量自动完成组件

    预测的超轻量自动完成组件。 目的是易于继承和扩展。用法快速示例: npm install predicty var Predicty = require ( 'predicty' ) ;var autocomplete = new Predicty ( ) ;autocomplete . items ( [ 'abc' , 'def' ...

    中英文超轻量PP-OCRv4模型

    【标题】"中英文超轻量PP-OCRv4模型" 涉及的核心知识点是光学字符识别(Optical Character Recognition, OCR)技术,特别是针对中文和英文的高效率、低资源消耗的模型设计。PP-OCRv4是PaddleOCR项目的一个重要版本,...

    GuiLite超轻量UI框架 v3.6.zip

    GuiLite超轻量UI框架 v3.6.zip

    机械键盘声音模拟超轻量小软件

    为了满足这部分用户的需求,开发者推出了“机械键盘声音模拟超轻量小软件”,以一种经济且便捷的方式提供类似的打字体验。 程序员在日常工作中需要处理大量的代码编写与调试,长时间的打字工作不仅要求键盘的可靠性...

    基于超轻量通道注意力的端对端语音增强方法.docx

    ### 基于超轻量通道注意力的端对端语音增强方法 #### 一、引言及背景 语音增强技术旨在提升目标语音的清晰度,去除背景噪声,这对于提高通信质量和效率至关重要。人类能轻松从嘈杂环境中识别出重要信息,而机器...

    Node.js-超轻量NPM包脚手架

    标题 "Node.js-超轻量NPM包脚手架" 提到的是一个专注于Node.js开发的工具,它致力于简化创建和管理NPM包的过程。在Node.js生态系统中,NPM(Node Package Manager)是用于管理和分发模块的平台,允许开发者共享和...

    GuiLite超轻量UI框架 v3.6-源码.zip

    GuiLite超轻量UI框架是面向嵌入式设备和物联网(IoT)应用设计的一款高效、小巧且易于使用的用户界面库。它旨在提供简洁的API和极低的内存占用,以便在资源有限的硬件上实现丰富的图形用户界面。版本v3.6带来了更多的...

    超轻量tcp实现源码【原创】

    超轻量级别的tcp协议实现框架 1、完全使用c语言编写,方便移植到windows以及linux 2、支持多sock以及并发处理 3、网络顶层接口定义简单,方便替换 4、测试代码为windows xp下,网络接口使用xfirewall.sys,局域网...

    超轻量 php 框架 startmvc v2.1.2.zip

    【超轻量 PHP 框架 StartMvc v2.1.2】 StartMvc 是一个针对初学者和小型项目设计的超轻量级 PHP 框架。它的主要目标是简化 Web 应用程序的开发过程,同时保持足够的灵活性,使得开发者能够快速构建高效能的应用。在...

    bashjumper是一个基于linux_bash的命令行下的超轻量跳板机。_bashjumper.zip

    bashjumper是一个基于linux_bash的命令行下的超轻量跳板机。_bashjumper

    一款超轻量高性能跨平台的嵌入式脚本语言可以运行在WindowsLinuxMCU上致力于打造一款开源高效强大的编程语言

    一款超轻量、高性能、跨平台的嵌入式脚本语言,可以运行在Windows、Linux、MCU上。致力于打造一款开源、高效、强大的编程语言。洛书(Losu) 编程语言,全称 Language Of Systemd Units ,超轻量、跨平台、易扩展、...

Global site tag (gtag.js) - Google Analytics