Context: Java 11, JavaFx 11 (where applicable), Linux Mint 19.3, Eclipse 2020.06. Java apps run as desktop applications.
Background: The Mongolian script is considered "complex" and, to be shaped correctly, requires OpenType tables as isol, init, medi, fina, rlig in the font(s) implementing it.
I am trying to insert Mongolian strings in Java UI and I am having unexpected results both with Swing and with JavaFX.
Basically, if a Mongolian string like "ᠪᠠᠢᠨᠠ" is inserted in a Swing JLabel or in an Fx Label alone, it is rendered without any shaping (more or less as in "ᠪ ᠠ ᠢ ᠨ ᠠ"), while if a string in another "complex" string is added in the same label, say "अनुच्छेद ᠪᠠᠢᠨᠠ" or "ᠪᠠᠢᠨᠠ अनुच्छेद", then it is rendered correctly.
Furthermore, I noticed that in Swing, either a Devanāgarī or an Arabic string turn on the correct shaping, while in JavaFx a Devanāgarī addition does the job but an Arabic addition does not.
Of course, I cannot add arbitrary strings just to turn the correct shaping on. Am I forgetting some important initialisation or is the Java shaping tier of the font stack broken? (I suppose it is HarfBuzz, which usually works quite well...).
Thanks for any suggestion!
A Swing minimal example, which comments showing which strings are rendered correctly and which are not:
package com.vistamaresoft.swingtest;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Main
{
private JFrame frame;
private static Main window;
public Main()
{
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setTitle("Mongolian Swing Test");
frame.setBounds(100, 100, 300, 200);
//Set up the GUI.
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
JLabel label = new JLabel("ᠪᠠᠢᠨᠠ"); // NOT CORRECT
panel.add(label);
label = new JLabel("Abc ᠪᠠᠢᠨᠠ"); // NOT CORRECT
panel.add(label);
label = new JLabel("ᠪᠠᠢᠨᠠ كتاب "); // CORRECT
panel.add(label);
label = new JLabel("كتاب ᠪᠠᠢᠨᠠ"); // CORRECT
panel.add(label);
label = new JLabel("ᠪᠠᠢᠨᠠ अनुच्छेद"); // CORRECT
panel.add(label);
label = new JLabel("अनुच्छेद ᠪᠠᠢᠨᠠ"); // CORRECT
panel.add(label);
frame.setContentPane(panel);
}
public static void main(String[] args)
{
window = new Main();
window.frame.setVisible(true);
}
}
A JavaFx minimal example. Note that the WebView is not any better than a Label and that copy and pasting a label text into the HTML input field yields the same results:
package com.vistamaresoft.fxtest;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class Main
{
static final String html =
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n\"http://www.w3.org/TR/html4/strict.dtd\">\n" +
"<html>\n<body>\n" +
"<p style='font-size: 18pt;'>Sample text: ᠴᠣᠴᠡᠭᠠ</p>" + // NOT CORRECT!
"<p style='font-size: 18pt;'>ᠪᠠᠢᠨᠠ كتاب </p>" + // NOT CORRECT!
"<p style='font-size: 18pt;'>अनुच्छेद ᠴᠣᠴᠡᠭᠠ</p>" + // CORRECT!
"<p><input type='text' name='title' size='20' maxlength='50' style='font-size: 18pt;' /></p>" +
"</body></html>\n";
public static void main(String[] args)
{
Application.launch(MainApp.class, args);
}
public static class MainApp extends Application
{
#Override public void start(Stage primaryStage) throws Exception
{
WebView webView = new WebView();
webView.getEngine().loadContent(html);
Label lab1 = new Label("ᠪᠠᠢᠨᠠ"); // NOT CORRECT
lab1.setStyle("-fx-font-size: 24pt;");
Label lab2 = new Label("ᠪᠠᠢᠨᠠ كتاب"); // NOT CORRECT
lab2.setStyle("-fx-font-size: 24pt;");
Label lab3 = new Label("كتاب ᠪᠠᠢᠨᠠ"); // NOT CORRECT
lab3.setStyle("-fx-font-size: 24pt;");
Label lab4 = new Label("ᠪᠠᠢᠨᠠ अनुच्छेद"); // CORRECT
lab4.setStyle("-fx-font-size: 24pt;");
Label lab5 = new Label("अनुच्छेद ᠪᠠᠢᠨᠠ"); // CORRECT
lab5.setStyle("-fx-font-size: 24pt;");
VBox vBox = new VBox(webView, lab1, lab2, lab3, lab4, lab5);
Scene scene = new Scene(vBox, 800, 600);
primaryStage.setTitle("JavaFX Mongolian Test");
primaryStage.setScene(scene);
primaryStage.show();
}
}
}
EDIT:
These issues have been filed as bugs by the Java bug database:
the AWT bug: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8252091
the JavaFx bug: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8252220
Related
I'm writing a Swing application and I'm trying to figure out a way to display text while being able to control the following text properties:
font family and size
text overline
lower index
Of course the more flexible the approach, the better, but those are strictly mandatory for me.
What I already tried:
using JTextPane and setting text-decoration: overline attribute -
doesn't work, because JTextPane html/css engine is dated and doesn't support this
using JTextPane with setting upper border via css -
doesn't work, because it can only be applied to html nodes with
display:block (such as divs), and I need this inline (setting display: inline-block is not
supported in JTextPane, so I can't use that)
using WebView from JavaFX - this is where I'm currently at, but I can't figure out how to load a custom font programmatically. It only seems to be working when the font is loaded at OS level (e.g. when the font file is present in ~/.fonts on Linux)
This is a working example. Mostly taken from Integrating JavaFX into Swing Applications.
Mind the font file, which you might have to specify yourself (here's the file I used):
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.scene.web.WebView;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Test {
private static void initAndShowGUI() {
JFrame frame = new JFrame("Swing and JavaFX");
final JFXPanel fxPanel = new JFXPanel();
frame.add(fxPanel);
frame.setSize(300, 200);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Platform.runLater(() -> initFX(fxPanel));
}
private static void initFX(JFXPanel fxPanel) {
Scene scene = createScene();
fxPanel.setScene(scene);
}
private static Scene createScene() {
var wb = new WebView();
// ???
var f = Font.loadFont("lmroman10-regular.otf", 10);
assert f != null;
wb.getEngine().loadContent(
"<html><body>" +
"<span style=\"" +
"text-decoration: overline; " +
"font-size: 24px;" +
"font-family: 'LM Roman 10';\">" +
"foo" +
"</span>" +
"bar" +
"</body></html>");
return new Scene(wb);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> initAndShowGUI());
}
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have been given an assignment whereby I need to create a tool that analyses a field of text and then outputs a couple of statistics about said body of text via a button click. I seem to have most of the basic framework up but am struggling with getting my two labels that are averageLength and totalWords inside my JPanel and also on getting said JPanel below where I enter my body of text. Any help would be much appreciated. Code is here:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TextStatisticsPanel extends JPanel
{
//Field for block of text
private JTextArea userText;
//Button to calculate Statistics
private JButton stats;
//Label for where statistics are shown and statistics
private JLabel averageLength, totalWords;
public TextStatisticsPanel(){
//creating the area for user text with wrapped text
userText = new JTextArea();
userText.setWrapStyleWord(true);
userText.setLineWrap(true);
//create button
stats = new JButton("Update Text Statistics");
//Listener for button
stats.addActionListener(new ButtonListener());
//Tilted border creater
JPanel statPanel = new JPanel();
statPanel.setBorder(BorderFactory.createTitledBorder("Text Statistics"));
statPanel.setOpaque(false);
//Create Scroller
JScrollPane scroller = new JScrollPane(userText);
scroller.setPreferredSize(new Dimension (350, 400));
scroller.setBorder(BorderFactory.createTitledBorder ("Enter the text below"));
//Add the statistics labels
averageLength = new JLabel("The average length of the words: ");
totalWords = new JLabel("The total number of words: ");
//add GUI
add(statPanel);
add(scroller);
add(averageLength);
add(totalWords);
setBackground(new java.awt.Color(202, 225, 255));
setPreferredSize(new Dimension (400, 600));
add(stats);
}
// When button is pressed do :
private class ButtonListener implements ActionListener{
public void actionPerformed(ActionEvent event)
{
if (event.getSource() == stats){
//Call statUpdate Method
statUpdate();
}
}
// Create statUpdate Method
private void statUpdate()
{
//Grab text user inputed
String text = userText.getText();
//Split the text by each space to find the number of words
String[] words = text.split(" ");
//Calculation for average
float average = (text.length() - words.length)/words.length;
//
averageLength.setText(String.valueOf(average));
totalWords.setText(String.valueOf(words.length));
System.out.println(averageLength);
System.out.println(totalWords);
}
}
}
OK so as to try and use MCVE, this is part of the relevent code however I am still unable to work out the root of the problem.
The code for my second panel is :
JPanel statPanel = new JPanel();
statPanel.setBorder(BorderFactory.createTitledBorder("Text Statistics"));
statPanel.setOpaque(false);
SO as per my understanding this is me creating a second panel among my app. The problem however is that this is being placed in a seemingly random location and is not wrapping around the two labels I wish to be inside this panel and I am unsure how to fix this problem.
The main class code:
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.JFrame;
public class TextStatistics {
public static void main(String[] args) {
JFrame frame = new JFrame("Text Statistics Tool");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TextStatisticsPanel panel = new TextStatisticsPanel();
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
}
Providing a visual example to show the code I believe is the problem and the problem I am encountering
Problem Visualised
Here's the GUI I put together.
These are the major changes I made.
I put the JFrame code in a Runnable, so I could start the Swing application with a call to the SwingUtilities invokeLater method. The invokeLater method ensures that the Swing components are created and updated on the Event Dispatch thread. Oracle and I require that everyone starts their Swing applications on the Event Dispatch thread.
I defined several new JPanels in your TextStatisticsPanel class and used two Swing layout managers, BorderLayout and BoxLayout. Study the link in the previous sentence. By study, I mean spend at least two to three weeks of 8 hour days absorbing all of the ins and outs of the Swing layout managers.
I added JTextFields to hold the calculated values. That's what JTextFields are for.
I fixed the integer division in your statUpdate method.
Here's the code. I put everything together in one file so it would be easier to upload. You should put the classes in separate files.
package com.ggl.testing;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class TextStatistics {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Text Statistics Tool");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TextStatisticsPanel panel = new TextStatistics().new TextStatisticsPanel();
frame.add(panel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
};
SwingUtilities.invokeLater(runnable);
}
public class TextStatisticsPanel extends JPanel {
private static final long serialVersionUID = 9049744714586970558L;
// Field for block of text
private JTextArea userText;
// Button to calculate Statistics
private JButton stats;
// Label for where statistics are shown and statistics
private JLabel averageLength, totalWords;
private JTextField averageLengthField, totalWordsField;
public TextStatisticsPanel() {
// creating the area for user text with wrapped text
userText = new JTextArea();
userText.setWrapStyleWord(true);
userText.setLineWrap(true);
// create button
stats = new JButton("Update Text Statistics");
stats.setAlignmentX(JButton.CENTER_ALIGNMENT);
// Listener for button
stats.addActionListener(new ButtonListener());
// Tilted border creater
JPanel statPanel = new JPanel();
statPanel.setBorder(BorderFactory
.createTitledBorder("Text Statistics"));
statPanel.setLayout(new BoxLayout(statPanel, BoxLayout.PAGE_AXIS));
statPanel.setOpaque(false);
// Create Scroller
JScrollPane scroller = new JScrollPane(userText);
scroller.setPreferredSize(new Dimension(350, 400));
scroller.setBorder(BorderFactory
.createTitledBorder("Enter the text below"));
// Add the statistics labels
averageLength = new JLabel("The average length of the words: ");
averageLength.setOpaque(false);
averageLengthField = new JTextField(10);
averageLengthField.setEditable(false);
averageLengthField.setOpaque(false);
totalWords = new JLabel("The total number of words: ");
totalWords.setOpaque(false);
totalWordsField = new JTextField(10);
totalWordsField.setEditable(false);
totalWordsField.setOpaque(false);
// add GUI
setLayout(new BorderLayout());
statPanel.add(stats);
statPanel.add(Box.createVerticalStrut(10));
JPanel lengthPanel = new JPanel();
lengthPanel.setOpaque(false);
lengthPanel.add(averageLength);
lengthPanel.add(averageLengthField);
statPanel.add(lengthPanel);
statPanel.add(Box.createVerticalStrut(10));
JPanel wordsPanel = new JPanel();
wordsPanel.setOpaque(false);
wordsPanel.add(totalWords);
wordsPanel.add(totalWordsField);
statPanel.add(wordsPanel);
add(statPanel, BorderLayout.SOUTH);
add(scroller, BorderLayout.CENTER);
setBackground(new java.awt.Color(202, 225, 255));
}
// When button is pressed do :
private class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
if (event.getSource() == stats) {
// Call statUpdate Method
statUpdate();
}
}
// Create statUpdate Method
private void statUpdate() {
// Grab text user inputed
String text = userText.getText();
// Split the text by each space to find the number of words
String[] words = text.split(" ");
// Calculation for average
float average = ((float) text.length() - words.length)
/ words.length;
//
averageLengthField.setText(String.valueOf(average));
totalWordsField.setText(String.valueOf(words.length));
}
}
}
}
I have a following piece of code which uses JTextArea to display some text,
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.text.DefaultCaret;
public class TextPane extends JFrame{
public static TextPane instance;
//private static JTextPane pane = new JTextPane(); //Uncomment to see alignment issue
private static JTextArea pane = new JTextArea(); // alignment works fine
private static JScrollPane scroll = new JScrollPane();
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
TextPane.getInstance().init();
}
});
}
private static TextPane getInstance() {
if(null == instance){
instance = new TextPane();
}
return instance;
}
private void init() {
pane.setFont(new Font("Courier new", Font.PLAIN, 12));
pane.setLayout(new BorderLayout());
pane.setFocusCycleRoot(true);
pane.setFocusTraversalKeysEnabled(false);
pane.setBackground(Color.black);
pane.setForeground(Color.white);
pane.setCaretColor(Color.green);
pane.setDragEnabled(false);
pane.setText("IOC_CONFUG_MMM.lag hkess.lag\t\t papdifs.lag\r\nMemSys.lag.txt\t eol.lag1\t\t papdifs.lag2\r\nopp.lag\t\t eol.lag2\t\t papm_by.lag1\r\n");
DefaultCaret caret = (DefaultCaret) pane.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
scroll.setViewportView(pane);
add(scroll);
setTitle("Test");
setSize(800 , 800);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(true);
setVisible(true);
}
}
There was an issue in alignment of the setText string initially however after i add font as Courier New i got it resolved(if i remove setFont alignment will not work.)
recently due to some requirements i changed from JtextArea to JTextPane , now with same piece of code the text doesn't align properly in JTextPane but if i change it to JTextArea alignment works fine.
I couldn't understand this behaviour. How can i achieve the alignment in JTextPane. please help.
The JTextPane (or the editor kit you are using implicitly) has a different default behavior regarding tab placement which stems from the fact that it is intended to contain far more complex content than a JTextArea. You can create your desired simple fixed-width font tab placement manually and set it explicitly. Just insert the following lines right before invoking setText(…); on your pane:
int w=pane.getFontMetrics(pane.getFont()).charWidth(' ');
TabStop[] stops={ new TabStop(0), new TabStop(w*8), new TabStop(w*16),
new TabStop(w*24), new TabStop(w*32), new TabStop(w*40), new TabStop(w*48),
new TabStop(w*56), new TabStop(w*64), new TabStop(w*72), new TabStop(w*80) };
MutableAttributeSet attrs=new SimpleAttributeSet();
StyleConstants.setTabSet(attrs, new TabSet(stops) );
pane.setParagraphAttributes(attrs, false);
So I asked something similar to this earlier and got the answer to the question I asked, but I apparently didn't ask the right question. So, what I'm trying to accomplish here is have the text area populate only in the center of the jFrame. As you can see, it is set up as a borderlayout, and there are buttons on the bottom, a label on the top (which will then - on the full version of this program - be copied into the text frame when it is replaced with text from the action listener on the button)
The problem is, the text area fills the entire window and covers up every other component on the window. I've tried to use preferred size, and I tried to specify columns/rows and I've read the tutorials on docs.oracle, although I suppose since I'm still having trouble i may have missed one.
Also, the offset commented lines I found in the docs.oracle information and it would be a good idea for this to text-wrap because it's going to be a log of what has occurred. I tried adding all the imports suggested on that website but netbeans still gives me a red underline that they're not recognized as commands. Have they been deprecated, did I not use them right, or am I missing an import?
I know I'm asking a lot, but thanks for your time and patience!
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package theproblem;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.TextArea;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
/**
*
* #author Heather
*/
public class TheProblem {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
JFrame window2 = new JFrame();
TextArea battleLogging = new TextArea(3,10);
JScrollPane logScrollPane = new JScrollPane(battleLogging);
JLabel BattleLog = new JLabel();
JLabel p1HPLabel= new JLabel();
JLabel p2HPLabel= new JLabel();
String attack1ButtonContents = "Just an attack";
String attack2ButtonContents = "Just another attack";
JButton attack1=new JButton(attack1ButtonContents);
JButton attack2=new JButton(attack2ButtonContents);
window2.setLayout(new BorderLayout());
window2.setSize(400,400);
JPanel attackPanel = new JPanel();
attackPanel.add(attack1);
attackPanel.add(attack2);
window2.add(battleLogging, BorderLayout.CENTER);
battleLogging.setEditable(false);
logScrollPane.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
logScrollPane.setPreferredSize(new Dimension(50, 50));
//battleLogging.setLineWrap(true);
//battleLogging.setWrapStyleWord(true);
window2.add(BattleLog, BorderLayout.NORTH);
window2.add(p1HPLabel, BorderLayout.WEST);
window2.add(p2HPLabel, BorderLayout.EAST);
window2.setVisible(true);
window2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Problems:
When adding any component BorderLayout.CENTER, it fills the center position, no matter what size or preferred size you give it.
You shouldn't even be setting sizes.
Don't use TextAreas with Swing apps. Use JTextAreas
Set the JTextArea's column and row count and let that do its sizing for you.
Don't forget to pack your GUI before displaying it.
For example:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.*;
public class TheProblem2 {
private static void createAndShowGUI() {
int rows = 5;
int cols = 20;
JTextArea textArea = new JTextArea(rows, cols);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JButton button1 = new JButton("Button 1");
JButton button2 = new JButton("Button 1");
JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 0));
btnPanel.add(button1);
btnPanel.add(button2);
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(scrollPane);
mainPanel.add(btnPanel, BorderLayout.SOUTH);
JFrame frame = new JFrame("EG 2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Below is the java Swing code to place a icon in a JLabel Swing component.
package com.TheMcLeodgrp;
import java.awt.FlowLayout;
import java.awt.HeadlessException;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Main extends JFrame {
public Main() throws HeadlessException {
setSize(300, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout(FlowLayout.LEFT));
Icon icon = new ImageIcon("myIcon.gif");
JLabel label1 = new JLabel("Full Name :", icon, JLabel.LEFT);
JLabel label2 = new JLabel("Address :", JLabel.LEFT);
label2.setIcon(new ImageIcon("myIcon.gif"));
getContentPane().add(label1);
getContentPane().add(label2);
}
public static void main(String[] args) {
new Main().setVisible(true);
}
}
It is a simple label program where everything else works fine. The icon (myIcon.gif) just wont show up in the label when I run the program. I am running it from a standard Eclipse IDE, and myIcon.gif resides in a folder - ie; images/myIcon.gif. It seems like I missing something simple here, but I don't know. Do I need to place the icon somewhere else in the application.
I think the following article will do much better job of explaining how to load image resources then I will :)
http://download.oracle.com/docs/cd/E17409_01/javase/tutorial/uiswing/components/icon.html
I'll second #eugener's recommendation on the tutorial. Also, try using the relative path, and check the result of constructing the ImageIcon:
JLabel label2 = new JLabel("Address :", JLabel.LEFT);
ImageIcon icon = new ImageIcon("images/myIcon.gif");
if (icon.getIconWidth() == -1) {
JOptionPane.showMessageDialog(null,
"No image!", "Gahh!", JOptionPane.ERROR_MESSAGE);
} else {
label2.setIcon(icon);
}