简体   繁体   English

有没有办法在 Swing 的自定义绘制图表中间显示一个项目?

[英]Is there a way to display an item in the middle of a custom painted chart in Swing?

Is there a way to display an item in the middle of the chart?有没有办法在图表中间显示一个项目?

Using the chart to output values from the database.使用图表从数据库中获取 output 值。

I'd like to place the next item in the center of each pie.我想将下一个项目放在每个馅饼的中心。

Is there a way?有办法吗? Below is the code.下面是代码。

这是图表图像

public class DrawingPiePanel extends JPanel {
    public DrawingPiePanel() {
    }

    private static final long serialVersionUID = 1L;

    Admin ad = Login.ad;

    String month = ad.year1 + "-01";

    kiosk_dao dao = new kiosk_dao();
    int Kor = dao.SelectSaleMonthRestaurant(month, "한식");
    int Ch = dao.SelectSaleMonthRestaurant(month, "중식");
    int Jp = dao.SelectSaleMonthRestaurant(month, "일식");
    int We = dao.SelectSaleMonthRestaurant(month, "양식");

    public void paint(Graphics g) {
        g.clearRect(0, 0, getWidth(), getHeight());

        int Total = Kor + Ch + Jp + We;
        if (Total != 0) {
            int arc1 = (int) 360.0 * Kor / Total;
            int arc2 = (int) 360.0 * Ch / Total;
            int arc3 = (int) 360.0 * Jp / Total;
            int arc4 = 360 - (arc1 + arc2 + arc3);

            double KorPer = (double) Kor / (double) Total * 100;
            double ChPer = (double) Ch / (double) Total * 100;
            double JpPer = (double) Jp / (double) Total * 100;
            double WePer = (double) We / (double) Total * 100;

            g.setColor(Color.YELLOW);
            g.fillArc(50, 20, 200, 200, 0, arc1);
            g.setColor(Color.RED);
            g.fillArc(50, 20, 200, 200, arc1, arc2);
            g.setColor(Color.BLUE);
            g.fillArc(50, 20, 200, 200, arc1 + arc2, arc3);
            g.setColor(Color.GREEN);
            g.fillArc(50, 20, 200, 200, arc1 + arc2 + arc3, arc4);
            g.setColor(Color.BLACK);
            g.setFont(new Font("굴림체", Font.PLAIN, 12));
            g.drawString(" 한식: 노랑" + String.format("%.2f", KorPer) + "%", 300, 150);
            g.drawString(" 중식: 빨강" + String.format("%.2f", ChPer) + "%", 300, 170);
            g.drawString(" 일식: 파랑" + String.format("%.2f", JpPer) + "%", 300, 190);
            g.drawString(" 양식: 초록" + String.format("%.2f", WePer) + "%", 300, 210);
            g.drawString(" 총매출액: " + Total + " 원", 300, 230);
        }

    }

}

I tried to use a Shape to draw the arcs and an Area to calculate the center of the filled arc.我尝试使用Shape来绘制弧线和Area来计算填充弧线的中心。

It does a reasonable job, but not perfect:它做得很合理,但并不完美:

import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.geom.*;

public class DrawPie extends JPanel
{
    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D)g.create();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        drawArc(g2d, Color.YELLOW, 0, 70, "Y");
        drawArc(g2d, Color.RED, 70, 80, "R");
        drawArc(g2d, Color.BLUE, 150, 90, "B");
        drawArc(g2d, Color.GREEN, 240, 120, "G");

        g2d.dispose();
    }

    private void drawArc(Graphics2D g2d, Color color, int start, int extent, String text)
    {
        g2d.setColor( color );
        Shape shape = new Arc2D.Double(50, 50, 200, 200, start, extent, Arc2D.PIE);
        g2d.fill( shape );

        Rectangle bounds = new Area(shape).getBounds();
        System.out.println(bounds);
        int centerX = bounds.x + (bounds.width / 2) - 5;
        int centerY = bounds.y + (bounds.height / 2) + 7;
        g2d.setColor( Color.BLACK );
        g2d.drawString(text, centerX, centerY);
    }

    @Override
    public Dimension getPreferredSize()
    {
        return new Dimension(300, 300);
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(() ->
        {
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.add(new JScrollPane(new DrawPie()));
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        });
    }
}

The adjustments to the centerX/Y values was a shortcut for using the real FontMetrics of the Graphics class.对 centerX/Y 值的调整是使用图形 class 的真实 FontMetrics 的捷径。 The X value should be half the width of the text you draw and the Y value should be the height test you draw. X 值应该是您绘制的文本宽度的一半,Y 值应该是您绘制的高度测试。 You can try playing with the real FontMetrics to see if it makes a difference.您可以尝试使用真正的 FontMetrics 看看它是否有所作为。

Note, this is an example of an "minimal, reproducible example".请注意,这是“最小的、可重现的示例”的示例。 Only the code directly related to the question is included in the example.示例中仅包含与问题直接相关的代码。 Anybody can copy/paste/compile and text.任何人都可以复制/粘贴/编译和文本。 In the future all questions should include an MRE to demonstrate the problem.将来所有的问题都应该包括一个 MRE 来证明问题。

Edit:编辑:

My second attempt which attempts to use Andrew's suggestion to determine a point on a line that is half the arc angle and half the radius.我的第二次尝试尝试使用 Andrew 的建议来确定直线上的一个点,该点是弧角的一半和半径的一半。

import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.geom.*;

public class DrawPie extends JPanel
{
    private int inset = 25;
    private int radius = 100;
    private int diameter = radius * 2;
    private int translation = inset + radius;

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D)g.create();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        drawArc(g2d, Color.YELLOW, 0, 70, "Y");
        drawArc(g2d, Color.RED, 70, 90, "R");
        drawArc(g2d, Color.CYAN, 160, 80, "B");
        drawArc(g2d, Color.GREEN, 240, 120, "G");

        g2d.dispose();
    }

    private void drawArc(Graphics2D g2d, Color color, int start, int extent, String text)
    {
        g2d.setColor( color );
        Shape shape = new Arc2D.Double(inset, inset, diameter, diameter, start, extent, Arc2D.PIE);
        g2d.fill( shape );

        double radians = Math.toRadians(90 + start + (extent / 2));
        int centerX = (int)(Math.sin(radians) * radius / 2);
        int centerY = (int)(Math.cos(radians) * radius / 2);
        g2d.setColor( Color.BLACK );
        g2d.drawString(text, centerX + translation, centerY + translation);
    }


    @Override
    public Dimension getPreferredSize()
    {
        int size = (inset * 2) + diameter;
        return new Dimension(300, 300);
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(() ->
        {
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.add(new JScrollPane(new DrawPie()));
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        });
    }
}

Don't know why I needed to add "90" when converting the angle to radians?不知道为什么在将角度转换为弧度时需要添加“90”?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM