So I created a simple JFrame and added a JTextPane to it to create a sorta console..
I have the following methods and variables in my class which is supposed to change the colour of text in the JTextPane.
private static final Object CurrentConsoleAttributes[] = new Object[4];
private static final SimpleAttributeSet ConsoleAttributes = new SimpleAttributeSet();
public Object[] getConsoleAttributes() {
CurrentConsoleAttributes[0] = StyleConstants.getForeground(ConsoleAttributes);
CurrentConsoleAttributes[1] = StyleConstants.getBackground(ConsoleAttributes);
CurrentConsoleAttributes[2] = StyleConstants.isBold(ConsoleAttributes);
CurrentConsoleAttributes[3] = StyleConstants.isItalic(ConsoleAttributes);
return CurrentConsoleAttributes;
}
public void setConsoleAttributes(Color Foreground, Color Background, boolean Bold, boolean Italics) {
synchronized(ConsoleAttributes) {
StyleConstants.setForeground(ConsoleAttributes, Foreground);
StyleConstants.setBackground(ConsoleAttributes, Background);
StyleConstants.setBold(ConsoleAttributes, Bold);
StyleConstants.setItalic(ConsoleAttributes, Italics);
}
}
private void setOutputAreaText(final String Text) {
SwingUtilities.invokeLater(new Runnable() { //I read that I need to use this when dealing with swing and JTextPane is a swing component.
#Override
public void run() {
try {
StyledDocument Document = Frame.this.OutputArea.getStyledDocument();
Document.insertString(Document.getLength(), Text, ConsoleAttributes);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
});
}
public void WriteLine(Object Value) {
try {
System.out.print("Hey");
setConsoleAttributes(java.awt.Color.red, Color.white, true, false);
System.out.print("Testing");
setConsoleAttributes(java.awt.Color.blue, Color.white, true, false);
System.out.println("Printing");
} catch (Exception Ex) {
Ex.printStackTrace();
}
}
However, when I call WriteLine, the entire line is written in blue or whatever colour was used last. Any ideas what I'm missing?
Related
I have a simple swing application with two JTextPanes. In the first I write a html code and in the second I get the appearance defined by this html. I want to have button which allows me to insert a table into the document.
Here is my code:
public class TestEditor extends JFrame {
public TestEditor(){
createConnection();
createGUI();
}
private void createGUI(){
setDefaultCloseOperation(EXIT_ON_CLOSE);
JScrollPane scroll1=new JScrollPane(text);
JScrollPane scroll2=new JScrollPane(html);
JSplitPane split=new JSplitPane();
split.setLeftComponent(scroll1);
split.setRightComponent(scroll2);
split.setDividerLocation(0.5);
split.setResizeWeight(0.5);
getContentPane().add(split);
table=new JButton("Insert table");
table.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
StringBuilder builder=new StringBuilder("<table border=1>\n");
for(int i=0;i<4;i++){
builder.append("<tr>");
for(int j=0;j<4;j++){
builder.append("<td></td>");
}
builder.append("</tr>\n");
}
builder.append("</table>\n");
try{
text.getStyledDocument().insertString(text.getCaretPosition(), builder.toString(), null);
}catch(BadLocationException ex){
ex.printStackTrace();
}
}
});
getContentPane().add(table, BorderLayout.SOUTH);
setTitle("Test");
setPreferredSize(new Dimension(600,300));
pack();
}
private void createConnection(){
text=new JTextPane();
html=new JTextPane();
html.setContentType("text/html");
html.getStyledDocument().addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent e) {
update();
}
#Override
public void removeUpdate(DocumentEvent e) {
update();
}
#Override
public void changedUpdate(DocumentEvent e) {
update();
}
private void update(){
if(fromText) return;
fromHtml=true;
text.setText(html.getText());
fromHtml=false;
}
});
text.getStyledDocument().addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent e) {
update();
}
#Override
public void removeUpdate(DocumentEvent e) {
update();
}
#Override
public void changedUpdate(DocumentEvent e) {
update();
}
private void update(){
if(fromHtml) return;
fromText=true;
html.setText(text.getText());
fromText=false;
}
});
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new TestEditor().setVisible(true);
}
});
}
private JTextPane text;
private JTextPane html;
private boolean fromHtml, fromText;
private JButton table;
}
However, this inserts a table in the wrong place, most often after the ending tag </html>. My goal is to insert the table in the place in which caret is on the right editor.
What should I do? How to detect the proper position?
I tested your code, and it fails when you are editing the styled document, but it works when you edit the text document. The reason is simple: when a call to update() occurs, the use of setText() puts the caret at the end of the document. The html code is then naturally inserted at the end.
So ideally you would want to keep track of the caret position and cleverly update it after setText(). But this is not easy: How do you manage inserted or removed text?
So here is a proposal: When the "add table" button is clicked, detect which editor has focus (= where the caret position is relevant), and insert the html code in the corresponding one.
However, inserting html code in the styled document will be done slightly differently (to avoid being escaped):
HTMLEditorKit kit = (HTMLEditorKit) html.getEditorKit();
HTMLDocument doc = (HTMLDocument) html.getStyledDocument();
kit.insertHTML(doc, html.getCaretPosition(), builder.toString(), 0, 0, null);
So you should get something like that:
Component c = getFocusOwner();
if(c==html){
HTMLEditorKit kit = (HTMLEditorKit) html.getEditorKit();
HTMLDocument doc = (HTMLDocument) html.getStyledDocument();
kit.insertHTML(doc, html.getCaretPosition(), builder.toString(), 0, 0, null);
}else if(c==text){
text.getStyledDocument().insertString(text.getCaretPosition(), builder.toString(), null);
}
Also, make the button unfocusable to avoid getFocusOwner() to detect the button click:
table.setFocusable(false);
I've search this question in different wording for the past day or two now and I just can not solve it :/,
I have Window that pops up on the screen that looks like a Command Prompt there is a two buttons Run and Stop. Anyways I have on the screen once you press start it starts "Scanning files" It says "Scanning 1-1900 something" counts up to 1900 and then says Scan completed, after that I want text to go Under the existing Text
and write multiple lines of text to mess with my friend for example.
{
Scan Completed
"wait time inbetween each line of text"
Hack initialized
"wait time inbetween each line of text"
Hack installing...
"wait time inbetween each line of text"
Hack installed
ECT
}
Hopefully someone can Help me, every one I looked at did not work with my code :/
I'm new to code as well so...
thanks in advance anyways here my code its not to long :P.
public static void main(String[] args) throws IOException {
JFrame frame = new JFrame("Happy Monday v0.05");
Container contentPane = frame.getContentPane();
JTextPane jta = new JTextPane();
JButton button = new JButton("Run");
JButton buttonstop = new JButton("Stop");
contentPane.add(button);
contentPane.add(buttonstop);
button.setBounds(-1,283,465,40);
buttonstop.setBounds(465,283,469,40);
frame.add(jta).setBackground(Color.black);
console(jta);
//Window
frame.setSize(950, 650 / 16 * 9);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
new SwingWorker<Void, Object>(){
#Override
protected Void doInBackground() throws Exception {
outputTest("Scanning...");
return null;
}}.execute();
}});
}
//Testing OUTPUTS:/
public static void outputTest(String msg){
for(int i=0;i<1969;i++){
System.out.println(i+" "+msg);
try {
Thread.sleep(01);
System.out.println("Scan Complete");
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
public static void console(final JTextPane area) throws IOException {
area.setContentType("text/html");
final PipedInputStream outPipe = new PipedInputStream();
System.setOut(new PrintStream(new PipedOutputStream(outPipe), true));
new SwingWorker<Void, String>() {
#Override
protected Void doInBackground() throws Exception {
Scanner s = new Scanner(outPipe);
while (s.hasNextLine()){
String line = s.nextLine();
publish(line + "\n");
}
return null;
}
#Override
protected void process(List<String> chunks) {
for (String line : chunks){
area.setText("<font size=\"5\" color=\"green\">"+line+"</font>");
}
}
}.execute();
}
}
The setText method does not appends the line.It overrides the text.So previous text won't be visible.
You have to append text, but have to find an mechanism for that as append method do not exist. In your console method, you can add these:
Document doc = area.getDocument();
Thread.sleep(2000);
doc.insertString(doc.getLength(),"hack installing....\n", null);
Thread.sleep(2000);
doc.insertString(doc.getLength(),"Hack installed...\n", null);
Note:
Calling Thread.sleep() is not recommended directly as you are using multi-threaded environment.It's just for your example haven't scanned your code.
public class NotEditableOutputArea extends JTextPane {
public NotEditableOutputArea() {
setEditable(false);
DefaultCaret caret = (DefaultCaret) getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
Font defaultFont = new Font("monospaced", Font.PLAIN, 12);
setFont(defaultFont);
}
public void appendColorText(String text, Color c) {
StyledDocument doc = getStyledDocument();
Style style = addStyle("Style", null);
StyleConstants.setForeground(style, c);
try {
doc.insertString(doc.getLength(), text, style);
} catch (BadLocationException e) {
}
}
public void setColorText(String text, Color c) {
setText(null);
appendColorText(text, c);
}
}
I have JTextPane (log) inside JScrollPane (logScrollPane) element. Log's content is set to "text/html".
I created a method that appends this log which looks like this:
public void appendLog(String someHTMLText)
{
HTMLDocument doc = (HTMLDocument) log.getDocument();
HTMLEditorKit editorKit = (HTMLEditorKit) log.getEditorKit();
try
{
editorKit.insertHTML(doc, doc.getLength(), someHTMLText, 0, 0, null);
}
catch (BadLocationException | IOException ex)
{
// handle exceptions
}
}
I want to improve this method and force logScrollPane's VerticalScrollBar to move_to_the_bottom/stay_at_it's_position depending on additional boolean argument.
Final method should look like this:
public void appendLog(String someHTMLText, boolean scroll)
{
if(scroll)
{
/*
* append log and set VerticalScrollBar to the bottom by
* log.setCaretPosition(log.getDocument().getLength());
*/
}
else
{
// append log BUT make VerticalScrollBar stay at it's previous position
}
}
Any suggestions? :)
Here is something similar to what I did when I wanted to achieve this. The key is to alter the behavior of scrollRectToVisible.
public class Docker extends JFrame {
boolean dockScrollbar = true;
MYTextPane textPane = new MYTextPane();
JScrollPane sp = new JScrollPane(textPane);
Docker() {
JCheckBox scrollbarDockCB = new JCheckBox("Dock scrollbar");
scrollbarDockCB.addItemListener(new DockScrollbarListener());
scrollbarDockCB.setSelected(true);
JButton insertText = new JButton("Insert text");
insertText.addActionListener(new TextInserter());
getContentPane().add(insertText, BorderLayout.PAGE_START);
getContentPane().add(sp);
getContentPane().add(scrollbarDockCB, BorderLayout.PAGE_END);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setVisible(true);
}
class MYTextPane extends JTextPane {
MYTextPane() {
setEditorKit(new HTMLEditorKit());
}
#Override
public void scrollRectToVisible(Rectangle aRect) {
if (dockScrollbar)
super.scrollRectToVisible(aRect);
}
void insertText(String msg) {
HTMLEditorKit kit = (HTMLEditorKit) getEditorKit();
HTMLDocument doc = (HTMLDocument) getDocument();
try {
kit.insertHTML(doc, doc.getLength(), msg, 0, 0, null);
} catch (BadLocationException | IOException e1) {
e1.printStackTrace();
}
setCaretPosition(doc.getLength());
}
}
class TextInserter implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
textPane.insertText("AAA\n");
}
}
class DockScrollbarListener implements ItemListener {
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
dockScrollbar = true;
JScrollBar sb = sp.getVerticalScrollBar();
sb.setValue(sb.getMaximum());
}
else if (e.getStateChange() == ItemEvent.DESELECTED)
dockScrollbar = false;
}
}
public static void main(String[] args) {
new Docker();
}
}
Notes:
I made the docking set to false when you manually scroll in my code, you can add it here too. by adding a mouse listener to the vertical scrollbar.
I have boolean dockScrollbar as a field of the text pane because I have more than one.
I don't have a field for the JScrollPane, I get it through the text pane.
I've never tried it on a JEditorPane but you should be able to use the caret update policy to control this.
Check out Text Area Scrolling for more information.
I am using this mmscomputing library as java applet to scan an image or document.
Using swings,awt i created one scan button which is acquiring scanner by calling scanner.acquire() method of mmscomputing jar..
and then placing that scanned image into jpanel for displaying.
Problem is, first time when i start my applet and hitting my scan button..scanning works fine..Twain states it goes into are: 3,4,5,6,7,5,4,3
then second time,hitting my scan button again ..
Twain states it goes into are: 3,4,5,4,3
It's not going into image transfer ready and transferring state and thus not into below CODE IF loop
if (type.equals(ScannerIOMetadata.ACQUIRED))
so i am not able to see the new scanned image into my jpanel second time...
then third time, hitting my scan button .. again it works fine.. getting into all states.
So i mean, For alternatively turns or restarting the java applet again ..it works.
what would be the issue.. ?
I want, every time when i hit scan button it should get me a new image into Jpanel.. but it's doing alternative times.
can i forcefully explicitly set or change twain states to come into 6th and 7th states..
or is there some twain source initialisation problem occurs second time?
because restarting applet is doing fine every time.. or some way to reinitialise applet objects everytime on clicking scan button..as it would feel like I am restarting applet everytime on clicking scan button...
I am not getting it..
Below is the sample code:
import uk.co.mmscomputing.device.twain.TwainConstants;
import uk.co.mmscomputing.device.twain.TwainIOMetadata;
import uk.co.mmscomputing.device.twain.TwainSource;
import uk.co.mmscomputing.device.twain.TwainSourceManager;
public class XXCrop extends JApplet implements PlugIn, ScannerListener
{
private JToolBar jtoolbar = new JToolBar("Toolbar", JToolBar.HORIZONTAL);
ImagePanel ipanel;
Image im =null;
BufferedImage imageforCrop;
ImagePlus imp=null;
int imageWidth;
int imageHeight;
private static final long serialVersionUID = 1L;
Container content = null;
private JPanel jContentPane = null;
private JButton jButton = null;
private JButton jButton1 = null;
JCheckBox clipBox = null;
JPanel crpdpanel=null;
JPanel cpanel=null;
private Scanner scanner=null;
private TwainSource ts ;
private boolean is20;
ImagePanel imagePanel,imagePanel2 ;
public static void main(String[] args) {
new XXCrop().setVisible(true);
}
public void run(String arg0) {
new XXCrop().setVisible(false);
repaint();
}
/**
* This is the default constructor
*/
public XXCrop() {
super();
init();
try {
scanner = Scanner.getDevice();
if(scanner!=null)
{
scanner.addListener(this);
}
} catch (Exception e)
{
e.printStackTrace();
}
}
/**
* This method initializes this
*
* #return void
*/
public void init()
{
this.setSize(1200, 600);
this.setLayout(null);
//this.revalidate();
this.setContentPane(getJContentPane());
}
private JToolBar getJToolBar()
{
jtoolbar.add(getJButton1());
jtoolbar.add(getJButton());
jtoolbar.setName("My Toolbar");
jtoolbar.addSeparator();
Rectangle r=new Rectangle(0, 0,1024, 30 );
jtoolbar.setBounds(r);
return jtoolbar;
}
private JPanel getJContentPane()
{
if (jContentPane == null)
{
jContentPane = new JPanel();
jContentPane.setLayout(null);
jContentPane.add(getJToolBar());
}
return jContentPane;
}
private JButton getJButton() {
if (jButton == null) {
jButton = new JButton();
jButton.setBounds(new Rectangle(4, 16, 131, 42));
jButton.setText("Select Device");
jButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
if (scanner.isBusy() == false) {
selectDevice();
}
}
});
}
return jButton;
}
/* Select the twain source! */
public void selectDevice() {
try {
scanner.select();
} catch (ScannerIOException e1) {
IJ.error(e1.toString());
}
}
private JButton getJButton1()
{
if (jButton1 == null) {
jButton1 = new JButton();
jButton1.setBounds(new Rectangle(35,0, 30, 30));
jButton1.setText("Scan");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e)
{//jContentPane.remove(crpdpanel);
//jContentPane.removeAll();
//jContentPane.repaint();
//jContentPane.revalidate();
getScan();
}
});
}
return jButton1;
}
public void getScan()
{
try
{
//scanner = Scanner.getDevice();
//scanner.addListener(this);
scanner.acquire();
}
catch (ScannerIOException e1)
{
IJ.showMessage("Access denied! \nTwain dialog maybe already opened!");
e1.printStackTrace();
}
}
public Image getImage()
{
Image image = imp.getImage();
return image;
}
/*Image cimg;
public Image getCimg()
{
return cimg;
}*/
public void update(ScannerIOMetadata.Type type, ScannerIOMetadata metadata) {
if (type.equals(ScannerIOMetadata.ACQUIRED))
{
//imagePanel.revalidate();
//imagePanel.repaint();
//imagePanel.invalidate();
//jContentPane.remove(ipanel);
//ipanel.repaint();
if(imp!=null)
{
jContentPane.remove(ipanel);
jContentPane.remove(cpanel);
jContentPane.remove(crpdpanel);
}
imp = new ImagePlus("Scan", metadata.getImage());
//imp.show();
im = imp.getImage();
//imagePanel = new ImagePanel(im,imageWidth,imageHeight);
imagePanel = new ImagePanel(im);
imagePanel.updateUI();
imagePanel.repaint();
imagePanel.revalidate();
ClipMover mover = new ClipMover(imagePanel);
imagePanel.addMouseListener(mover);
imagePanel.addMouseMotionListener(mover);
ipanel = imagePanel.getPanel();
ipanel.setBorder(new LineBorder(Color.blue,1));
ipanel.setBorder(BorderFactory.createTitledBorder("Scanned Image"));
ipanel.setBounds(0, 30,600, 600);
ipanel.repaint();
ipanel.revalidate();
ipanel.updateUI();
jContentPane.add(ipanel);
jContentPane.getRootPane().revalidate();
jContentPane.updateUI();
//jContentPane.repaint();
// cimg=imagePanel.getCimg();
// ImagePanel cpanel = (ImagePanel) imagePanel.getUIPanel();
/*
cpanel.setBounds(700, 30,600, 800);
jContentPane.add(imagePanel.getUIPanel());
*/
cpanel = imagePanel.getUIPanel();
cpanel.setBounds(700, 30,300, 150);
cpanel.repaint();
cpanel.setBorder(new LineBorder(Color.blue,1));
cpanel.setBorder(BorderFactory.createTitledBorder("Cropping Image"));
jContentPane.add(cpanel);
jContentPane.repaint();
jContentPane.revalidate();
metadata.setImage(null);
try {
new uk.co.mmscomputing.concurrent.Semaphore(0, true).tryAcquire(2000, null);
} catch (InterruptedException e) {
IJ.error(e.getMessage());
}
}
else if (type.equals(ScannerIOMetadata.NEGOTIATE)) {
ScannerDevice device = metadata.getDevice();
try {
device.setResolution(100);
} catch (ScannerIOException e) {
IJ.error(e.getMessage());
}
try{
device.setShowUserInterface(false);
// device.setShowProgressBar(true);
// device.setRegionOfInterest(0,0,210.0,300.0);
device.setResolution(100); }catch(Exception e){
e.printStackTrace(); }
}
else if (type.equals(ScannerIOMetadata.STATECHANGE)) {
System.out.println("Scanner State "+metadata.getStateStr());
System.out.println("Scanner State "+metadata.getState());
//switch (metadata.ACQUIRED){};
ts = ((TwainIOMetadata)metadata).getSource();
//ts.setCancel(false);
//ts.getState()
//TwainConstants.STATE_TRANSFERREADY
((TwainIOMetadata)metadata).setState(6);
if ((metadata.getLastState() == 3) && (metadata.getState() == 4)){}
// IJ.error(metadata.getStateStr());
}
else if (type.equals(ScannerIOMetadata.EXCEPTION)) {
IJ.error(metadata.getException().toString());
}
}
public void stop(){ // execute before System.exit
if(scanner!=null){ // make sure user waits for scanner to finish!
scanner.waitToExit();
ts.setCancel(true);
try {
scanner.setCancel(true);
} catch (ScannerIOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I'm not an expert, but when ScannerIOMetadata.STATECHANGE shouldn't you check if the scanning is complete?
And if it is you should initialize the scanner again.
Something like that:
if (metadata.isFinished())
{
twainScanner = (TwainScanner) Scanner.getDevice();
}
I want To insert hyperlink in JPanel (so that on clicking i go to web address)
Is it possible ?
If yes, how can i do this?
See the How to Use HTML in Swing Components
tutorial.
We've been using something like this:
public class UrlTextPane extends JTextPane {
private final Pattern urlPattern = Pattern.compile(UrlUtil.URL_REGEX);
public UrlTextPane() {
this.setEditable(false);
this.addHyperlinkListener(new UrlHyperlinkListener());
this.setContentType("text/html");
}
private class UrlHyperlinkListener implements HyperlinkListener {
#Override
public void hyperlinkUpdate(final HyperlinkEvent event) {
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
try {
Desktop.getDesktop().browse(event.getURL().toURI());
} catch (final IOException e) {
throw new RuntimeException("Can't open URL", e);
} catch (final URISyntaxException e) {
throw new RuntimeException("Can't open URL", e);
}
}
}
};
#Override
/**
* Set the text, first translate it into HTML:
*/
public void setText(final String input) {
final StringBuilder answer = new StringBuilder();
answer.append("<html><body style=\"font-size: 8.5px;font-family: Tahoma, sans-serif\">");
final String content = StringEscapeUtils.escapeHtml(input);
int lastIndex = 0;
final Matcher matcher = urlPattern.matcher(content);
while(matcher.find()) {
//Append everything since last update to the url:
answer.append(content.substring(lastIndex, matcher.start()));
final String url = content.substring(matcher.start(), matcher.end()).trim();
if(UrlUtil.isValidURI(url)) {
answer.append(""+url+"");
} else {
answer.append(url);
}
lastIndex = matcher.end();
}
//Append end:
answer.append(content.substring(lastIndex));
answer.append("</body></html>");
super.setText(answer.toString().replace("\n", "<br />"));
}
}
I wrote a simple function that takes the text, link, and the position you want to display and returns a JLabel. When the mouse is over the text, it becomes blue with underline and makes cursor a pointing hand, otherwise it becomes black with no underline and default cursor.
public static JLabel makeHyperLink(final String s, final String link, int x, int y)
{
final JLabel l = new JLabel(s);
l.addMouseListener(new MouseAdapter()
{
#Override
public void mouseExited(MouseEvent arg0)
{
l.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
l.setText(s);
}
#Override
public void mouseEntered(MouseEvent arg0)
{
l.setCursor(new Cursor(Cursor.HAND_CURSOR));
l.setText(String.format("<HTML><FONT color = \"#000099\"><U>%s</U></FONT></HTML>", s));
}
#Override
public void mouseClicked(MouseEvent arg0)
{
try
{
URI uri = new URI(link);
if (Desktop.isDesktopSupported())
Desktop.getDesktop().browse(uri);
} catch (Exception e)
{
}
}
});
l.setBounds(x, y, s.length()*5, 20);
l.setToolTipText(String.format("go to %s", link));
return l;
}
If any part of code is not clear, contact me;)
Yes possible,
Use HTML
Add one JLabel use HTML as text and add it to Panel