有没有办法在 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”?
有没有办法在图表中间显示一个项目?
使用图表从数据库输出值。
我想将下一项放在每个馅饼的中心。
有办法吗?下面是代码。
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”?