0

I have a program that outputs the calculation result in a JFrame that contains a JPanel (for extensibility), which contains a JLabel, which displays the said output (which is a string).

I found JLabel's default font to be rather small and hard to read, and so increased the font size and replaced it with a Windows specific font, but didn't think much of it since I checked with a font that doesn't exist, and noticed the program worked fine even if the font doesn't exist. (on both Windows 7 and 8)

However, when run on Ubuntu, the result was a JFrame that was the minimal size.

smallllll

So now I'm wondering if this is an example of some incompatibility on JVM, or a problem with the copy of Ubuntu it was run on.

The following code should replicate the problem on Ubuntu (or maybe Linux in general) if this is a JVM issue.

import java.awt.BorderLayout;
import java.awt.Font;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class Main {
    public Main(){
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JLabel lbl = new JLabel("SOME TEXT");
        lbl.setFont(new Font("font that doesnt exist", Font.PLAIN, 20));
        JPanel pnl = new JPanel();
        pnl.add(lbl);
        frame.add(pnl, BorderLayout.CENTER);
        frame.setVisible(true);
        frame.pack();
        frame.setLocationRelativeTo(null);
    }

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

PS the Ubuntu computer is not mine, so I can't exactly test as I want

dare0021
  • 583
  • 6
  • 13
  • 1
    Make sure you are starting the UI from within the context of the EDT, see [Initial Threads](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html) for more details – MadProgrammer Nov 19 '14 at 06:38
  • Also, I'm kind of wondering what you expected from `lbl.setFont(new Font("font that doesnt exist", Font.PLAIN, 20))` and `frame.pack();`... – MadProgrammer Nov 19 '14 at 06:39
  • @MadProgrammer I didn't bother with a proper implementation since the program only displays a single result. It does not take any input, neither does it need to update its output, and neither does it take a long time to compute the output. – dare0021 Nov 19 '14 at 07:01
  • @MadProgrammer I don't understand what you mean in your second comment. – dare0021 Nov 19 '14 at 07:03
  • I'm unsure as to what Java/Swing will do if the font doesn't exist, but if it can't determine the font metrics of the font, it can't calculate the preferred size of the component, and therefore, the preferred size of the window – MadProgrammer Nov 19 '14 at 07:58
  • @MadProgrammer So am I to understand that trying to retrieve a font that is undefined behavior, and that it is merely by lucky chance that it works fine on Windows? The Oracle documentation indeed doesn't mention what happens in this case. – dare0021 Nov 19 '14 at 08:26
  • I would expect that it would fall back to a suitable font (maybe the default), but then I tend not to screw with the fonts ;) – MadProgrammer Nov 19 '14 at 09:52
  • Invoke `pack()` _then_ `setVisible()`, for [example](http://stackoverflow.com/a/7189029/230513). – trashgod Nov 19 '14 at 11:13
  • @trashgod The link only describes a workaround, although from the link I can assume the problem is the Windows JVM being able to function properly with a missing font while OSX and Linux JVM can't, which is an inconsistency in JVM. – dare0021 Nov 19 '14 at 11:28
  • @trashgod Also, if I'm not mistaken, the workaround is using a logical font rather than a specific font, not using setVisible() after pack() – dare0021 Nov 19 '14 at 11:28
  • @user2444520: Ubuntu does font substitution, too; you should do all three—logical font, `setVisible()` last, and start on EDT; update your example, and I'll give it a whirl when I can. – trashgod Nov 19 '14 at 12:22
  • @trashgod I really don't see the point in making a proper EDT when there is no need to have a responsive GUI, kind of like how HelloWorld doesn't do that either. As I said before, the GUI output is completely static. It doesn't have to deal with any input. It's a few lines of text. I don't see why there is this insistence on a proper EDT any more than I can see a reason to implement proper serial UID or non default packaging. https://docs.oracle.com/javase/tutorial/uiswing/examples/start/ – dare0021 Nov 19 '14 at 13:06
  • @user2444520: The goal would be to have an otherwise correct program that can be tested by someone having your versions of Ubuntu and the JVM; updating your question will bump it to the top where it is more likely to be seen. – trashgod Nov 19 '14 at 17:16

1 Answers1

1

Testing on Ubuntu 14, Java 7, font substitution appears to work in the usual way. Note the need to invoke pack() and then setVisible(), as well as to start the UI on the EDT.

image

import java.awt.Font;
import java.awt.GridLayout;
import java.io.File;
import javax.swing.*;

public class TestFrame extends JFrame {

    public TestFrame() {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLayout(new GridLayout(0, 1));
        JLabel label1 = new JLabel("Some big, bold, serif text.");
        label1.setFont(new Font(Font.SERIF, Font.BOLD, 24));
        this.add(label1);
        JLabel label2 = new JLabel("Some big, bold, default text.");
        label2.setFont(new Font("42", Font.BOLD, 24));
        this.add(label2);
        this.pack();
        this.setLocationRelativeTo(null);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestFrame().setVisible(true);            }
        });
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045