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

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

有没有办法在图表中间显示一个项目?

使用图表从数据库输出值。

我想将下一项放在每个馅饼的中心。

有办法吗?下面是代码。

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);
        }

    }

}

我尝试使用 Shape 绘制圆弧并使用 Area 计算填充圆弧的中心。

它做得还不错,但并不完美:

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);
        });
    }
}

对 centerX/Y 值的调整是使用图形 class 的真实 FontMetrics 的快捷方式。 X值应该是你绘制的文本宽度的一半,Y值应该是你绘制的高度测试。您可以尝试使用真正的 FontMetrics 看看它是否有所作为。

注意,这是一个“最小的、可重现的例子”的例子。示例中仅包含与问题直接相关的代码。任何人都可以 copy/paste/compile 和文本。将来所有的问题都应该包括一个 MRE 来证明问题。

编辑:

我的第二次尝试是尝试使用 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);
        });
    }
}

不知道为什么我在将角度转换为弧度时需要添加“90”?