在Swing中创建可变统计信息展示界面遇到的技术问题
嘿,恭喜你在Stack Overflow提第一个问题!别担心疏漏,大家都是从新手阶段过来的😉 我完全理解你的需求:做一个动态的统计展示界面,支持/反对两类统计项,每个项的名称要放在对应条形元素的上方,而且所有统计项的数量、名称、百分比都是不固定的。
针对你遇到的“名称无法放在对应元素上方”的问题,我给你提供一个实用的Swing实现思路和代码示例:
核心思路
把每个统计项做成一个垂直排列的独立小容器,顶部放名称标签,下方放显示百分比的条形组件(可以用默认的JProgressBar,也可以自定义绘制更个性化的条形)。然后把这些小容器分别归类到“支持”和“反对”两个大面板中,最终组合成主界面。
完整代码示例
1. 主统计面板类(支持动态添加项)
import javax.swing.*; import java.awt.*; public class DecisionStatsPanel extends JPanel { private final JPanel supportGroupPanel; private final JPanel opposeGroupPanel; public DecisionStatsPanel() { // 主面板用两列网格布局,分隔支持/反对区域 setLayout(new GridLayout(1, 2, 30, 0)); setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); // 初始化支持区域面板 supportGroupPanel = createGroupPanel("支持"); // 初始化反对区域面板 opposeGroupPanel = createGroupPanel("反对"); add(supportGroupPanel); add(opposeGroupPanel); } // 创建每个类别的头部面板 private JPanel createGroupPanel(String groupName) { JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); JLabel groupLabel = new JLabel(groupName, SwingConstants.CENTER); groupLabel.setFont(new Font("微软雅黑", Font.BOLD, 16)); panel.add(groupLabel); panel.add(Box.createVerticalStrut(15)); return panel; } // 动态添加单个统计项 public void addStatItem(String itemName, double percentage, boolean isSupport) { JPanel itemPanel = createSingleStatItem(itemName, percentage, isSupport); if (isSupport) { supportGroupPanel.add(itemPanel); } else { opposeGroupPanel.add(itemPanel); } // 添加项之间的间距 supportGroupPanel.add(Box.createVerticalStrut(20)); opposeGroupPanel.add(Box.createVerticalStrut(20)); // 更新界面布局 revalidate(); repaint(); } // 创建单个统计项的垂直容器(名称+条形) private JPanel createSingleStatItem(String itemName, double percentage, boolean isSupport) { JPanel itemPanel = new JPanel(); itemPanel.setLayout(new BoxLayout(itemPanel, BoxLayout.Y_AXIS)); itemPanel.setAlignmentX(Component.CENTER_ALIGNMENT); // 顶部的名称标签 JLabel nameLabel = new JLabel(itemName, SwingConstants.CENTER); nameLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14)); nameLabel.setAlignmentX(Component.CENTER_ALIGNMENT); // 下方的百分比条形(这里用自定义组件,样式更灵活) CustomPercentageBar bar = new CustomPercentageBar(percentage, isSupport); bar.setAlignmentX(Component.CENTER_ALIGNMENT); // 添加到容器并设置间距 itemPanel.add(nameLabel); itemPanel.add(Box.createVerticalStrut(8)); itemPanel.add(bar); return itemPanel; } // 自定义百分比条形组件(比默认ProgressBar样式更可控) static class CustomPercentageBar extends JComponent { private final double percentage; private final boolean isSupport; public CustomPercentageBar(double percentage, boolean isSupport) { this.percentage = Math.max(0, Math.min(1, percentage)); // 限制0-1范围 this.isSupport = isSupport; setPreferredSize(new Dimension(220, 35)); // 设置默认尺寸 } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 绘制背景边框 g2d.setColor(Color.LIGHT_GRAY); g2d.fillRoundRect(0, 0, getWidth(), getHeight(), 8, 8); // 绘制填充进度 int fillWidth = (int) (getWidth() * percentage); g2d.setColor(isSupport ? new Color(46, 204, 113) : new Color(231, 76, 60)); g2d.fillRoundRect(0, 0, fillWidth, getHeight(), 8, 8); // 绘制百分比文本 g2d.setColor(Color.WHITE); g2d.setFont(new Font("微软雅黑", Font.BOLD, 14)); String text = String.format("%.0f%%", percentage * 100); FontMetrics fm = g2d.getFontMetrics(); int textX = (getWidth() - fm.stringWidth(text)) / 2; int textY = (getHeight() + fm.getAscent()) / 2; g2d.drawString(text, textX, textY); } } // 测试主方法 public static void main(String[] args) { SwingUtilities.invokeLater(() -> { JFrame frame = new JFrame("决策统计展示"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); DecisionStatsPanel statsPanel = new DecisionStatsPanel(); // 模拟动态添加统计项 statsPanel.addStatItem("sneezing", 0.78, true); statsPanel.addStatItem("coughing", 0.65, true); statsPanel.addStatItem("headache", 0.42, false); statsPanel.addStatItem("fatigue", 0.83, false); frame.add(statsPanel); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); }); } }
关键说明
- 垂直布局的小容器:用
BoxLayout.Y_AXIS实现名称和条形的上下排列,确保每个统计项的结构独立。 - 自定义条形组件:相比默认的
JProgressBar,自定义绘制可以更灵活地控制颜色、圆角、文本样式,完全匹配你想要的效果。 - 动态更新:添加新的统计项后调用
revalidate()和repaint(),确保界面及时刷新显示新内容。
如果需要调整样式(比如条形颜色、字体、间距),直接修改对应代码里的参数就行,非常灵活。
内容的提问来源于stack exchange,提问作者Gabartas
相关产品推荐
相关产品推荐

