在运行时更改字体
Posted
技术标签:
【中文标题】在运行时更改字体【英文标题】:Change Font at runtime 【发布时间】:2012-04-15 00:37:08 【问题描述】:对于整个 AWT/Swing GUI,是否有另一种方法可以,就像使用 FontUIResource 一样,而不需要任何关于是否存在局部变量和 JComponents 类型的知识/兴趣
import java.awt.*;
import java.awt.event.*;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import javax.swing.plaf.FontUIResource;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
public class SystemFontDisplayer extends JFrame
private static final long serialVersionUID = 1L;
private JFrame frame = new JFrame("Nimbus UIDeafaults and Font");
private JComboBox fontsBox;
private javax.swing.Timer timer = null;
private JButton testButton = new JButton("testButton");
private JTextField testTextField = new JTextField("testTextField");
private JLabel testLabel = new JLabel("testLabel");
public SystemFontDisplayer()
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontFamilyNames = ge.getAvailableFontFamilyNames(Locale.getDefault());
fontsBox = new JComboBox(fontFamilyNames);
fontsBox.setSelectedItem(0);
fontsBox.setRenderer(new ComboRenderer());
fontsBox.addItemListener(new ItemListener()
@Override
public void itemStateChanged(ItemEvent e)
if (e.getStateChange() == ItemEvent.SELECTED)
final String fontName = fontsBox.getSelectedItem().toString();
fontsBox.setFont(new Font(fontName, Font.PLAIN, 16));
start();
);
fontsBox.setSelectedItem(0);
fontsBox.getEditor().selectAll();
frame.setLayout(new GridLayout(4, 0, 20, 20));
frame.add(fontsBox);
frame.add(testButton);
frame.add(testTextField);
frame.add(testLabel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(200, 105);
frame.pack();
java.awt.EventQueue.invokeLater(new Runnable()
@Override
public void run()
fontsBox.setPopupVisible(true);
fontsBox.setPopupVisible(false);
);
frame.setVisible(true);
private void start()
timer = new javax.swing.Timer(750, updateCol());
timer.setRepeats(false);
timer.start();
public Action updateCol()
return new AbstractAction("text load action")
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e)
final Font fnt = new Font(fontsBox.getSelectedItem().toString(), Font.PLAIN, 12);
/*try
LookAndFeel lnf = UIManager.getLookAndFeel().getClass().newInstance();
final FontUIResource res = new FontUIResource(fnt);
UIDefaults uiDefaults = lnf.getDefaults();
uiDefaults.put("Button.font", res);
uiDefaults.put("TextField.font", res);
uiDefaults.put("Label.font", res);
UIManager.getLookAndFeel().uninitialize();
UIManager.setLookAndFeel(lnf);
catch (InstantiationException ex)
Logger.getLogger(SystemFontDisplayer.class.getName()).log(Level.SEVERE, null, ex);
catch (IllegalAccessException ex)
Logger.getLogger(SystemFontDisplayer.class.getName()).log(Level.SEVERE, null, ex);
catch (UnsupportedLookAndFeelException ex)
Logger.getLogger(SystemFontDisplayer.class.getName()).log(Level.SEVERE, null, ex);
UIDefaults defaults = UIManager.getDefaults();
final FontUIResource res = new FontUIResource(fnt);
defaults.put("Button.font", res);
defaults.put("TextField.font", res);
defaults.put("Label.font", res);
SwingUtilities.updateComponentTreeUI(frame);*/
final FontUIResource res = new FontUIResource(fnt);
UIManager.getLookAndFeelDefaults().put("Button.font", res);
UIManager.getLookAndFeelDefaults().put("TextField.font", res);
UIManager.getLookAndFeelDefaults().put("Label.font", res);
SwingUtilities.updateComponentTreeUI(frame);
;
public static void main(String arg[])
/*try
for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels())
if ("Nimbus".equals(laf.getName()))
UIManager.setLookAndFeel(laf.getClassName());
catch (Exception e)
e.printStackTrace();
*/
java.awt.EventQueue.invokeLater(new Runnable()
@Override
public void run()
SystemFontDisplayer systemFontDisplayer = new SystemFontDisplayer();
);
private class ComboRenderer extends BasicComboBoxRenderer
private static final long serialVersionUID = 1L;
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
final Object fntObj = value;
final String fontFamilyName = (String) fntObj;
setFont(new Font(fontFamilyName, Font.PLAIN, 16));
return this;
.
编辑:我发布了 Nimbus 的叙述,然后是 Nimbus 的代码
import java.awt.*;
import java.awt.event.*;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import javax.swing.plaf.FontUIResource;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
public class SystemFontDisplayer extends JFrame
private static final long serialVersionUID = 1L;
private JFrame frame = new JFrame("Nimbus UIDeafaults and Font");
private JComboBox fontsBox;
private javax.swing.Timer timer = null;
private JButton testButton = new JButton("testButton");
private JTextField testTextField = new JTextField("testTextField");
private JLabel testLabel = new JLabel("testLabel");
public SystemFontDisplayer()
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontFamilyNames = ge.getAvailableFontFamilyNames(Locale.getDefault());
fontsBox = new JComboBox(fontFamilyNames);
fontsBox.setSelectedItem(0);
fontsBox.setRenderer(new ComboRenderer());
fontsBox.addItemListener(new ItemListener()
@Override
public void itemStateChanged(ItemEvent e)
if (e.getStateChange() == ItemEvent.SELECTED)
final String fontName = fontsBox.getSelectedItem().toString();
fontsBox.setFont(new Font(fontName, Font.PLAIN, 16));
start();
);
fontsBox.setSelectedItem(0);
fontsBox.getEditor().selectAll();
frame.setLayout(new GridLayout(4, 0, 20, 20));
frame.add(fontsBox);
frame.add(testButton);
frame.add(testTextField);
frame.add(testLabel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(200, 105);
frame.pack();
java.awt.EventQueue.invokeLater(new Runnable()
@Override
public void run()
fontsBox.setPopupVisible(true);
fontsBox.setPopupVisible(false);
);
frame.setVisible(true);
private void start()
timer = new javax.swing.Timer(750, updateCol());
timer.setRepeats(false);
timer.start();
public Action updateCol()
return new AbstractAction("text load action")
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e)
final Font fnt = new Font(fontsBox.getSelectedItem().toString(), Font.PLAIN, 12);
try
LookAndFeel lnf = UIManager.getLookAndFeel().getClass().newInstance();
final FontUIResource res = new FontUIResource(fnt);
UIDefaults uiDefaults = lnf.getDefaults();
uiDefaults.put("Button.font", res);
uiDefaults.put("TextField.font", res);
uiDefaults.put("Label.font", res);
UIManager.getLookAndFeel().uninitialize();
UIManager.setLookAndFeel(lnf);
catch (InstantiationException ex)
Logger.getLogger(SystemFontDisplayer.class.getName()).log(Level.SEVERE, null, ex);
catch (IllegalAccessException ex)
Logger.getLogger(SystemFontDisplayer.class.getName()).log(Level.SEVERE, null, ex);
catch (UnsupportedLookAndFeelException ex)
Logger.getLogger(SystemFontDisplayer.class.getName()).log(Level.SEVERE, null, ex);
UIDefaults defaults = UIManager.getDefaults();
final FontUIResource res = new FontUIResource(fnt);
defaults.put("Button.font", res);
defaults.put("TextField.font", res);
defaults.put("Label.font", res);
SwingUtilities.updateComponentTreeUI(frame);
/*final FontUIResource res = new FontUIResource(fnt);
UIManager.getLookAndFeelDefaults().put("Button.font", res);
UIManager.getLookAndFeelDefaults().put("TextField.font", res);
UIManager.getLookAndFeelDefaults().put("Label.font", res);
SwingUtilities.updateComponentTreeUI(frame);*/
;
public static void main(String arg[])
try
for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels())
if ("Nimbus".equals(laf.getName()))
UIManager.setLookAndFeel(laf.getClassName());
catch (Exception e)
e.printStackTrace();
java.awt.EventQueue.invokeLater(new Runnable()
@Override
public void run()
SystemFontDisplayer systemFontDisplayer = new SystemFontDisplayer();
);
private class ComboRenderer extends BasicComboBoxRenderer
private static final long serialVersionUID = 1L;
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
final Object fntObj = value;
final String fontFamilyName = (String) fntObj;
setFont(new Font(fontFamilyName, Font.PLAIN, 16));
return this;
【问题讨论】:
+1 代表sscce;另见FontShower
。
小注:只需要javax.swing.Timer
的一个实例;只需要一个setSelectedItem()
;考虑getAvailableFontFamilyNames(Locale.getDefault())
。适用于 Mac OS。
@trashgod 再次确定我无用的镇流器的一部分,以前我从 Timer 为 JComboBox 设置了 auto_select,然后从 JComboBox 的 selectedItem 中按值更改字体,对此我很抱歉
更新看起来不错; manItemInCombo()
看起来也很方便。
@trashgod 我知道也许,我猜这已经是一个大胆的风险......
【参考方案1】:
例如:从 FontFamily 列表中创建一个新字体,并使用 c.setFont (font) 将其应用到您的组件;
第二种方法是,搜索 TTF 文件(例如),并使用静态方法 Font.createFont (new File ("...")); 创建新字体;
这个简单的应用程序将按系列创建一个字体列表,并将其应用于 JButton 和 JTextField。
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
/**
FontSwitcher
@author Stefan Wagner
@date So 13. Mai 03:25:23 CEST 2012
*/
public class FontSwitcher extends JFrame implements ActionListener
private static final String progname = "FontSwitcher 0.1";
private JTextField feedback;
private JButton jb;
private JList fontList;
public FontSwitcher ()
super (progname);
JPanel mainpanel = new JPanel ();
mainpanel.setLayout (new BorderLayout ());
this.getContentPane ().add (mainpanel);
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment ();
String [] fonts = ge.getAvailableFontFamilyNames ();
fontList = new JList (fonts);
JScrollPane js = new JScrollPane (fontList);
feedback = new JTextField ("Feedback");
jb = new JButton ("apply font");
jb.addActionListener (this);
mainpanel.add (feedback, BorderLayout.NORTH);
mainpanel.add (js, BorderLayout.CENTER);
mainpanel.add (jb, BorderLayout.SOUTH);
setSize (400, 800);
setLocation (100, 100);
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
setVisible (true);
public void actionPerformed (final ActionEvent e)
SwingWorker worker = new SwingWorker ()
protected String doInBackground () throws InterruptedException
String cmd = e.getActionCommand ();
if (cmd.equals ("apply font"))
String selectedFont = fontList.getSelectedValue ().toString ();
Font font = new Font (selectedFont, Font.TRUETYPE_FONT, 14);
jb.setFont (font);
feedback.setFont (font);
return "done";
protected void done ()
feedback.setText ("done");
;
worker.execute ();
public static void main (final String args[])
Runnable runner = new Runnable ()
public void run ()
new FontSwitcher ();
;
EventQueue.invokeLater (runner);
【讨论】:
aaach 现在我发现我的问题没有被正确提出,当然我想念整个 AWT/Swing GUI,对局部变量 danke 没有任何兴趣 @mKorbel:对不起,我不确定我是否理解。您只对切换整个外观、所有组件的字体感兴趣 - 而不是单独切换?而且您正在寻找第二种方法,仅出于纯粹的兴趣 - 而不是您无法解决的特定问题?您是否搜索过“LookAndFeel”?几年前我读过一些关于它的东西,但没有调查它。我认为这是关于切换应用程序的整体外观和感觉,并且也应该更改字体。 另一个想法是访问者,它遍历你的整个 GUI-Tree(不知道它有多难)并在任何地方应用一些字体。 我没有任何问题,也没有各种外观和感觉(在 Substance L&F 之后),ComponentTree 可能是另一种方式以上是关于在运行时更改字体的主要内容,如果未能解决你的问题,请参考以下文章