I need to draw a string to a BufferedImage in Java. The way this is done doesn't matter, however the image should take up only the space it needs, like in the example below.
I need a new BufferedImage created containing only the string. Extra space above the string and on the right side of the string could be tolerated, but I can't have extra space below and left of the drawn string.
Is something like this possible? I have tried to do it myself, but I always end up having extra space which is not what I want. Any help would be appreciated.
You can use Graphics2D#drawString method:
import java.awt.Container;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class MainClass{
public static void main(String[] args) {
JFrame jf = new JFrame("Demo");
Container cp = jf.getContentPane();
MyCanvas tl = new MyCanvas();
cp.add(tl);
jf.setSize(300, 200);
jf.setVisible(true);
}
}
class MyCanvas extends JComponent {
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Font font = new Font("Serif", Font.PLAIN, 96);
g2.setFont(font);
g2.drawString("Test string", 40, 120);
}
}
I need to draw a string to an image in Java. I have tried to do it myself, but I always end up having extra space
I can't tell if you are trying to create an image of a String or add some text to an existing image. Since you say you have extra space I assume you are trying to create an image of the text and you don't know how big to make the BufferedImage that you are drawing on.
Create a JLabel with the text you want. Then you can use the Screen Image class to create an image of the label component. The the image will be the exact size pf the text.
Related
So, I have this simple program that paints a string on JPanel using g2.drawString("Hello world", 40, 120). Basically, I want to be able to keep track of many strings on the JPanel at once. I'm not sure how to do this. For example, I would want to have an ArrayList of objects that keep track of these strings.
I want to be able to click-and-drag these strings so I will need to know there locations, etc.
Right now, using g2.drawString, it only draws the string. I want something like gw.draw(myStringObject). Not sure if this is a dumb request but this is what I am looking for. Thanks!
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DrawSimpleText extends JPanel {
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Font font = new Font("Serif", Font.PLAIN, 96);
g2.setFont(font);
g2.drawString("Hello world", 40, 120);
}
public static void main(String[] args) {
JFrame f = new JFrame();
f.getContentPane().add(new DrawSimpleText());
f.setSize(300, 200);
f.setVisible(true);
}
}
I want to be able to click-and-drag these strings so I will need to know there locations, etc.
Use a JLabel, then you can just drag them like any component.
See Component Mover for one way to do the dragging.
So I've been trying for the last two hours to get this program to draw a simple rectangle in a frame but nothing gets displayed in the frame when i run the program. I've looked through textbooks and old notebooks and everything in my program seems to be fine, yet nothing is displayed. Help?
This is the class that creates the frame and is supposed to draw the rectangle.
import javax.swing.JFrame;
public class FrameViewer {
public static void main(String[] args) {
//creates an empty frame.
JFrame frame = new JFrame();
frame.setSize(300,400);
frame.setTitle("Empty Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//draws the rectangle within the frame.
RectangleComponent component = new RectangleComponent();
frame.add(component);
frame.setVisible(true);
}
}
And here is the RectangleComponent
import javax.swing.JComponent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
public class RectangleComponent extends JComponent{
public void paintCOmponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
Rectangle box = new Rectangle(5,10,20,30);
g2.draw(box);
}
}
Java is case sensitive, instead of
paintCOmponent
You want
paintComponent
You should use the #Override annotation to mark methods you think you are overriding as it will highlight problems like this.
The method should also remain protected, as there is no reason any one should be calling from outside the class
You may also want to take a look at Initial Threads
I have a JFrame that I am putting several JButtons on. Half the JButtons have color coding--i.e. I turn them blue when X event happens--and I use btn.setBackgroundColor(Color). When I use setBackgroundColor, I can see that I look the ones that are normal JButtons have shading/coloring/something that the ones with the setBackgroundColor do not. I've tried making the color transparent to a limited degree, but I still get a flat block of color, rather than a tinted version of the shaded button.
This seems like it should be a pretty easy thing to fix, but it is bugging me right now. I don't want to change the default LAF--it's fine. I don't want to abandon the color change. I do want the buttons to all appear styled (the word I'd use for HTML).
So I'm missing something right here....what is it?
Edited to add:
JFrame frame = new JFrame();
frame.add(new JButton("42"));
JButton btn24 = new JButton("24");
btn24.setBackground(Color.red);
frame.add(btn24);
frame.setVisible(true);
In the above example, "42" will--on my Windows machine--show a slight color variation at the bottom and the top, creating a rounded and shaded effect. The "24" button will show a red square. My question is: Is there a way to make "24" show the rounded/shaded/styled with the red tint on top? Or do I need to simple make all my buttons flat squares for a uniform appearance?
Thanks!
Create a custom JButton and override the paint method as illustrated bellow :
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
JButton btn24 = new DepthButton("24");
JButton btn25 = new DepthButton("25");
btn24.setBackground(Color.red);
btn25.setBackground(Color.GREEN);
JPanel pane = new JPanel(new BorderLayout());
pane.add(new JButton("42"), BorderLayout.PAGE_START);
pane.add(btn24, BorderLayout.PAGE_END);
pane.add(btn25, BorderLayout.CENTER);
frame.add(pane);
frame.pack();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setVisible(true);
}
/**
*
* #author Romain Guy
*/
public static class DepthButton extends JButton {
/** Creates a new instance of DepthButton */
public DepthButton(String text) {
super(text);
setContentAreaFilled(false);
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
GradientPaint p;
p = new GradientPaint(0, 0, new Color(0xFFFFFF), 0, getHeight(), getBackground());
Paint oldPaint = g2.getPaint();
g2.setPaint(p);
g2.fillRect(0, 0, getWidth(), getHeight());
g2.setPaint(oldPaint);
super.paintComponent(g);
}
}
}
And Here is the Result:
The example is from an excellent book for advanced java swing : Filthy Rich Clients
https://github.com/romainguy/filthy-rich-clients/blob/master/Gradients/TwoStopsGradient/src/DepthButton.java
I have an AWT component (3rd party library), and I need to mask it by showing a translucent panel over it (alpha of 128 in this case). Is there any way at all to do this? I looked at the "TransparentPanel" class that uses Sun's AWTUtilities class, but that has a limitation of not being able to show pixels with 0 < alpha < 255. Even if it's not a pretty solution, I'm just looking for some way to do this.
Maybe a GlassPane with translucent paint can solve this. Here's a simple example:
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GlassFrame extends JComponent
{
public GlassFrame()
{
super();
}
#Override
protected void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D)g.create();
Paint p = new GradientPaint(
0, 0, new Color(200,180,180,200), //Select RGB and Alpha values
getWidth(), 0, new Color(0,0,0,0)
);
g2.setPaint(p);
g2.fillRect(0, 0, getWidth(), getHeight());
g2.dispose();
}
public static void main(String args[])
{
JFrame jf = new JFrame("Simple test");
jf.add(new JPanel());
GlassFrame g = new GlassFrame();
jf.setSize(300,300);
jf.setVisible(true);
jf.setGlassPane(g);
g.setVisible(true);
}
}
As far as I know, you cannot do this. What comes closer is to create a screen capture of the AWT component while a swing component is to be shown above, and eventually refresh the screen capture now and then. That means the native component is not really there and cannot be used while in screen capture mode (does not respond to mouse clicks and key events).
This is what one of DJ NativeSwing example does to overlay a Swing PNG image with alpha transparency above an embedded web browser. Check the demo: http://djproject.sourceforge.net/ns
first of all, this is the first week that I use swing, then sorry if my question is too obvious. Also, I need solutions that use the standard java libraries, since this is for homework and I'm not allowed to use strange libraries.
I'm using JLabel with ImageIcon to show images on a JFrame. Now I want to rotate the image on screen to arbitrary angles. I found something about Graphics2D but i don't find the way to do that.
Since solutions that I found doesn't work or I don't understand them, I'm interested in any solution to rotate the ImageIcon or the JLabel. Since I'm positioning the image doing setBounds on the JLabel, rotate the JLabel will be a better solution I think (this way I'm not forced to save the ImageIcon object too).
Thank you for your attention and sorry for my bad English.
Edit...
To show the image in screen I do the next:
JFrame frame = new JFrame("Something");
frame.setLayout(new FlowLayout()); //for example
JPanel panel = new JPanel();
panel.setLayout(null);
ImageIcon playerSprite = new ImageIcon("rute/to/file.png");
JLabel player = new JLabel(playerSprite);
panel.add(player);
player.setBounds(10,10,36,52); //for example
frame.getContentPane().add(panel);
frame.setVisible(true);
Resuming, how can I rotate this IconImage or the JLabel. I can use other method to show the image if you think that is better. If the solution is use Graphics2D, like I see, I will appreciate a solution to arrive to an object of this class an later return the rotated image to an ImageIcon, because when I try this...
ImageIcon imagePlayer = new ImageIcon("img/stand.png");
Image image = imagePlayer.getImage();
Graphics2D g = (Graphics2D)image.getGraphics();
At execution time, the answer is this...
Exception in thread "main" java.lang.UnsupportedOperationException: getGraphics() not valid for images created with createImage(producer)
2th edition...
Now I'm working with this code. The image rotates but the old unrotated image still remains on screen under the new one. Put a png image called stand.png on the same directory and you will see it.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.lang.Math;
public class Test {
public static void main(String args[]) throws Exception {
try {
JFrame frame = new JFrame("Rotation Test");
frame.setBounds(10,10,1008,756);
BufferedImage bi = ImageIO.read(new File("stand.png"));
Graphics2D g = (Graphics2D)bi.getGraphics();
g.rotate(Math.toRadians(45),26,26);
g.drawImage(bi, 0, 0, null);
JLabel player = new JLabel(new ImageIcon(bi));
frame.getContentPane().add(player);
player.setBounds(0,0,100,100);
frame.setVisible(true);
} catch (IOException ex) {
System.out.println("Exception");
}
}
}
Instead of rotating the component itself, consider rotating the content of a component. This example draws a rotated image in a JPanel.
Addendum: In the example RotatableImage.getImage() creates a BufferedImage directly in memory, but you can use ImageIO.read() to obtain an image from elsewhere. BufferedImage#createGraphics() is supported if you want to modify the image, but you probably just want to draw the unmodified image in a rotated graphics context as part of paintComponent().
Addendum: You're painting over the image with a rotated copy; instead, draw the image into a rotated graphics context:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static void main(String args[]) throws Exception {
JFrame frame = new JFrame("Rotation Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final BufferedImage bi = ImageIO.read(new File("img/stand.jpg"));
frame.add(new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(bi.getWidth(), bi.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.rotate(Math.PI / 4, bi.getWidth() / 2, bi.getHeight() / 2);
g2.drawImage(bi, 0, 0, null);
}
});
frame.pack();
frame.setVisible(true);
}
}
Since solutions that I found doesn't work or I don't understand them
Well, if you don't understand them, then you should post your SSCCE (http://sscce.org) demonstrating your test code. Then maybe someone will be able to explain how the code work.
I doubt you would be able to understand any new code we might post since the concepts of rotation an image or an Icon are all the same.
Since I'm positioning the image doing setBounds on the JLabel
Why are you using setBounds(). You should use a layout manager so you don't have to worry about this.
Edit:
Maybe you can use a Rotated Icon.