I was trying to read a .ttc file using java.io.InputStream in IntelliJ IDEA, but it failed.
Here is my code:
InputStream inputStream = getClass().getResourceAsStream("Dependencies\\msjh.ttc");
Font font;
try
{
if (inputStream == null)
throw new IOException();
font = Font.createFont(Font.TRUETYPE_FONT, inputStream).deriveFont(Font.PLAIN);
}
catch (IOException | FontFormatException exception)
{
font = new Font("Microsoft JhengHei UI", Font.PLAIN, 16);
}
No matter how I try, the condition if (inputStream == null) is always true and the IOException will be thrown.
But a similar way of setting window icon works:
Frame frame = new Frame("Window");
frame.setIconImage(Toolkit.getDefaultToolkit().getImage("Dependencies\\icon.png"));
Here are paths from my files :
IdeaProjects\Project\Dependencies\msjh.ttc (font file)
IdeaProjects\Project\Dependencies\icon.png (image file)
IdeaProjects\Project\src\bin_gen\Main.java (source code)
and there is a VM option: -Dfile.encoding=MS950
That .ttc file was copied from C:\Windows\Fonts\Microsoft JhengHei UI. I'm trying this because font = new Font("Microsoft JhengHei UI", Font.PLAIN, 16); seems not working (The font display on the window is still the default font).
I recommend to use getResource rather than getResourceAsStream. They follow slightly different rules and I understand the rules of the former well.
If the font is in the Jar created by the IDE, it will be located at /Dependencies/msjh.ttc.
Note the two separate forward slashes (/) as opposed to a file-like back-slash (\\). That backslash is only for files, and only on Windows. What getResource needs is a resource path either direct from the project or jar root, or relative to the class calling it. The / prefix tells the JRE to look for the resource from the root of the classpath, rather than relative to the calling class.
Also don't use getImage("Dependencies\\icon.png"). That will presume the string represents a file path, which won't work when the project is deployed. Use getResource for that as well.
Related
I need to use custom fonts (ttf) in my Java Swing application. How do I add them to my package and use them?
Mean while, I just install them in windows and then I use them, but I don't wish that the usage of the application will be so complicated, it`s not very convenient to tell the user to install fonts before using my application.
You could load them via an InputStream:
InputStream is = MyClass.class.getResourceAsStream("TestFont.ttf");
Font font = Font.createFont(Font.TRUETYPE_FONT, is);
This loaded font has no predefined font settings so to use, you would have to do:
Font sizedFont = font.deriveFont(12f);
myLabel.setFont(sizedFont);
See:
Physical and Logical Fonts
As Reimeus said, you can use an InputStream. You can also use a File:
File font_file = new File("TestFont.ttf");
Font font = Font.createFont(Font.TRUETYPE_FONT, font_file);
In both cases you would put your font files in either the root directory of your project or some sub-directory. The root directory should probably be the directory your program is run from. For example, if you have a directory structure like:
My_Program
|
|-Fonts
| |-TestFont.ttf
|-bin
|-prog.class
you would run your program with from the My_Program directory with java bin/prog. Then in your code the file path and name to pass to either the InputStream or File would be "Fonts/TestFont.ttf".
Try this:
#Override
public Font getFont() {
try {
InputStream is = GUI.class.getResourceAsStream("TestFont.ttf");
Font font = Font.createFont(Font.TRUETYPE_FONT, is);
return font;
} catch (FontFormatException | IOException ex) {
Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
return super.getFont();
}
}
I have a Java project that has a custom font and when compiled on other computers the font is not the same because my font is not compiled with it. How do I compile with it so it works on other PCs?
This code won't work. Entered it in all my WindowOpened.
try {
InputStream istream = getClass().getResourceAsStream("/fonts/cs_regularttf");
Font myFont = Font.createFont(Font.TRUETYPE_FONT, istream);
} catch (FontFormatException fontFormatException) {
} catch (IOException iOException)
{
}
EDIT: Using the stack trace method, this is what I get for me code.
java.io.IOException: Problem reading font data.
at java.awt.Font.createFont0(Font.java:1000)
at java.awt.Font.createFont(Font.java:877)
at projetfinal.frmMenu.<init>(frmMenu.java:56)
at projetfinal.ProjetFinal.main(ProjetFinal.java:20)
If you use getClass().getResourceAsStream(...) this will interpret the given path relative to your current package (and thus you'd have to put your font in /path/to/your/classes/package/fonts within a resources/ directory of your NetBeans project.
Otherwise you may use getClass().getClassLoader().getResourceAsStream() and omit the package part.
I have a Java project with a toolbar, and the toolbar has icons on it. These icons are stored in a folder called resources/, so for example the path might be "resources/icon1.png". This folder is located in my src directory, so when it is compiled the folder is copied into bin/
I'm using the following code to access the resources.
protected AbstractButton makeToolbarButton(String imageName, String actionCommand, String toolTipText,
String altText, boolean toggleButton) {
String imgLocation = imageName;
InputStream imageStream = getClass().getResourceAsStream(imgLocation);
AbstractButton button;
if (toggleButton)
button = new JToggleButton();
else
button = new JButton();
button.setActionCommand(actionCommand);
button.setToolTipText(toolTipText);
button.addActionListener(listenerClass);
if (imageStream != null) { // image found
try {
byte abyte0[] = new byte[imageStream.available()];
imageStream.read(abyte0);
(button).setIcon(new ImageIcon(Toolkit.getDefaultToolkit().createImage(abyte0)));
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
imageStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} else { // no image found
(button).setText(altText);
System.err.println("Resource not found: " + imgLocation);
}
return button;
}
(imageName will be "resources/icon1.png" etc). This works fine when run in Eclipse. However, when I export a runnable JAR from Eclipse, the icons are not found.
I opened the JAR file and the resources folder is there. I've tried everything, moving the folder, altering the JAR file etc, but I cannot get the icons to show up.
Does anyone know what I'm doing wrong?
(As a side question, is there any file monitor that can work with JAR files? When path problems arise I usually just open FileMon to see what's going on, but it just shows up as accessing the JAR file in this case)
Thank you.
I see two problems with your code:
getClass().getResourceAsStream(imgLocation);
This assumes that the image file is in the same folder as the .class file of the class this code is from, not in a separate resources folder. Try this instead:
getClass().getClassLoader().getResourceAsStream("resources/"+imgLocation);
Another problem:
byte abyte0[] = new byte[imageStream.available()];
The method InputStream.available() does not return the total number of bytes in the stream! It returns the number of bytes available without blocking, which is often much less.
You have to write a loop to copy the bytes to a temporary ByteArrayOutputStream until the end of the stream is reached. Alternatively, use getResource() and the createImage() method that takes an URL parameter.
To load an image from a JAR resource use the following code:
Toolkit tk = Toolkit.getDefaultToolkit();
URL url = getClass().getResource("path/to/img.png");
Image img = tk.createImage(url);
tk.prepareImage(img, -1, -1, null);
The section from the Swing tutorial on How to Use Icons shows you how to create a URL and read the Icon in two statements.
For example in a NetBeans project, create a resources folder in the src folder. Put your images (jpg, ...) in there.
Whether you use ImageIO or Toolkit (including getResource), you must include a leading / in your path to the image file:
Image image = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/resources/agfa_icon.jpg"));
setIconImage(image);
If this code is inside your JFrame class, the image is added to the frame as an icon in your title bar.
I am trying to hack together a game in Java, and on the start screen I used a custom font I downloaded. When I run the program from Eclipse, the screen looks like this (just as it should):
However, when I run the program from the compiled jar, the screen looks like this:
Here is my code for loading the font:
title = new JLabel("philip k. dick"); // font requires all lowercase
try {
Font f = Font.createFont(Font.TRUETYPE_FONT, new File(Util.getFile("all used up.ttf")));
title.setFont(new Font(f.getName(), f.getStyle(), 150));
} catch (Exception e) {
e.printStackTrace();
Font oldFont = title.getFont();
title.setFont(new Font(oldFont.getName(), oldFont.getStyle(), 100));
}
The method Util.getFile just adds "resources/" to the beginning of the given String.
There are no errors given when I run the jar from the command line. I know that the program can access the font resource because when I rename the "resources" folder (to prevent access), the screen looks like this:
Additionally, I get this error:
java.io.IOException: Can't read resources/all used up.ttf
Of course, THIS is expected.
I would also like to note that I have other audio and image resources being loaded from the same location, and they work fine. This location is in the folder directly outside of the jar. Also, I am using a Mac, but I get the same problem on Windows.
The contents of your resources directly are typically add to your Jar.
This means that they can no longer be access using a File object, as they are actually now part of a Zip file.
You need to use something like getClass().getResource(...) to it up. This returns an instance of URL which points to the resource (if it can be found)
However, Font.createFont takes either a File or InputStream reference, in this case you should use getClass().getResourceAsInputStream(...), something like...
Font f = Font.createFont(Font.TRUETYPE_FONT, getClass().getResourceAsInputStream("resources/all used up.ttf"));
This makes a "relative" path request from the context of the class trying to load the resource. This is probably not going to work, so instead, you could use
getClass().getResourceAsInputStream("/resources/all used up.ttf")
Which creates an absolute path lookup from the context of the classpath
If you get stuck, try unpacking the Jar and see if the font resides within and where and make adjusts as required.
Updated...
Try using...
Font f = Font.createFont(Font.TRUETYPE_FONT, new File("resources/all used up.ttf"));
title.setFont(f.deriveFont(150f));
As I understand it, new Font(...) is trying to find the font from the available system fonts.
From the Java Docs for Font#createFont...
This base font can then be used with the deriveFont methods in this
class to derive new Font objects with varying sizes, styles,
transforms and font features. ...To make the Font available to Font
constructors the
returned Font must be registered in the GraphicsEnviroment by calling
registerFont(Font).
I have a Font object in Java for a font file. I need to convert that object to a File object or get the font file path.
Is there a way to do this?
What I'm doing here is calling a method from an external library that loads a font file to use it in writing:
loadTTF(PDDocument pdfFile, File fontfile);
So I wanted to let the user choose a font from the ones defined in his operating system using :
GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment();
Font[] fonts = e.getAllFonts();
Then when the user chooses a font, I pass it to the loadTTF(...) method to load it.
Is there a bad practice here?
// use reflection on Font2D (<B>PhysicalFont.platName</B>) e.g.
Font f = new Font("Courier New", 0, 10);
Font2D f2d = FontManager.findFont2D(f.getFontName(), f.getStyle(),
FontManager.LOGICAL_FALLBACK).handle.font2D;
Field platName = PhysicalFont.class.getDeclaredField("platName");
platName.setAccessible(true);
String fontPath = (String)platName.get(f2d);
platName.setAccessible(false);
// that's it..
System.out.println(fontPath);
Ok ... This will return the font file path :
String fontFilePath = FontManager.getFontPath( true ) + "/" + FontManager.getFileNameForFontName( fontName );
I have tried this in Windows and Linux and in both it worked fine.
No.
A Font in Java is just a representation and definition of how characters can be displayed graphically. It has nothing to do with the filesystem, and technically need not even be ultimately defined in a file (see for example the createFont() method that takes an arbitrary input stream, which could come from anywhere e.g. a network socket). In any case, it would certainly be a ridiculous break in abstraction for you to be able to get the path of the underlying system file that defines the font.
I would suggest that you might be doing the wrong thing in your other method if you're relying on accepting a file. Or if this really is needed, then you're doing the wrong thing in this method by thinking that a Font object has a simple correlation to an underlying file. If you really need to get the file path of a particular font you'll need to approach it from a different angle that doesn't involve java.awt.Font.