Java Swing程序Windows正常Mac端字体异常、按钮不变色问题咨询
项目开发进度说明
- 开发目标:5x5网格猜点位运气类小游戏,最终逻辑为程序随机生成3-5个隐藏目标点位,玩家点中目标点位判定为命中,点错扣除生命值
- 当前已完成:窗口整体布局搭建、错误点击扣减生命值的计数逻辑,目前硬编码了3个索引值为10、2、22的命中点位做测试,随机生成目标点位的功能仍在开发中,空方法不影响当前运行
- 异常现象:代码在Windows设备可正常运行,在Mac设备上存在两类异常:一是设置的文字字体无法正常显示,二是点击网格方块后无法按预期变更为红/绿提示色
项目完整代码
import javax.swing.*; import java.awt.*; import java.awt.event.*; public class Display implements ActionListener{ int lives = 3; int[] hit = {10,2,22}; JFrame frame = new JFrame(); JPanel tile_panel = new JPanel(); JButton[] button = new JButton[25]; JTextField title = new JTextField(); JTextField life_label = new JTextField(); JLabel life_counter = new JLabel(); public Display(){ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(600,600); frame.getContentPane().setBackground(Color.GRAY); frame.setLayout(null); title.setBounds(0,0,600,75); title.setBackground(Color.GRAY); title.setForeground(Color.GREEN); title.setFont(new Font("Ink Free", Font.BOLD, 50)); title.setEditable(false); title.setHorizontalAlignment(JTextField.CENTER); title.setBorder(null); title.setText("Sequence Game"); life_label.setBounds(480,260,100,25); life_label.setBackground(Color.GRAY); life_label.setForeground(Color.GREEN); life_label.setFont(new Font("Roboto",Font.PLAIN,25)); life_label.setText("Lives: "); life_label.setBorder(null); life_label.setEditable(false); life_counter.setBounds(500,300,100,25); life_counter.setForeground(Color.GREEN); life_counter.setFont(new Font("Roboto",Font.PLAIN,25)); life_counter.setText(String.valueOf(lives)); tile_panel.setBounds(25,120,400,400); tile_panel.setBackground(Color.GRAY); tile_panel.setLayout(new GridLayout(5,5, 1,1)); for (int i = 0; i < button.length; i++){ button[i] = new JButton(); button[i].setSize(80,80); button[i].addActionListener(this); tile_panel.add(button[i]); } frame.add(tile_panel); frame.add(life_label); frame.add(life_counter); frame.add(title); frame.setVisible(true); } @Override public void actionPerformed(ActionEvent e) { boolean correct = false; for(int i = 0; i < button.length; i++){ if (e.getSource() == button[i]){ for (int k = 0; k < hit.length; k++){ if (hit[k] == i){ button[i].setBackground(Color.GREEN); correct = true; } } if (correct == false){ button[i].setBackground(Color.RED); lives--; life_counter.setText(String.valueOf(lives)); } i = button.length; } } } public void results(){ } } public class Main{ public static void main(String[] args){ new Display(); } }
跨设备运行异常原因
- 字体显示异常原因:代码中硬编码指定的
Ink Free、Roboto两款字体均为Windows平台常见预装字体,MacOS系统默认不搭载这两款字体。Swing找不到代码指定的字体时,会自动回退到系统默认字体,最终显示效果和预期不符。 - 按钮点击不变色原因:MacOS系统默认使用Aqua原生外观(Look and Feel)渲染Swing组件,会强制接管JButton的背景绘制逻辑,直接调用
setBackground()设置的颜色会被原生按钮样式覆盖,无法正常显示;Windows平台默认的Swing外观没有这类强制覆盖逻辑,所以颜色设置可以正常生效。
对应修复方案
- 字体兼容:不要硬编码特定系统的专有字体,改用Swing提供的跨平台逻辑字体(如
SansSerif、Dialog),程序会自动匹配当前系统的对应默认字体;如果必须使用指定字体,需要将字体文件打包进项目,启动时手动加载字体,避免依赖系统预装。 - 按钮颜色兼容:两种方案可选,一是创建按钮时追加配置
button.setOpaque(true); button.setBorderPainted(false);,关闭原生样式的绘制覆盖;二是在main方法启动时强制设置跨平台Metal外观,跳过Mac原生Aqua UI渲染,代码示例:
public static void main(String[] args) { try { UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); } catch (Exception e) { e.printStackTrace(); } new Display(); }
内容的提问来源于stack exchange,提问作者AskingLotsOfQuestions
相关产品推荐
相关产品推荐

