setFont()导致JFrame加载延迟

时间:2015-07-27 22:39:33

标签: java swing fonts

我已经看到了一些与此相关的问题,但它们要么涉及重复创建Fonts,要么涉及paintComponent()。我的项目都没有。我创建了一个可运行的测试用例,显示了延迟(随着setFont()之后对JComponents的后续调用,这种延迟似乎会增加。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

import extensions.JActionButton;

public class TestFrame {

    private JFrame mainframe;
    private JPanel content;
    private JButton exitButton;

    public static void main(String[] args) {
        new TestFrame();
    }

    public TestFrame() {
        Color foreground = new Color(240, 240, 240);
        Color background = new Color(254, 70, 70);
        Color border = new Color(127, 127, 127);
        Theme activeTheme = new Theme(foreground, background, border);

        mainframe = new JFrame("Test");
        mainframe.getContentPane().setLayout(new BorderLayout());

        content = new JPanel();
        content.setLayout(new FlowLayout(FlowLayout.RIGHT, 10, 10));
        content.setPreferredSize(new Dimension(480, 320));

        Font bold = new Font("Sans", Font.BOLD, 14);

        exitButton = new JActionButton("Exit", activeTheme, 
                BorderFactory.createMatteBorder(1, 3, 1, 1, activeTheme.getBorder()));
//      exitButton = new JButton("Exit");
        exitButton.setForeground(activeTheme.getForeground());
        exitButton.setBackground(activeTheme.getBackground());
        exitButton.setPreferredSize(new Dimension(140, 40));
        exitButton.setFont(bold);

        exitButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });

        content.add(exitButton);
        mainframe.add(content, BorderLayout.CENTER);

        mainframe.pack();
        mainframe.setLocationByPlatform(true);
        mainframe.setVisible(true);
    }

}

您可以将JActionButton替换为JButton以获得相同的结果。以防万一,这里是所有相关代码。

JActionButton

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;

import javax.swing.JButton;
import javax.swing.border.Border;

import widgets.Theme;

public class JActionButton extends JButton {

    private static final long serialVersionUID = 1L;
    private BufferedImage backgroundImage = null;
    private MouseListener mL = null;

    private Theme theme;

    // you can always pass in null for the Border
    public JActionButton(Theme theme, Border border) {
        super();
        refreshContent();
        setExtendedVariables(theme, border);
    }

    public JActionButton(String text, Theme theme, Border border) {
        super(text);
        refreshContent();
        setExtendedVariables(theme, border);
    }   

    // and you can always pass in a blank string. Bad form, but seriously bored of writing constructors
    public JActionButton(BufferedImage image, String text, Theme theme, Border border) {
        super(text);
        this.backgroundImage = image;
        refreshContent();
        setExtendedVariables(theme, border);
    }

    public void setExtendedVariables(Theme theme, Border border) {
        this.theme = theme;
        setBorder(border);
    }

    public void refreshContent() {
        setFocusPainted(false);
        setContentAreaFilled(false);
        setOpaque(true);

        removeMouseListener(mL);
        mL = new MouseListener() {
            @Override
            public void mouseClicked(MouseEvent e) {
            }

            @Override
            public void mouseEntered(MouseEvent e) {
                setForeground(theme.getForegroundHighlight());
                setBackground(theme.getBackgroundHighlight());
            }

            @Override
            public void mouseExited(MouseEvent e) {
                setForeground(theme.getForeground());
                setBackground(theme.getBackground());
            }

            @Override
            public void mousePressed(MouseEvent e) {
                setForeground(theme.getForegroundLowlight());
                setBackground(theme.getBackgroundLowlight());
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                setForeground(theme.getForegroundHighlight());
                setBackground(theme.getBackgroundHighlight());
            }
        };

        addMouseListener(mL);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        if(null != backgroundImage) {
            g2d.drawImage(backgroundImage, 0, 0, null);
        }
    }

    // for use with BoxLayout as it requires explicit bounds to be set
    public void setAllSimilarConstraints(Dimension dim) {
        setPreferredSize(dim);
        setMinimumSize(dim);
        setMaximumSize(dim);
    }

    public void setAllUniqueConstraints(Dimension min, Dimension max, Dimension pref) {
        setPreferredSize(pref);
        setMinimumSize(min);
        setMaximumSize(max);
    }

    public BufferedImage getBackgroundImage() {
        return backgroundImage;
    }

    public void setBackgroundImage(BufferedImage backgroundImage) {
        this.backgroundImage = backgroundImage;
    }

}

Theme

import java.awt.Color;

/**
 * 
 * @author Sean H
 * 
 * Welcome to the multicoloured parade!
 */

public class Theme {

    private Color foreground;
    private Color foregroundHighlight;
    private Color foregroundLowlight;
    private Color background;
    private Color backgroundHighlight;
    private Color backgroundLowlight;
    private Color border;
    private Color borderHighlight;
    private Color borderLowlight;

    public Theme(Color fore, Color back, Color border) {
        foreground = fore;
        int foreR = fore.getRed();
        int foreG = fore.getGreen();
        int foreB = fore.getBlue();
        // courtesy of http://stackoverflow.com/a/6615053/1306811
        Double foreRconv = foreR * 0.75;
        Double foreGconv = foreG * 0.75;
        Double foreBconv = foreB * 0.75;
        foregroundLowlight = new Color(foreRconv.intValue(), foreGconv.intValue(), foreBconv.intValue());
        foreRconv = foreR + ((255 - foreR) * 0.25);
        foreGconv = foreG + ((255 - foreG) * 0.25);
        foreBconv = foreB + ((255 - foreB) * 0.25);
        foregroundHighlight = new Color(foreRconv.intValue(), foreGconv.intValue(), foreBconv.intValue());

        background = back;
        int backR = back.getRed();
        int backG = back.getGreen();
        int backB = back.getBlue();
        Double backRconv = backR * 0.75;
        Double backGconv = backG * 0.75;
        Double backBconv = backB * 0.75;
        backgroundLowlight = new Color(backRconv.intValue(), backGconv.intValue(), backBconv.intValue());
        backRconv = backR + ((255 - backR) * 0.25);
        backGconv = backG + ((255 - backG) * 0.25);
        backBconv = backB + ((255 - backB) * 0.25);
        backgroundHighlight = new Color(backRconv.intValue(), backGconv.intValue(), backBconv.intValue());

        this.border = border;
        int borR = border.getRed();
        int borG = border.getGreen();
        int borB = border.getBlue();
        Double borRconv = borR * 0.75;
        Double borGconv = borG * 0.75;
        Double borBconv = borB * 0.75;
        borderLowlight = new Color(borRconv.intValue(), borGconv.intValue(), borBconv.intValue());
        borRconv = borR + ((255 - borR) * 0.25);
        borGconv = borG + ((255 - borG) * 0.25);
        borBconv = borB + ((255 - borB) * 0.25);
        borderHighlight = new Color(borRconv.intValue(), borGconv.intValue(), borBconv.intValue());
    }

    public Color getForeground() {
        return foreground;
    }

    public void setForeground(Color foreground) {
        this.foreground = foreground;
    }

    public Color getForegroundHighlight() {
        return foregroundHighlight;
    }

    public void setForegroundHighlight(Color foregroundHighlight) {
        this.foregroundHighlight = foregroundHighlight;
    }

    public Color getForegroundLowlight() {
        return foregroundLowlight;
    }

    public void setForegroundLowlight(Color foregroundLowlight) {
        this.foregroundLowlight = foregroundLowlight;
    }

    public Color getBackground() {
        return background;
    }

    public void setBackground(Color background) {
        this.background = background;
    }

    public Color getBackgroundHighlight() {
        return backgroundHighlight;
    }

    public void setBackgroundHighlight(Color backgroundHighlight) {
        this.backgroundHighlight = backgroundHighlight;
    }

    public Color getBackgroundLowlight() {
        return backgroundLowlight;
    }

    public void setBackgroundLowlight(Color backgroundLowlight) {
        this.backgroundLowlight = backgroundLowlight;
    }

    public Color getBorder() {
        return border;
    }

    public void setBorder(Color border) {
        this.border = border;
    }

    public Color getBorderHighlight() {
        return borderHighlight;
    }

    public void setBorderHighlight(Color borderHighlight) {
        this.borderHighlight = borderHighlight;
    }

    public Color getBorderLowlight() {
        return borderLowlight;
    }

    public void setBorderLowlight(Color borderLowlight) {
        this.borderLowlight = borderLowlight;
    }

}

1 个答案:

答案 0 :(得分:1)

一旦我导出到JAR并将其作为程序运行,这似乎不是问题。据推测,这是由于启动时间延长并包含SplashScreen提供。

仍然是一般性能的瓶颈,但除非我发现任何相反的建议,否则在构建JFrame作为Java程序的初始部分时是个问题。

作为JAR运行解决了TestFrame实例和我的实际项目的问题。