Is there anyway to add text inside picture in JFrame? - java

EDIT:Damn, my english is a bit off. I meant to ask how to add text "inside" picture not over(above) it , with the text be at the center of picture.
thank you for previous helps anyway :).

One way is to use OverlayLayout. For the text to be at the center of the image in both axes an alignment value of 0.5 should be used for both X & Y for both JLabel components shown below.
public class OverlayLabelApp {
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Overlay App");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
LayoutManager overlay = new OverlayLayout(panel);
panel.setLayout(overlay);
JLabel label1 = new JLabel("Centered Text");
label1.setForeground(Color.GREEN);
label1.setFont(new Font("SansSerif", Font.BOLD, 16));
label1.setAlignmentX(0.5f);
label1.setAlignmentY(0.5f);
panel.add(label1);
JLabel label2 =
new JLabel(new ImageIcon(OverlayLabelApp.class.getResource("/images/sunset.png"))); label2.setAlignmentX(0.5f);
label2.setAlignmentY(0.5f);
panel.add(label2);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
});
}
}

Sure. Paint the text direct to the picture. Display the picture in a label.
E.G.
How to edit a text that is converted into image?
How to resize text in java
Of course, if you want it 'simpler' there are other options. One is OverlayLayout as described by #Reimeus. Here is another. It utilizes the fact that we can set a layout for a label, and show components within it. This technique was popularized by #mKorbel.
import java.awt.*;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
class TextOnImage {
public static void main(String[] args) throws Exception {
URL url = new URL("http://i.stack.imgur.com/zJ8am.png");
final BufferedImage image = ImageIO.read(url);
Runnable r = new Runnable() {
#Override
public void run() {
JPanel gui = new JPanel(new BorderLayout());
JLabel l = new JLabel(new ImageIcon(image));
l.setLayout(new FlowLayout(FlowLayout.CENTER));
JLabel text = new JLabel("Hi!");
l.add(text);
JOptionPane.showMessageDialog(null, l);
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(r);
}
}

with the text be at the center of picture.
4 more approaches. The first is the easiest and sounds like what you want:
import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
public class LabelImageText extends JPanel
{
public LabelImageText()
{
JLabel label1 = new JLabel( new ColorIcon(Color.ORANGE, 100, 100) );
label1.setText( "Easy Way" );
label1.setHorizontalTextPosition(JLabel.CENTER);
label1.setVerticalTextPosition(JLabel.CENTER);
add( label1 );
//
JLabel label2 = new JLabel( new ColorIcon(Color.YELLOW, 200, 150) );
label2.setLayout( new BoxLayout(label2, BoxLayout.Y_AXIS) );
add( label2 );
JLabel text = new JLabel( "More Control" );
text.setAlignmentX(JLabel.CENTER_ALIGNMENT);
label2.add( Box.createVerticalGlue() );
label2.add( text );
label2.add( Box.createVerticalStrut(10) );
//
JLabel label3 = new JLabel( new ColorIcon(Color.GREEN, 200, 150) );
add( label3 );
JLabel text3 = new JLabel();
text3.setText("<html><center>Text<br>over<br>Image<center></html>");
text3.setLocation(20, 20);
text3.setSize(text3.getPreferredSize());
label3.add( text3 );
//
JLabel label4 = new JLabel( new ColorIcon(Color.CYAN, 200, 150) );
add( label4 );
JTextPane textPane = new JTextPane();
textPane.setText("Add some text that will wrap at your preferred width");
textPane.setEditable( false );
textPane.setOpaque(false);
SimpleAttributeSet center = new SimpleAttributeSet();
StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER);
StyledDocument doc = textPane.getStyledDocument();
doc.setParagraphAttributes(0, doc.getLength(), center, false);
textPane.setBounds(20, 20, 75, 100);
label4.add( textPane );
}
public static class ColorIcon implements Icon
{
private Color color;
private int width;
private int height;
public ColorIcon(Color color, int width, int height)
{
this.color = color;
this.width = width;
this.height = height;
}
public int getIconWidth()
{
return width;
}
public int getIconHeight()
{
return height;
}
public void paintIcon(Component c, Graphics g, int x, int y)
{
g.setColor(color);
g.fillRect(x, y, width, height);
}
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("LabelImageText");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new LabelImageText() );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}

Related

Java Swing GridLayout Change Grid Sizes

I'm trying to create a program that lists movies in a Netflix style to learn Front-End coding.
How I want it to look in the end:
My guess is that every movie is a button component with an image a name label and a release year label.
I'm struggling to recreate this look. This is how it looks when I try it:
The navigationbar in my image is at the page start of a border layout. Below the navigationbar the movie container is in the center of the border layout.
My idea was creating a GridLayout and then create a button for each movie and adding it to the GridLayout.
You can recreate this with this code:
public class Main {
private static JFrame frame;
public static void main(String[] args) throws HeadlessException {
frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.setBackground(new Color(32, 32, 32));
JPanel navigationPanel = createNavigationBar();
frame.add(navigationPanel, BorderLayout.PAGE_START);
JPanel moviePanel = createMoviePanel();
frame.add(moviePanel, BorderLayout.CENTER);
frame.setPreferredSize(new Dimension(1920, 1080));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Example App");
frame.pack();
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setVisible(true);
}
public static JPanel createMoviePanel() {
JPanel moviePanel = new JPanel();
GridLayout layout = new GridLayout(0, 10);
layout.setHgap(3);
layout.setVgap(3);
moviePanel.setLayout(layout);
moviePanel.setBackground(new Color(32, 32, 32));
ArrayList<String> exampleList = new ArrayList<>();
// Add stuff to the example list
for(int i = 0; i < 120; i++) {
exampleList.add(Integer.toString(i));
}
final File root = new File("");
for(final String movie : exampleList) {
JLabel picLabel = new JLabel();
try {
File imageFile = new File(root.getAbsolutePath() + "\\src\\images\\" + "imageName.jpg"); // Try to find the cover image
if(imageFile.exists()) {
BufferedImage movieCover = ImageIO.read(imageFile);
picLabel = new JLabel(new ImageIcon(movieCover));
} else {
BufferedImage movieCover = ImageIO.read(new File(root.getAbsolutePath() + "\\src\\images\\temp.jpg")); // Get a temp image
picLabel = new JLabel(new ImageIcon(movieCover));
}
} catch (IOException e) {
e.printStackTrace();
}
JLabel movieName = new JLabel("New Movie");
movieName.setForeground(Color.WHITE);;
JButton movieButton = new JButton();
movieButton.setLayout(new GridLayout(0, 1));
//movieButton.setContentAreaFilled(false);
//movieButton.setBorderPainted(false);
//movieButton.setFocusPainted(false);
movieButton.add(picLabel);
movieButton.add(movieName);
moviePanel.add(movieButton);
}
return moviePanel;
}
public static JPanel createNavigationBar() {
JPanel navBar = new JPanel();
navBar.setLayout(new FlowLayout(FlowLayout.LEFT, 30, 20));
navBar.setBackground(new Color(25, 25, 25));
JButton homeButton = new JButton("Home");
homeButton.setContentAreaFilled(false);
homeButton.setBorderPainted(false);
homeButton.setFocusPainted(false);
JButton movieButton = new JButton("Movies");
movieButton.setContentAreaFilled(false);
movieButton.setBorderPainted(false);
movieButton.setFocusPainted(false);
// Add all the buttons to the navbar
navBar.add(homeButton);
navBar.add(movieButton);
return navBar;
}
}
I noticed that the GridLayout always tries to fit everything onto the window.
All that's needed is a properly configured JButton in a GridLayout.
E.G.
public static JPanel createMoviePanel() {
JPanel movieLibraryPanel = new JPanel(new GridLayout(0, 10, 3, 3));
movieLibraryPanel.setBackground(new Color(132, 132, 132));
int m = 5;
BufferedImage image = new BufferedImage(9 * m, 16 * m, BufferedImage.TYPE_INT_RGB);
for (int ii = 1; ii < 21; ii++) {
JButton picButton = new JButton("Mov " + ii, new ImageIcon(image));
picButton.setMargin(new Insets(0,0,0,0));
picButton.setForeground(Color.WHITE);
picButton.setContentAreaFilled(false);
picButton.setHorizontalTextPosition(JButton.CENTER);
picButton.setVerticalTextPosition(JButton.BOTTOM);
movieLibraryPanel.add(picButton);
}
return movieLibraryPanel;
}
Here is a complete source for the above with a tweak to put the year on a new line. It uses HTML in the JButton to break the button text into two lines.
The input focus is on the first button, whereas the mouse hovers over the '2009' movie:
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
class MovieGrid {
MovieGrid() {
JFrame f = new JFrame("Movie Grid");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.add(createMoviePanel());
f.pack();
f.setVisible(true);
}
public static JPanel createMoviePanel() {
JPanel movieLibraryPanel = new JPanel(new GridLayout(0, 10, 3, 3));
movieLibraryPanel.setBackground(new Color(132, 132, 132));
int m = 5;
BufferedImage image = new BufferedImage(
9 * m, 16 * m, BufferedImage.TYPE_INT_RGB);
for (int ii = 2001; ii < 2021; ii++) {
JButton picButton = new JButton(
"<html>Movie<br>" + ii, new ImageIcon(image));
picButton.setMargin(new Insets(0,0,0,0));
picButton.setForeground(Color.WHITE);
picButton.setContentAreaFilled(false);
picButton.setHorizontalTextPosition(JButton.CENTER);
picButton.setVerticalTextPosition(JButton.BOTTOM);
movieLibraryPanel.add(picButton);
}
return movieLibraryPanel;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new MovieGrid();
}
};
SwingUtilities.invokeLater(r);
}
}
Same idea's from Andrew Thompson answer but with some minor text alignment changes and hover effect
final class Testing
{
public static void main(String[] args)
{
JFrame frame=new JFrame("NEFLIX");
frame.setContentPane(new GridDisplay());
frame.pack();
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private static final class GridDisplay extends JPanel implements ActionListener
{
private GridDisplay()
{
super(new GridLayout(0,5,20,20));
setBackground(new Color(0,0,0,255));
BufferedImage image=new BufferedImage(150,200,BufferedImage.TYPE_INT_RGB);
Graphics2D g2d=(Graphics2D)image.getGraphics();
g2d.setColor(Color.BLUE);
g2d.fillRect(0,0,image.getWidth(),image.getHeight());
HoverPainter painter=new HoverPainter();
for(int i=0;i<10;i++)
{
TVShowCard card=new TVShowCard(image,"Show "+i,"199"+i);
card.addMouseListener(painter);
add(card);
}
}
//highlight only on hover
private final class HoverPainter extends MouseAdapter
{
#Override
public void mouseExited(MouseEvent e) {
((TVShowCard)e.getSource()).setBorderPainted(false);
}
#Override
public void mouseEntered(MouseEvent e) {
((TVShowCard)e.getSource()).setBorderPainted(true);
}
}
private final class TVShowCard extends JButton
{
private TVShowCard(BufferedImage preview,String name,String year)
{
super();
setContentAreaFilled(false);
setBackground(new Color(0,0,0,0));
setFocusPainted(false);
setBorderPainted(false);
//I didn't use image icon & text horizontal alignment because the text always horizontally centered aligned but from the expected output it was left so created 2 labels for the job
setLayout(new GridBagLayout());
addIcon(preview);
addLabel(name,year);
addActionListener(GridDisplay.this);
}
private void addIcon(BufferedImage preview)
{
JLabel icon=new JLabel();
icon.setIcon(new ImageIcon(preview));
add(icon,new GridBagConstraints(0,0,1,1,1.0f,0.0f,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(0,0,0,0),0,0));
}
private void addLabel(String name,String year)
{
JLabel label=new JLabel("<html><body>"+name+"<br>"+year+"</body></html>");
label.setForeground(Color.white);
label.setBackground(new Color(0,0,0,0));
add(label,new GridBagConstraints(0,1,1,1,1.0f,1.0f,GridBagConstraints.SOUTHWEST,GridBagConstraints.NONE,new Insets(5,0,0,0),0,0));
}
}
#Override
public void actionPerformed(ActionEvent e)
{
TVShowCard card=(TVShowCard)e.getSource();
//do stuff with it
}
}
}

How to alignment each JPanel to left or to right into main JPanel

I wanna my app look like this:
I have to try use
jpanel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
jpanel.setAlignmentX(JPanel.RIGHT_ALIGNMENT);
But it's working for first jpanel when I add it into main_JPanel. Show correctly
But when I add the JPanel2, JPanel3,... then main_Panel show not correctly, it show this:
This my function create each JPanel
public JPanel makeJpanel(String Mess, String username) {
int height = 40;
int width = 200;
JTextPane textPane = new JTextPane();
textPane.setEditable(false);
StyledDocument doc = textPane.getStyledDocument();
String rs = splitMess(Mess);
Mess = rs.substring(2).trim();
Style style = textPane.addStyle("I'm a Style", null);
StyleConstants.setFontFamily(style, "Arial");
StyleConstants.setBold(style, true);
StyleConstants.setFontSize(style, 20);
StyleConstants.setForeground(style, new Color(19, 51, 55));
try {
doc.insertString(doc.getLength(), Mess.trim(), style);
} catch (BadLocationException e) {
}
height = (int) Math.round(textPane.getPreferredSize().getHeight());
width = (int) Math.round(textPane.getPreferredSize().getWidth());
//creat avatar
JLabel ava = null;
if (username.equals(this.userName)) {
ava = new JLabel(label_myAvaProfile1.getIcon());
} else {
ava = new JLabel(label_avaYourFriends1.getIcon());
}
JLabel borderAva = new JLabel(border_label_avaYourFriends.getIcon());
if (height < 40) {
ava.setPreferredSize(new Dimension(40, 40));
borderAva.setPreferredSize(new Dimension(40, 40));
} else {
ava.setPreferredSize(new Dimension(40, height));
borderAva.setPreferredSize(new Dimension(40, height));
}
JLayeredPane lpAva = new JLayeredPane();
lpAva.setLayout(new OverlayLayout(lpAva));
lpAva.add(borderAva);
lpAva.add(ava);
JPanel panelChat = new JPanel();
panelChat.setLayout(new BoxLayout(panelChat, BoxLayout.LINE_AXIS));
panelChat.setBackground(Color.WHITE);
panelChat.setPreferredSize(new Dimension(width + 40, height));
panelChat.setMinimumSize(new Dimension(width + 40, height));
panelChat.setMaximumSize(new Dimension(width + 40, height));
if (username.equals(this.userName)) {
panelChat.add(textPane);
panelChat.add(lpAva);
//NOTICE THIS
panelChat.setAlignmentX(JPanel.LEFT_ALIGNMENT);
} else if (username.equals(currentFriendUserName)) {
panelChat.add(lpAva);
panelChat.add(textPane);
//NOTICE THIS
panelChat.setAlignmentX(JPanel.RIGHT_ALIGNMENT);
}
resetPanelListFriends(panelChat);
return panelChat;
}
This function I call when i add new Jpanel
public void renderPanelChatLog()
{
JPanel panelChat = new JPanel();
panelChat = makeJPanel(mess, username);
if (panelChat != null) {
panel_ChatLog.add(panelChat);
panel_ChatLog.add(Box.createVerticalStrut(20));
}
resetPanelListFriends(panel_ChatLog);
}
Sorry My English, I'm just new guy... Plzz help me!
Here is one way:
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class BoxLayoutAligned
{
private static void createAndShowGUI()
{
JLabel left = new JLabel( "Left Aligned" );
Box leftBox = Box.createHorizontalBox();
leftBox.add( left );
leftBox.add( Box.createHorizontalGlue() );
JLabel right = new JLabel( "Right Aligned" );
Box rightBox = Box.createHorizontalBox();
rightBox.add( Box.createHorizontalGlue() );
rightBox.add( right );
Box vertical = Box.createVerticalBox();
vertical.setBorder( new EmptyBorder(0, 10, 0, 10) );
vertical.add( leftBox );
vertical.add( rightBox );
JFrame frame = new JFrame("BoxLayout Aligned");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(vertical);
frame.setSize(300, 300);
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args) throws Exception
{
java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
}
}
By adding "glue" you allow the other components added to the Box to be aligned to the left or right.

Make TitledBorder editable upon double click

This is an extension of : Make a TitledBorder title editable
To be more specific, I want the TitledBorder to be editable when the title is double clicked. I'm placing the Border around a java Box that uses BoxLayout. The double click would preferably open a JTextField right there, but if that cannot be done, opening another window to edit the title is acceptable.
TitledBorder editableBorder = new TitledBorder(editableString);
editableBorder.setTitleJustification(TitledBorder.CENTER);
Box containerBox = new Box(BoxLayout.PAGE_AXIS);
containerBox.setBorder(new CompoundBorder(editableBorder, new EmptyBorder(10, 0, 10, 0)));
Box insideBox = new Box(BoxLayout.PAGE_AXIS);
insideBox.add(new JLabel(new ImageIcon(new BufferedImage(200,40,BufferedImage.TYPE_INT_RGB))));
containerBox.add(insideBox);
Here is an example. The MouseListener uses a JPopupMenu to display the text field. This means you can cancel editing by using the Escape key.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class TitledBorderListener extends MouseAdapter
{
private JPopupMenu editPopup;
private JTextField editTextField;
private TitledBorder titledBorder;
#Override
public void mouseClicked(MouseEvent e)
{
if (e.getClickCount != 2)
return;
// Edit the border on a double click
JComponent component = (JComponent)e.getSource();
Border border = component.getBorder();
if (border instanceof TitledBorder)
{
titledBorder = (TitledBorder)border;
FontMetrics fm = component.getFontMetrics( titledBorder.getTitleFont() );
int titleWidth = fm.stringWidth(titledBorder.getTitle()) + 20;
Rectangle bounds = new Rectangle(0, 0, titleWidth, fm.getHeight());
if (bounds.contains(e.getPoint()))
{
if (editPopup == null)
createEditPopup();
// Position the popup editor over top of the title
editTextField.setText( titledBorder.getTitle() );
Dimension d = editTextField.getPreferredSize();
d.width = titleWidth;
editPopup.setPreferredSize(d);
editPopup.show(component, 0, 0);
editTextField.selectAll();
editTextField.requestFocusInWindow();
}
}
}
private void createEditPopup()
{
editTextField = new JTextField();
// Add an Action to the text field to save the new title text
editTextField.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String value = editTextField.getText();
titledBorder.setTitle( value );
editPopup.setVisible(false);
editPopup.getInvoker().revalidate();
editPopup.getInvoker().repaint();
}
});
// Add the editor to the popup
editPopup = new JPopupMenu();
editPopup.setBorder( new EmptyBorder(0, 0, 0, 0) );
editPopup.add(editTextField);
}
private static void createAndShowUI()
{
JPanel panel = new JPanel();
panel.setBorder( new TitledBorder("Double Click to Edit") );
panel.addMouseListener( new TitledBorderListener() );
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( panel );
frame.setSize(200, 200);
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}

JPanel titled border with tooltip text for the title

I am using setBorder(BorderFactory.createTitledBorder(title)) in my JPanel in order to group its content in a rectangle with a title above it. How can I set a tooltip text for the title?
A possible approach is nesting components. As Borders are not components they can not have tooltips, but you can have a component with the sole purpose of holding border and the tooltip:
JPanel outer = new JPanel();
outer.setBorder(BorderFactory.createTitledBorder("Title"));
outer.setToolTipText("sample text");
JPanel inner = new JPanel();
outer.add(inner);
and then use inner as the container for the components you want to group.
You can override the getToolTipText() method of the panel to check if the mouse of over the title text:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class TitledBorderTest
{
private static void createAndShowUI()
{
UIManager.getDefaults().put("TitledBorder.titleColor", Color.RED);
Border lowerEtched = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
TitledBorder title = BorderFactory.createTitledBorder(lowerEtched, "Title");
// title.setTitleJustification(TitledBorder.RIGHT);
Font titleFont = UIManager.getFont("TitledBorder.font");
title.setTitleFont( titleFont.deriveFont(Font.ITALIC + Font.BOLD) );
JPanel panel = new JPanel()
{
#Override
public String getToolTipText(MouseEvent e)
{
Border border = getBorder();
if (border instanceof TitledBorder)
{
TitledBorder tb = (TitledBorder)border;
FontMetrics fm = getFontMetrics( tb.getTitleFont() );
int titleWidth = fm.stringWidth(tb.getTitle()) + 20;
Rectangle bounds = new Rectangle(0, 0, titleWidth, fm.getHeight());
return bounds.contains(e.getPoint()) ? super.getToolTipText() : null;
}
return super.getToolTipText(e);
}
};
panel.setBorder( title );
panel.setToolTipText("Title With ToolTip");
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( panel );
frame.setSize(200, 200);
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
This code assumes the title is on the left. If you want the title on the right then you would need to adjust the X value of the text bounds.
I don't think you can add setToolTipText to TitledBorder. you can provide tooltip for JComponent but TitledBorder is not derived from JComponent.
You can try to use JPanel instead:
ToolTipManager.sharedInstance().registerComponent(new JPanel());
//ToolTipManager.sharedInstance().setDismissDelay(800000);
TollTip isn't right Components for experiments, all goog workaround for popup or tooltips are based on JWindow/ undecorated JDialog
maybe not necessary, keys in UIManager are accesible, but in this case all TollTips has the same settings
import java.awt.*;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.plaf.*;
public class ColoredToolTipExample extends JFrame {
private static final long serialVersionUID = 1L;
public ColoredToolTipExample() {
Border line, raisedbevel, loweredbevel, title, empty;
line = BorderFactory.createLineBorder(Color.black);
raisedbevel = BorderFactory.createRaisedBevelBorder();
loweredbevel = BorderFactory.createLoweredBevelBorder();
title = BorderFactory.createTitledBorder("");
empty = BorderFactory.createEmptyBorder(1, 1, 1, 1);
Border compound;
compound = BorderFactory.createCompoundBorder(empty, line);
UIManager.put("ToolTip.foreground", new ColorUIResource(Color.red));
UIManager.put("ToolTip.background", new ColorUIResource(Color.yellow));
UIManager.put("ToolTip.font", new FontUIResource(new Font("Verdana", Font.PLAIN, 18)));
UIManager.put("ToolTip.border", new BorderUIResource(compound));
JButton button = new JButton("Hello, world");
button.setToolTipText("<html> - myText <br> - myText <br> - myText <br>");
getContentPane().add(button);
JFrame frame = new JFrame("Colored ToolTip Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 100);
frame.setVisible(true);
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ColoredToolTipExample();
}
});
}
}

How can I measure/calculate the size a Document needs to render itself?

I have a javax.swing.text.Document and I want to calculate the size of the bounding box that document needs to render itself.
Is that possible?
It is almost trivial for plain text (height = line count * line height, width = max width over each line) But how can I do this with RTF, HTML or any other document?
This code might give you some ideas:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class TextPanePerfectSize extends JFrame
{
JTextField textField;
JTextPane textPane;
public TextPanePerfectSize()
{
textField = new JTextField(20);
textField.setText("add text");
getContentPane().add(textField, BorderLayout.NORTH );
textField.addActionListener( new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try
{
Document doc = textPane.getDocument();
doc.insertString(doc.getLength(), " " + textField.getText(), null);
textField.setText("");
Dimension d = textPane.getPreferredSize();
Rectangle r = textPane.modelToView( textPane.getDocument().getLength() );
d.height = r.y + r.height;
textPane.setPreferredSize( d );
getContentPane().validate();
// pack();
}
catch(Exception e2) {}
}
});
JLabel label = new JLabel("Hit Enter to Add Text to Text Pane");
getContentPane().add(label);
JPanel south = new JPanel();
textPane = new JTextPane();
textPane.setText("Some text");
textPane.setEditable( false );
// textPane.setPreferredSize( new Dimension(120, 23) );
south.add( textPane );
// getContentPane().add(south, BorderLayout.SOUTH);
getContentPane().add(textPane, BorderLayout.SOUTH);
}
public static void main(String[] args)
{
JFrame frame = new TextPanePerfectSize();
frame.setSize(200, 200);
frame.setLocationRelativeTo( null );
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
The Document interface is a model for a text component, so the Document doesn't really have a boundary; but the View has a number of methods that "translate between the model and view coordinate systems." Depending on the goal, something there may help.
Try to use this to measure height for fixed widht.
http://java-sl.com/tip_text_height_measuring.html
The getPreferred will return you the width and height.

Categories