How can I add images as a JPanel background? - java

I would like to make four panels using different backgrounds, and merge them together using a BorderLayout. I used JLabel, but I can't add any component to a JLabel, therefore I need to make it as a background.
I've search some code but it only tell how to add a background in JFrame.
import javax.swing.*;
import java.awt.*;
public class LoginPanel extends JFrame{
private ImageIcon top = new ImageIcon("C:/Users/user/Desktop/top.png");
private ImageIcon mid = new ImageIcon("C:/Users/user/Desktop/mid.png");
private ImageIcon center = new ImageIcon("C:/Users/user/Desktop/center.png");
private ImageIcon bottom = new ImageIcon("C:/Users/user/Desktop/bottom.png");
public LoginPanel(){
JPanel topp = new JPanel();
topp.setLayout(new BorderLayout(0,0));
topp.add(new JLabel(top),BorderLayout.NORTH);
JPanel centerp = new JPanel();
centerp.setLayout(new BorderLayout(0,0));
centerp.add(new JLabel(mid),BorderLayout.NORTH);
centerp.add(new JLabel(center),BorderLayout.SOUTH);
topp.add(new JLabel(bottom),BorderLayout.SOUTH);
topp.add(centerp,BorderLayout.CENTER);
add(topp);
}
public static void main(String[] args) {
LoginPanel frame = new LoginPanel();
frame.setTitle("Test");
frame.setSize(812, 640);
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}

I would make a new class called JImagePanel, and then use that:
class JImagePanel extends JComponent {
private static final long serialVersionUID = 1L;
public BufferedImage image;
public JImagePanel(BufferedImage image)
{
this.image = image;
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
// scale image
BufferedImage before = image;
int w = before.getWidth();
int h = before.getHeight();
BufferedImage after = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
AffineTransform at = new AffineTransform();
at.scale(2.0, 2.0);
AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
after = scaleOp.filter(before, after);
// center image and draw
Graphics2D g2d = (Graphics2D) g;
int x = (getWidth() - 1 - image.getWidth(this)) / 2;
int y = (getHeight() - 1 - image.getHeight(this)) / 2;
g2d.drawImage(image, x, y, this);
g2d.dispose();
}
}

Check out Custom Painting and 2D Graphics
Check out
Add image to panel not using swings
Java: maintaining aspect ratio of JPanel background image
Java background JFrame with a Jpanel arranging images in a grid

Related

JComponent for images with no zoom for HiDPI

I'd like to have a component that shows an image in Java without zooming on HiDPI screens.
The obvious candidate is to use a JLabel. I've succesfully done it by overwriting the AffineTransform in paintComponent but it remains the problem that the label preferred size is incorrect on HiDPI.
The following example seems to work even when I move the window from HiDPI (4K scaled 1.75) to FullHD (scale 1.0) except for the size of the component on HiDPI which is larger than the image displayed.
How can I achieve to have the preferred size of a component not to be zoomed on a HiDPI screen?
public class UnscaledImage extends JPanel {
private AffineTransform noChangeTransform = new AffineTransform();
private JLabel imageLabel;
private JLabel colorLabel = new JLabel("Color");
private BufferedImage image;
private double scale = 1.0;
public UnscaledImage() {
initUI();
packAndShow("Unscaled Image");
}
public void initUI() {
setLayout(new BorderLayout());
ImageIcon imageIcon = (ImageIcon) UIManager.getIcon("OptionPane.warningIcon");
image = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = image.createGraphics();
g2d.drawImage(imageIcon.getImage(), 0, 0, null);
g2d.dispose();
imageLabel = new JLabel() {
#Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
AffineTransform oldTransform = g2d.getTransform();
scale = oldTransform.getScaleX();
Dimension labelPrefSize = imageLabel.getPreferredSize();
if (scale != 1.0 && labelPrefSize.width == image.getWidth()) {
imageLabel.setSize(new Dimension((int) (labelPrefSize.width / scale), (int) (labelPrefSize.height / scale)));
SwingUtilities.windowForComponent(imageLabel).pack();
}
g2d.setTransform(noChangeTransform);
super.paintComponent(g);
g2d.setTransform(oldTransform);
}
};
imageLabel.setIcon(imageIcon);
imageLabel.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseMoved(MouseEvent me) {
int mouseX = (int) (me.getX() * scale);
int mouseY = (int) (me.getY() * scale);
if (mouseX < image.getWidth() && mouseY < image.getHeight()) {
int color = image.getRGB(mouseX, mouseY);
colorLabel.setBackground(new Color(color));
}
}
});
colorLabel.setOpaque(true);
colorLabel.setBackground(Color.WHITE);
add(imageLabel, BorderLayout.CENTER);
add(colorLabel, BorderLayout.SOUTH);
}
public void packAndShow(String title) {
JFrame frame = new JFrame(title);
frame.add(this);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public final static void main(String[] args) {
SwingUtilities.invokeLater(() -> new UnscaledImage());
}
}

How can i draw circle in JFrame without overriding paint(...) or paintComponent(...)

I want to draw circle using a method that I create but I get a nullPointerException
public class GenealogyTreeGUI extends JFrame {
JFrame frame;
Graphics2D g2;
public GenealogyTreeGUI(){
frame = new JFrame("Genealoy Tree");
JPanel panel = new JPanel();
frame.add(panel);
frame.setVisible(true);
panel.setVisible(true);
}
this is my method
public void drawPerson(int x, int y, Person p1){
System.out.println("----------------------DrawPerson---------------------------------");
this.g2.drawOval(x, y, frame.getWidth()/12 , frame.getHeight()/12 );
}
You can:
Create a BufferedImage of the size desired
Get its Graphics object via createGraphics() (for a Graphics2D object) or getGraphics() (for a Graphics object)
Draw with the above graphics object, and then .dispose() it
Create an ImageIcon using the above image via new ImageIcon(myImage)
Display the icon in a JLabel via .setIcon(myIcon)
done
e.g.,
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class SomeDrawingFoo extends JPanel {
private static final int IMG_W = 400;
private static final int IMG_H = IMG_W;
private static final Color COLOR_1 = Color.RED;
private static final Color COLOR_2 = Color.BLUE;
private static final float DELTA = 40f;
private JLabel label = new JLabel();
public SomeDrawingFoo() {
// create image and draw with it
BufferedImage myImage = new BufferedImage(IMG_W, IMG_H, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = myImage.createGraphics();
Paint gradPaint = new GradientPaint(0, 0, COLOR_1, DELTA, DELTA, COLOR_2, true);
g2.setPaint(gradPaint);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.fillOval(10, 10, IMG_W - 20, IMG_H - 20);
g2.dispose();
// put image into Icon and then into JLabel
Icon myIcon = new ImageIcon(myImage);
label.setIcon(myIcon);
add(label);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(()-> {
JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SomeDrawingFoo());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
Notes:
You could also call .getGraphics() on your JPanel or JFrame, but the object obtained would not be stable or long-lasting, and this will lead to images that disappear or that cause a NullPointerException. I most definitely do NOT recommend this
Usually the easiest way to do your graphics is the way that you stated you wished not doing -- draw within a JPanel's protected void paintComponent(Graphics g) method.

Graphics2d Stuff

Hey i am new to this whole coding scene and i was wondering if there was a way to this:
Graphics2D g = bufferedImage.getGraphics();
In a similar fashion to how you would do this:
int j = Integer.parseint(JOptionPane.showInputDialog);
Here is all of my code(Sorry i know its messy):
public class Drawing extends Canvas {
public static void main (String[]args) {
JFrame frame = new JFrame();
frame.setSize(800, 400);//height in pixles
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//closed program
Canvas canvas = new Drawing();
canvas.setBackground(Color.black);
canvas.setSize(800, 400);
frame.add(canvas);
frame.pack();
frame.setVisible(true);
}
private Image createImageWithText() {
BufferedImage bufferedImage = new BufferedImage(200,200,BufferedImage.TYPE_INT_RGB);
Graphics2D g = bufferedImage.getGraphics();
Image greenskull = Toolkit.getDefaultToolkit().getImage("C:\\Users\\Powell Design\\Pictures\\Saved Pictures\\greenskull");
//gets image from c drive
g.drawImage(greenskull);
return bufferedImage;
}
}

Swing drawString: Text bounds and line wrapping

I need to draw text with Graphics#drawString
I'm drawing on top of a JPanel that changes both in width and height (by dragging).
I'm looking for a solution to generate bounds, so that I can warp the lines automatically and adapt the text accordingly, without overflows.
I figured I could just hardcode it myself by getting the length in pixels with fontMetrics, however, I would rather have a component that does this automatically (drawString also doesn't support '\n').
In the docs as well as in this other answer I found this:
Graphics2D g = ...;
Point2D loc = ...;
Font font = Font.getFont("Helvetica-bold-italic");
FontRenderContext frc = g.getFontRenderContext();
TextLayout layout = new TextLayout("This is a string", font, frc);
layout.draw(g, (float)loc.getX(), (float)loc.getY());
Rectangle2D bounds = layout.getBounds();
bounds.setRect(bounds.getX()+loc.getX(),
bounds.getY()+loc.getY(),
bounds.getWidth(),
bounds.getHeight());
g.draw(bounds);
Which does draw the string and the bounds, but they have no effect, so no luck here.
Any class I could use?
Any class I could use?
Another option is to use a LineBreakMeasurer:
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.text.*;
import java.util.Objects;
import javax.swing.*;
import javax.swing.border.Border;
public final class LineBreakMeasurerTest {
private static final String TEXT = "1234567890 ABCDEFG HIJKLMN OPQRSTU VWXYZ";
private final JLabel lbl1 = new JLabel(TEXT);
private final JTextArea lbl2 = new JTextArea(TEXT);
private final JLabel lbl3 = new WrappingLabel(TEXT);
public JComponent makeUI() {
Border b = BorderFactory.createLineBorder(Color.GREEN, 5);
lbl1.setBorder(
BorderFactory.createTitledBorder(b, "JLabel"));
lbl2.setBorder(
BorderFactory.createTitledBorder(b, "JTextArea"));
lbl3.setBorder(
BorderFactory.createTitledBorder(b, "LineBreakMeasurer"));
lbl2.setFont(lbl1.getFont());
lbl2.setEditable(false);
lbl2.setLineWrap(true);
lbl2.setWrapStyleWord(true);
lbl2.setBackground(lbl1.getBackground());
JPanel p = new JPanel(new GridLayout(3, 1));
p.add(lbl1);
p.add(lbl2);
p.add(lbl3);
return p;
}
public static void main(String... args) {
EventQueue.invokeLater(() -> {
UIManager.put("swing.boldMetal", Boolean.FALSE);
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new LineBreakMeasurerTest().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
class WrappingLabel extends JLabel {
//TEST: private AffineTransform at = AffineTransform.getScaleInstance(.8, 1d);
protected WrappingLabel(String text) {
super(text);
}
#Override protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(getForeground());
Insets i = getInsets();
float x = i.left;
float y = i.top;
int w = getWidth() - i.left - i.right;
AttributedString as = new AttributedString(getText());
//TEST: as.addAttribute(TextAttribute.FONT, g2.getFont());
//TEST: as.addAttribute(TextAttribute.TRANSFORM, at);
AttributedCharacterIterator aci = as.getIterator();
FontRenderContext frc = g2.getFontRenderContext();
LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc);
while (lbm.getPosition() < aci.getEndIndex()) {
TextLayout tl = lbm.nextLayout(w);
tl.draw(g2, x, y + tl.getAscent());
y += tl.getDescent() + tl.getLeading() + tl.getAscent();
}
g2.dispose();
}
}
Simplest solution: use a JTextArea.
You can rig it up so that it doesn't even look like a JTextArea by setting background to null, by making it nonfocusable, and it will automatically wrap words if you call setLineWrap(true) and setWrapStyleWord(true) on it. To have it fill the JPanel, give the panel a BorderLayout, and add the JTextArea BorderLayout.CENTER. You can even set a margin if desired.

Add an object from another class to a JPanel

Ok i have a JPanel such as this one :
public class GUI {
JFrame frame = new JFrame("Net");
JPanel panel = new JPanel();
public GUI()
{
frame.setSize(835,650);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
frame.add(panel);
panel.setSize(600,600);
panel.setLocation(215,5);}
There are some other panels in there tables etc. My main is this one :
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
//new GUI();
new GUI().buildTable();
}
});
And there i another class this one :
public class DrawPlanes extends GUI
{
private static int centreX, centreY, radius;
private Color colour;
public DrawPlanes()
{
centreX = 300;
centreY = 300;
radius = 200;
colour = Color.BLACK;
}
public DrawPlanes(int centreX,int centreY, int radius, Color colour)
{
this.centreX = centreX;
this.centreY = centreY;
this.radius = radius;
this.colour = colour;
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
System.out.println("ppp");
Graphics2D g2D = (Graphics2D) g;
g2D.setStroke(new BasicStroke(2F));
g.setColor(Color.BLACK);
g.drawOval(centreX - radius , centreY - radius, radius * 2 , radius * 2);
......
}
}
Now i cant add this class to my panel i tried creating an object in main and then adding the object to my panel. I ve also tried
panel.add(new DrawPlanes(int x, int y, int radius,Color colour));
but it didnt get the drawing added in the panel.Any suggestions?
DrawPanel is not a component, it extends GUI which is not a component either.
container.add(component) function expects a Component, in Swing essentially JComponent and it's extending component: JPanel, JLabel, JButton etc.
extends DrawPanel to a JComponent or JPanel. However they both are basically some other than the fact that JComponent is non-opaque while JPanel is opaque.

Categories