I am creating a class to handle the creation of musical notation in my music training app, which is being built with Java Swing. As such, I am using the font Bravura for most of the symbols such as the treble clef and accidentals (using the Graphics drawString method with unicode characters).
However, I am unable to find a way to draw a semibreve, or a whole note, with this method; I get a rectangle instead of the desired character when I input the sequence "\uD834\uDD5D", which should correspond to a whole note, according to my research using fileformat.info.
My code for the JFrame is below:
public MusicalNotation() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JTextArea semibreveTextArea = new JTextArea();
semibreveTextArea.setBounds(50, 100, 200, 200);
semibreveTextArea.setFont(new Font("Bravura", Font.PLAIN, 24));
semibreveTextArea.setText("\uD834\uDD5D");
contentPane.add(semibreveTextArea);
semibreveTextArea.setBackground(getBackground());
semibreveTextArea.setEditable(false);
}
However, the resulting window looks like the below:
Are there any other fonts which have this functionality, or other ways to draw a semibreve?
Any help is much appreciated. Thank you in advance.
Are there any other fonts which have this functionality?. Yes there are (several) and and one of them is the font you are already using.
The Bravura music font already contains the Semibreve and you shouldn't need to draw anything since Bravura is a font. All you need to do is provide the appropriate Unicode value for the notes, lines, and spacing you want and of course, the "\uD834\uDD5D" is valid for displaying the Semibreve note providing the Text component you are displaying the characters in has the Bravura font set to it (not all fonts support all of these Unicode music characters), for example:
try {
// Load the "Bravura.otf" font file.
Font bravura = Font.createFont(Font.TRUETYPE_FONT, new File("Bravura.otf"));
// Font Size - NEEDED! I believe default is 1.
// Set it to what you want but you may find
// size 12 too small.
bravura = bravura.deriveFont(36f);
// Set the font to a JTextArea (or whatever).
jTextArea1.setFont(bravura);
// Display the Semibreve.
jTextArea1.setText("\uD834\uDD5D");
}
catch (FontFormatException | IOException ex) {
ex.printStackTrace();
}
You should see a Semibreve within the JTextAea.
Related
So, I just need to add a title to my swing. Here's the code:
import javax.swing.*;
import java.util.Scanner;
public class Wall extends JFrame {
public static void main(String[] args) {
new Wall();
}
public Wall() {
final String title = "Wall Game";
this.setSize(300,300); //sets the screen
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle(title);
this.setVisible(true);
JPanel panel1 = new JPanel();
JLabel label1 = new JLabel("Welcome to the Wall Game!");
JLabel label2 = new JLabel("Click the button to read the instructions!");
panel1.add(label1);
panel1.add(label2);
this.add(panel1);
}
}
I want the Welcome to the Wall Game! part of this to be bigger. Is it possible to make it bigger? If there's a bonus, I wonder if you can add different fonts. But that's not important right now.
Thanks to anyone who knows :P.
I believe all you need is something like this:
JLabel label1 = new JLabel("Welcome to the Wall Game!");
label1.setFont(new java.awt.Font("Arial", 1, 24));
This will set the font to type Arial, '1' will set it to plain, and '24' is the font size. Just read this if you want to do more with the font: https://docs.oracle.com/javase/7/docs/api/java/awt/Font.html
Font font = new Font("Font Name", Font.TYPE_OF_FONT, size);
yourLabel.setFont(font);
Basically, you're creating a "new" font (not really "new" because Arial already exists, but you're just making it bigger (deriving it)).
The first parameter: "Font Name" is self-explanatory: The name of the font; e.g Arial.
The second parameter: Font.TYPE_OF_FONT determines what type your font is: for example, Font.ITALIC italicizes your label. Font.BOLD bolds your label. For more information, see here.
The third parameter: size, which is, in fact, the size! Changing size to 42 makes the font size 42, and changing it to 12345.67890f changes the font size to 12345.67890.
Applying the font
label.setFont(font);
Pretty self-explanatory.
For more information, read this link.
The default JLabel draws its text at the middle of its bounds. For example, if height of the label is 20, font height is 14, the Y coordinate would be (20 - 14)/2 = 3. Like this:
What should I do if want to align the text to the TOP of the JLabel bounds? Like this:
UPD:
public class LabelTest extends JFrame {
public LabelTest() {
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(500, 500);
setLocationRelativeTo(null);
JPanel contentPanel = new JPanel();
contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.X_AXIS));
contentPanel.add(Box.createHorizontalStrut(10));
final JLabel label1 = new JLabel("JLabel");
label1.setVerticalAlignment(SwingConstants.TOP); // by the answer of Kevin Workman, doesn't help
label1.setBorder(BorderFactory.createLineBorder(Color.RED));
label1.setFont(new Font("Arial", Font.PLAIN, 14));
contentPanel.add(label1);
setContentPane(contentPanel);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new LabelTest();
}
});
}
}
You should be packing the frame. If you so this, there should be no unused space in the label. If you want empty space, use an empty border
label.setBorder(new EmptyBorder(0, 0, 5, 0));
top, left, bottom, right
Also, don't set sizes, Use Layout Mangers and let them do the sizing for you. Setting sizes will give you. Setting sizes will give you a rigid look that may look and perform differently on different platforms. Layout Managers will allow your GUI to be more fluid and adaptable to different environments.
See Laying out Components Within a Container for more information on working with layouts
Also see Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?
As always, the API is your best friend: http://docs.oracle.com/javase/7/docs/api/javax/swing/JLabel.html#setVerticalAlignment(int)
Edit- Based on your updated SSCCE, the problem is that your BoxLayout is shrinking the JLabel as small as it will go, so the vertical text position doesn't really matter. Try using a BorderLayout to check that.
The problem is that the insets of the JLabel are adding a small space to the top and bottom of the JLabel, so your text looks centered even though it's at the top. Here's a fix for the insets problem: How to change gap in swing label
I'm making a simple Jeopardy-esque game:
using Java Swing. It's obviously a JFrame with a JPanel in it and buttons in rows.
Now what I need is to add a layered panel with a centered and wrapped text in it:
Which I can remove later. I already tried using JTextPane and JTextArea and JPanel, none of those want to even display. The best effect I have achieved with AWT Panel, it does display but I can't center or wrap text in it.
Here's some code for which I appologise, I would usually try to make it short and readable but since it's not working I don't know what to do with it to make ti look better:
JLabel questionLabel = new JLabel(questionList.get(randomNumber).getQuestion(), SwingConstants.CENTER);
Font font = new Font("Arial", Font.PLAIN, 20);
//------------------JTextPane--------------------
JTextPane questionPane = new JTextPane();
questionPane.setForeground(Color.WHITE);
questionPane.setSize(gameWidth, gameHeight);
questionPane.setText(questionList.get(randomNumber).getQuestion());
questionPane.setFont(font);
questionPane.setEditable(false);
//------------------AWT panel--------------------
Panel awtPanel = new Panel();
awtPanel.setBackground(Color.blue);
awtPanel.setSize(game.getWidth(),game.getHeight());
Label labelQuestion = new Label("<html>" + questionList.get(randomNumber).getQuestion() + "</html>", Label.CENTER);
labelQuestion.setFont(font);
awtPanel.setForeground(Color.white);
awtPanel.add(labelQuestion);
//------------------JPanel-----------------------
JPanel layeredPanel = new JPanel();
layeredPanel.setBackground(Color.blue);
layeredPanel.setSize(game.getWidth(),game.getHeight());
JLabel jLabelQuestion = new JLabel("<html>" + questionList.get(randomNumber).getQuestion() + "</html>", SwingConstants.CENTER);
jLabelQuestion.setFont(font);
layeredPanel.setForeground(Color.WHITE);
layeredPanel.add(jLabelQuestion, BorderLayout.CENTER);
game.getLayeredPane().add(layeredPanel, JLayeredPane.DEFAULT_LAYER);
try {
Thread.sleep(3000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
button.setEnabled(false);
font = new Font("Arial", Font.PLAIN, 16);
button.add(jLabelQuestion, BorderLayout.CENTER);
button.setDisabledIcon(new ImageIcon(source.getScaledInstance(gameWidth/4, gameHeight/5, java.awt.Image.SCALE_SMOOTH)));
questionList.remove(randomNumber);
logger.info(questionList.size());
game.getLayeredPane().remove(layeredPanel);
UPDATE: I chnaged to SWT rather than Swing, and I use the StackLayout with a few Composites in it, and just change between them as I see fit.
You can generally solve issues like this with a JLabel.
I would recommend encapsulating the above grid in the BorderLayout.CENTER of another pane, perhaps a new content pane. Then, add the caption to BorderLayout.NORTH.
As a more tangible example,
private void createContent() {
this.getContentPane().setLayout(new BorderLayout());
//establish the panel currently set as center, here labeled "everythingElse"
this.getContentPane().add(everythingElse, BorderLayout.CENTER);
//Create a JLabel with your caption
JLabel jlbl = new JLabel("Question");
//format that caption, most details being rather obvious, but most importantly:
jlbl.setHorizontalAlignment(SwingConstants.CENTER); //keeps text centered
this.getContentPane().add(jlbl, BorderLayout.NORTH); //add it to the top of the panel
//...other cleanup operations...
}
The issue with grid panes is that they have a limited tolerance for the number of components visible in them. If you overload one, it won't show. For BorderLayout panes, you can easily swap new items into and out of them.
For efficiency's sake, I might recommend compiling this JLabel as a final somewhere else in your code, and holding onto it for when you need it. This way, you will also dodge overhead from repeatedly creating the label object.
Lastly, avoid AWT whenever you can. It's been deprecated for an excess of ten years, and if you do use it you will run into numerous critical problems involving heavyweight and lightweight component incompatibilities. If you intend to use another windowing kit, consider implementing the new standard, JavaFX, with a JFXPane-- it's much more tolerant of HTML syntax, as well.
When I try to use the Wingdings font (or other symbol fonts), the text comes out as rectangles instead of the correct text. How do I get the correct characters to show?
import java.awt.*;
import javax.swing.*;
public class WingdingsFontDisplay extends JFrame
{
public static void main(String[] args)
{
new WingdingsFontDisplay();
}
public WingdingsFontDisplay()
{
this.setSize(500,150);
this.setTitle("Fun with Fonts");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//This shows that I do have "Wingdings" available
GraphicsEnvironment g;
g = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fonts = g.getAvailableFontFamilyNames();
for(String f : fonts)
{
System.out.println(f);
}
//Displaying text in the Wingdings font shows rectangles
JLabel wingdingsText = new JLabel("All work and no play makes Jack a dull boy");
Font f1 = new Font("Wingdings", Font.PLAIN, 14);
wingdingsText.setFont(f1);
this.add(wingdingsText, BorderLayout.NORTH);
//Displaying text in Arial works correctly
JLabel arialText = new JLabel("All work and no play makes Jack a dull boy");
Font f2 = new Font("Arial", Font.PLAIN, 14);
arialText.setFont(f2);
this.add(arialText, BorderLayout.SOUTH);
this.setVisible(true);
}
}
You need to use the appropriate Unicode range for the symbols you seek. In Java, symbols are not overlaid on the ASCII range, but have their own distinct character codes.
You can find a reference to the appropriate symbol codes at http://unicode.org/~asmus/web-wing-ding-ext.pdf . Most common symbols are in the 0x2200 and 0x2700 Unicode ranges.
Your Java install may include the SymbolTest sample applet, which makes it straightforward to preview the presentation of Unicode ranges with available fonts. Be warned, however, that better Java implementations will use font substitutions for symbols or characters not in the specified font, so you'll want to be sure you're actually getting the specified font.
Part of the application I am building demands that I display a variable amount of text in a non-editable component of some sort. Currently this has been implemented in JTextArea, but JTextArea has only the setRows() to set the vertical size of the component.
What I want is a component that will expand to the size needed. This does not pose a problem since the panel on which this thing is embedded is scrollable. It doesn't have to all show up at any particular time but it has to be visible. (And I don't want scrollbars within scrollbars, which I consider an abomination.
What Swing component is best for these requirements?
(Note: I am only asking this here because the entire #$%^&* Oracle Java documentation site including all the Swing demos and tutorials appears to be down now).
I've managed a working prototype for this addressing the dynamic resize issues in the original problem. As more text is added, the text area is resized to be big enough to contain the text. Obviously use setEditable(false) to stop editing of text. Hopefully it will give you some ideas.
set the text
change the column count to an approximate value - here I used square root of total characters * a arbitrary factor.
not the text area is a reasonable width, but we still need to fix the height.
set preferred size to a low value - this will force a recalculation
set preferred height to the minimum height - this is calculated from minimum bounding box of content.
Code
JFrame frame = new JFrame();
GroupLayout gLayout = new GroupLayout(frame.getContentPane());
frame.getContentPane().setLayout(gLayout);
final JTextArea area = new JTextArea();
area.setEditable(false);
area.setLineWrap(true);
area.setWrapStyleWord(true);
JButton button = new JButton("Add more");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
area.setText(area.getText()
+ "apple banana carrot dingo eagle fox gibbon ");
// set approx number of cols
int chars = area.getText().length();
int cols = (int) Math.round(Math.sqrt(chars) * 1.3);
area.setColumns(cols);
// force recalculation
area.setPreferredSize(new Dimension(25, 25));
// downsize
area.setPreferredSize(new Dimension(
area.getPreferredSize().width,
area.getMinimumSize().height));
}
});
ParallelGroup hGroup = gLayout
.createParallelGroup()
.addComponent(button)
.addComponent(area, GroupLayout.PREFERRED_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE);
gLayout.setHorizontalGroup(hGroup);
SequentialGroup vGroup = gLayout
.createSequentialGroup()
.addComponent(button)
.addComponent(area, GroupLayout.PREFERRED_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE);
gLayout.setVerticalGroup(vGroup);
frame.setSize(600, 500);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.invalidate();
frame.validate();
frame.setVisible(true);
Emm... In the case you don't want to enter text you don't need JTextArea... Just to display some text you can simply use JLabel; JLabel supports html text format so you can easily use it in some way like this
...
JPanel aPanel=new JLanel(new FlowLayout());
JLabel aLabel=new JLabel();
aPanel.add(aLabel);
void showFormattedText(String html)
{
aLabel.setText(html);
}
...
As you may guessed, the formatted text can be anything like this
<html>
Put some text<br>
...<br>
</html>
I hope you got the conception
...
mini parser - not tested
String getFormattedText(String text)
{
char commonBR='\n';
String htmlBR="<br>";
char check;
String result="";
for(int i=0; i<text.length(); i++)
{
check=text.charAt(i);
if(check==commonBR)
{
result+=htmlBR;
continue;
}
result+=check;
}
return result;
}
...
void test
{
String text="Hello world \n Hello World once again \n ...and again ";
System.out.println(this.getFormattedText(text));
}
... it is not a final solution though but a basis conception. I hope it was helpful
Good luck