How to Load an Image object in Java - java

I am getting input==null while trying to load an Image. I can't seem to figure out why, even after browsing a good number of StackOverflow questions. It looks right to me.
Here is the code:
private BufferedImage image;
public practice(){
setLayout(new BorderLayout());
timeBall.start();
JPanel panelNorth = makePanel();
panelNorth.setBackground(Color.CYAN);
add(panelNorth, BorderLayout.NORTH);
try{
image = ImageIO.read(practice.class.getResource("/pics/flying.png"));
}catch(IOException e){
e.printStackTrace();
}
}
public Dimension getPreferredSize() {
return image == null ? new Dimension(400, 300): new Dimension(image.getWidth(), image.getHeight());
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLUE);
ellipse = new Ellipse2D.Double(Ox, Oy+Speedy, height, height);
Graphics2D graphics = (Graphics2D)g;
g.drawImage(image, 0, 0, this);
graphics.fill(ellipse);
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
Oy = Oy + Speedy / 10;
Ox = Ox + Speedx / 10;
}

Related

JScrollPane blank until you scroll.

I have a JScrollPane implemented like so in the frame:
public ImagePanel imgPane = new ImagePanel();
JScrollPane scrollPane = new JScrollPane(imgPane);
ImagePanel is an extension of JPanel:
public class ImagePanel extends JPanel {
private BufferedImage img;
public ImagePanel(BufferedImage img) {
this.img = img;
}
public ImagePanel() {
}
#Override
public Dimension getPreferredSize() {
return img == null ? super.getPreferredSize() : new Dimension(img.getWidth(), img.getHeight());
}
protected Point getImageLocation() {
Point p = null;
if (img != null) {
int x = (getWidth() - img.getWidth()) / 2;
int y = (getHeight() - img.getHeight()) / 2;
p = new Point(x, y);
}
return p;
}
public void setImage(BufferedImage bi) {
img = bi;
}
public Point toImageContext(Point p) {
Point imgLocation = getImageLocation();
Point relative = new Point(p);
relative.x -= imgLocation.x;
relative.y -= imgLocation.y;
return relative;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
Point p = getImageLocation();
g.drawImage(img, p.x, p.y, this);
}
}
The trouble I'm having is, when I load an image into the Pane:
frame.imgPane.setImage(img);
unless the previous image was the same size, the pane appears blank, no image, until you scroll. imgPane.repaint() has no effect on this. Is there a way to cause the JScrollPane to adjust to the new image without the user having to scroll?
Thanks
The setImage(...) method should also invoke:
img = bi;
revalidate(); // to invoke the layout manager
repaint(); // paint itself

How build personal JFrame from a PNG picture

I try to build my personal JFrame from a PNG picture. But there is different behavior between Mac OSX 10.8 and Windows 7. (I have to use JDK 6)
Here is my code :
[...]
public Fenetre()
{
this.setLocationRelativeTo(null);
this.setUndecorated(true);
this.setBackground(new Color(0,0,0,0));
try {
image = ImageIO.read(this.getClass().getResource("/Images/frame.png"));
} catch (IOException e) {
e.printStackTrace();
}
this.setSize(image.getWidth(),image.getHeight());
this.setLayout(null);
panel = new JPanel();
JButton quit = new JButton("Quitter");
panel.add(quit);
Dimension size = panel.getPreferredSize();
panel.setBounds(67, 45, size.width, size.height);
this.add(panel);
this.addMouseListener(this);
this.addMouseMotionListener(this);
this.setVisible(true);
}
public void paint(Graphics g) {
Graphics2D g2 =(Graphics2D) g;
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC)); // SRC_ATOP > Windows
g2.drawImage(image, 0, 0, this);
panel.update(panel.getGraphics());
}
[...]
The result on Mac OSX 10.8 (AlphaComposite = SRC) :
http://imageshack.us/photo/my-images/15/maczr.png/
Then, on Windows 7 (AlphaComposite = SRC_ATOP), at start up and when I move it, I can see :
http://imageshack.us/photo/my-images/16/windowsqu.jpg/
How do it ?
Your code is incomplete, but it seems to me like you are overriding the paint() method of a JFrame. You should never do this (unless you know what you doing and you invoke super.paint(..))!
If you want to display an image in the frame then either:
a) add a JLabel with an image to the frame
b) or do custom painting on a JPanel by overriding the paintComponent() method and then add the panel to the frame.
You are not honoring the paint chain
public void paint(Graphics g) {
// You must call super.paint somewhere here...
Graphics2D g2 =(Graphics2D) g;
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC)); // SRC_ATOP > Windows
g2.drawImage(image, 0, 0, this);
panel.update(panel.getGraphics());
}
You should NEVER call Component#update.
panel.update(panel.getGraphics());
This is called on you behalf by the repaint manager, which calls paint.
paint calls paintComponent, paintBorder and paintChildren failing to honor the paint chain means that not of these methods are been called and they are very important
As camickr has pointed out, you should never need to overrride the paint method of a top level container, like JFrame.
Instead, create a custom component that is capable of performing you painting for you and set it as the frames content pane...
this.setLocationRelativeTo(null);
this.setUndecorated(true);
this.setBackground(new Color(0,0,0,0));
setContentPane(new FancyPaintPane());
pack();
And the FancyPaintPane
public class FancyPaintPane extends JPanel {
private BufferedImage image;
public FancyPaintPane() {
try {
image = ImageIO.read(this.getClass().getResource("/Images/frame.png"));
} catch (IOException e) {
e.printStackTrace();
}
setOpaque(false);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(image.getWidth(), image.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
Graphics2D g2 = (Graphics2D) g.create();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC)); // SRC_ATOP > Windows
g2.drawImage(image, 0, 0, this);
g2.dispose();
}
}
You should also never modify a Graphics context without reverting it. These are shared resources across all components within the same top level container. A better approach is to create a copy which you can manipulate and dispose of when you're done...
You are also trying to show a component with transparent elements without first marking the component as transparent. This can produce nasty paint artifacts. You should call JComponent#setOpaque passing it a false value.
I would also strongly discourage you from using null layouts. They have a nasty habit of coming back and biting you.
Updated with simple example
public class CirclePaneTest {
public static void main(String[] args) {
new CirclePaneTest();
}
public CirclePaneTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
CirclePane circlePane = new CirclePane();
circlePane.setLayout(new BorderLayout());
circlePane.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
System.exit(0);
}
}
});
JLabel label = new JLabel("Look Ma, I'm a circle");
label.setHorizontalAlignment(JLabel.CENTER);
label.setVerticalAlignment(JLabel.CENTER);
JFrame frame = new JFrame("Test");
frame.setUndecorated(true);
frame.setBackground(new Color(0, 0, 0, 0));
frame.setContentPane(circlePane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(label);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class CirclePane extends JPanel {
public CirclePane() {
setOpaque(false);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected int getRadius() {
return Math.min(getWidth(), getHeight()) - 1;
}
#Override
public Insets getInsets() {
int radius = getRadius();
int xOffset = (getWidth() - radius) / 2;
int yOffset = (getHeight() - radius) / 2;
Insets insets = new Insets(
radius / 6,
radius / 6,
radius / 6,
radius / 6);
return insets;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int radius = getRadius();
int xOffset = (getWidth() - radius) / 2;
int yOffset = (getHeight() - radius) / 2;
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(getBackground());
g2d.fillOval(xOffset, yOffset, radius, radius);
g2d.setColor(Color.GRAY);
g2d.drawOval(xOffset, yOffset, radius, radius);
g2d.dispose();
}
}
}
Updated with code for Java 7
The following code should be used to set up the frame to be transparent under Java 6.
JFrame frame = new JFrame("Test");
frame.setAlwaysOnTop(true);
frame.setUndecorated(true);
try {
Class<?> awtUtilsClass = Class.forName("com.sun.awt.AWTUtilities");
if (awtUtilsClass != null) {
Method method = awtUtilsClass.getMethod("setWindowOpaque", Window.class, boolean.class);
method.invoke(null, frame, false);
}
} catch (Exception exp) {
}
//frame.setBackground(new Color(0, 0, 0, 0));
frame.setContentPane(circlePane);

Drawing a bounding rectangle to select what area to record

How do I draw that semi-transparent rectangle on the screen?
That cannot be a JFrame because JFrames have the usual close, minimize, maximize options in top right.
if it is indeed a swing competent, How is it drawn in thin air? Without inserting it in a JFrame whatsoever?
Please tell me what it is and how I can implement it...
The immediate idea that comes to mind is to use java.awt.Robot to capture a screen shot, paint that to frameless window. From there you can simply draw a rectangle on it
Updated with example
... Took some time ...
public class SelectionRectangle {
public static void main(String[] args) {
new SelectionRectangle();
}
public SelectionRectangle() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setUndecorated(true);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new BackgroundPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class BackgroundPane extends JPanel {
private BufferedImage background;
private Point mouseAnchor;
private Point dragPoint;
private SelectionPane selectionPane;
public BackgroundPane() {
selectionPane = new SelectionPane();
try {
Robot bot = new Robot();
background = bot.createScreenCapture(getScreenViewableBounds());
} catch (AWTException ex) {
Logger.getLogger(SelectionRectangle.class.getName()).log(Level.SEVERE, null, ex);
}
selectionPane = new SelectionPane();
setLayout(null);
add(selectionPane);
MouseAdapter adapter = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
mouseAnchor = e.getPoint();
dragPoint = null;
selectionPane.setLocation(mouseAnchor);
selectionPane.setSize(0, 0);
}
#Override
public void mouseDragged(MouseEvent e) {
dragPoint = e.getPoint();
int width = dragPoint.x - mouseAnchor.x;
int height = dragPoint.y - mouseAnchor.y;
int x = mouseAnchor.x;
int y = mouseAnchor.y;
if (width < 0) {
x = dragPoint.x;
width *= -1;
}
if (height < 0) {
y = dragPoint.y;
height *= -1;
}
selectionPane.setBounds(x, y, width, height);
selectionPane.revalidate();
repaint();
}
};
addMouseListener(adapter);
addMouseMotionListener(adapter);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(background, 0, 0, this);
g2d.dispose();
}
}
public class SelectionPane extends JPanel {
private JButton button;
private JLabel label;
public SelectionPane() {
button = new JButton("Close");
setOpaque(false);
label = new JLabel("Rectangle");
label.setOpaque(true);
label.setBorder(new EmptyBorder(4, 4, 4, 4));
label.setBackground(Color.GRAY);
label.setForeground(Color.WHITE);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
add(label, gbc);
gbc.gridy++;
add(button, gbc);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.getWindowAncestor(SelectionPane.this).dispose();
}
});
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
label.setText("Rectangle " + getX() + "x" + getY() + "x" + getWidth() + "x" + getHeight());
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(new Color(128, 128, 128, 64));
g2d.fillRect(0, 0, getWidth(), getHeight());
float dash1[] = {10.0f};
BasicStroke dashed =
new BasicStroke(3.0f,
BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER,
10.0f, dash1, 0.0f);
g2d.setColor(Color.BLACK);
g2d.setStroke(dashed);
g2d.drawRect(0, 0, getWidth() - 3, getHeight() - 3);
g2d.dispose();
}
}
public static Rectangle getScreenViewableBounds() {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
return getScreenViewableBounds(gd);
}
public static Rectangle getScreenViewableBounds(GraphicsDevice gd) {
Rectangle bounds = new Rectangle(0, 0, 0, 0);
if (gd != null) {
GraphicsConfiguration gc = gd.getDefaultConfiguration();
bounds = gc.getBounds();
Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc);
bounds.x += insets.left;
bounds.y += insets.top;
bounds.width -= (insets.left + insets.right);
bounds.height -= (insets.top + insets.bottom);
}
return bounds;
}
}
Update with SnipIt Example
Some people have suggested using a transparent window laid over the top of the screen, this actually won't work, as transparent windows don't actually respond to mouse clicks UNLESS they have something to be painted on them that will allow the mouse event to be trapped.
It's also been suggested that you use a Window as the selection mechanism, this is a valid answer, however, I would (personally) find that to be an unsuitable solution, as you want the user to simply click and drag the selection rectangle (IMHO).
Another approach is use something like SnipIt.
public class SnipIt {
public static void main(String[] args) {
new SnipIt();
}
public SnipIt() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setUndecorated(true);
// This works differently under Java 6
frame.setBackground(new Color(0, 0, 0, 0));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new SnipItPane());
frame.setBounds(getVirtualBounds());
frame.setVisible(true);
}
});
}
public class SnipItPane extends JPanel {
private Point mouseAnchor;
private Point dragPoint;
private SelectionPane selectionPane;
public SnipItPane() {
setOpaque(false);
setLayout(null);
selectionPane = new SelectionPane();
add(selectionPane);
MouseAdapter adapter = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
mouseAnchor = e.getPoint();
dragPoint = null;
selectionPane.setLocation(mouseAnchor);
selectionPane.setSize(0, 0);
}
#Override
public void mouseDragged(MouseEvent e) {
dragPoint = e.getPoint();
int width = dragPoint.x - mouseAnchor.x;
int height = dragPoint.y - mouseAnchor.y;
int x = mouseAnchor.x;
int y = mouseAnchor.y;
if (width < 0) {
x = dragPoint.x;
width *= -1;
}
if (height < 0) {
y = dragPoint.y;
height *= -1;
}
selectionPane.setBounds(x, y, width, height);
selectionPane.revalidate();
repaint();
}
};
addMouseListener(adapter);
addMouseMotionListener(adapter);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Rectangle bounds = new Rectangle(0, 0, getWidth(), getHeight());
Area area = new Area(bounds);
area.subtract(new Area(selectionPane.getBounds()));
g2d.setColor(new Color(192, 192, 192, 64));
g2d.fill(area);
}
}
public class SelectionPane extends JPanel {
private JButton button;
private JLabel label;
public SelectionPane() {
button = new JButton("Close");
setOpaque(false);
label = new JLabel("Rectangle");
label.setOpaque(true);
label.setBorder(new EmptyBorder(4, 4, 4, 4));
label.setBackground(Color.GRAY);
label.setForeground(Color.WHITE);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
add(label, gbc);
gbc.gridy++;
add(button, gbc);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.getWindowAncestor(SelectionPane.this).dispose();
}
});
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
label.setText("Rectangle " + getX() + "x" + getY() + "x" + getWidth() + "x" + getHeight());
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
// I've chosen NOT to fill this selection rectangle, so that
// it now appears as if you're "cutting" away the selection
// g2d.setColor(new Color(128, 128, 128, 64));
// g2d.fillRect(0, 0, getWidth(), getHeight());
float dash1[] = {10.0f};
BasicStroke dashed =
new BasicStroke(3.0f,
BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER,
10.0f, dash1, 0.0f);
g2d.setColor(Color.BLACK);
g2d.setStroke(dashed);
g2d.drawRect(0, 0, getWidth() - 3, getHeight() - 3);
g2d.dispose();
}
}
public static Rectangle getVirtualBounds() {
Rectangle bounds = new Rectangle(0, 0, 0, 0);
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice lstGDs[] = ge.getScreenDevices();
for (GraphicsDevice gd : lstGDs) {
bounds.add(gd.getDefaultConfiguration().getBounds());
}
return bounds;
}
}
Update Multi Monitor Support to the Example Answer from #MadProgrammer.
Without ExtendedState(JFrame.MAXIMIZED_BOTH) and pack()
public SelectionRectangle() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setUndecorated(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new BackgroundPane());
frame.setResizable( false );
frame.setBounds( getScreenViewableBounds() );
frame.setVisible(true);
}
});
}
public static Rectangle getScreenViewableBounds() {
GraphicsDevice[] devices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
int minx = Integer.MAX_VALUE;
int miny = Integer.MAX_VALUE;
int maxx = Integer.MIN_VALUE;
int maxy = Integer.MIN_VALUE;
for( GraphicsDevice device : devices ) {
for( GraphicsConfiguration config : device.getConfigurations() ) {
Rectangle bounds = config.getBounds();
minx = Math.min( minx, bounds.x );
miny = Math.min( miny, bounds.y );
maxx = Math.max( maxx, bounds.x + bounds.width );
maxy = Math.max( maxy, bounds.y + bounds.height );
}
}
return new Rectangle( new Point(minx, miny), new Dimension(maxx - minx, maxy - miny) );
}
You could use a transparent, undecorated frame in order to create a basic border.
public class ScreenRectangle extends JFrame {
public ScreenRectangle() {
this.setUndecorated(true);
this.setBackground(new Color(0, 0, 0, 0.25F));
// opacity ranges 0.0-1.0 and is the fourth paramater
this.add(new DrawPanel());
}
private class DrawPanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(0, 0, this.getWidth(), this.getHeight());
// any other drawing
}
}
}
The frame may also need to be setOpaque, or the panel size may need to be handled, but this is the general idea of it.

panel background image take screenshot

I'm trying to draw over an image (with the mouse) in a JPanel, this is working, but when I try to take an screenshot of the panel and generate an image of this, I only can see the image background without drawn with the mouse.
This is my code to generate the background Panel.java
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(this.createImage("/imagenes/cuerpoHumano.png").getImage(), 0, 0, null);
}
This is my code to draw as a pencil over the image: Panel.java
private void formMouseDragged(java.awt.event.MouseEvent evt) {
x = evt.getX();
y = evt.getY();
this.getGraphics().setColor(Color.RED);
this.getGraphics().fillOval(x, y, 4, 4);
}
This is the code to generate an screenshot
Dimension size = panel.getSize();
BufferedImage image = (BufferedImage) panel.createImage(size.width, size.height);
Graphics g = image.getGraphics();
panel.paint(g);
g.dispose();
try {
String fileName = UUID.randomUUID().toString().substring(0, 18);
ImageIO.write(image, "jpg", new File(path, fileName + ".jpg"));
} catch (IOException e) {
e.printStackTrace();
}
When you are taking the screenshot, the paintComponent() method is called. This means it will only paint you the image. You have to store the mouse move inside some model and paint the contents of the model in the paintComponent() method. This method is triggered by calling repaint() on the panel during the mouse move.
I think this is code that works .
public class PanelImagenCuerpoHumano extends JPanel {
private int x = -1;
private int y = -1;
private Image image = null;
private ArrayList<Point> puntos = new ArrayList<Point>();
public PanelImagenCuerpoHumano() {
image = new ImageIcon(getClass()
.getResource("/imagenes/cuerpoHumano.png")).getImage();
this.addMouseMotionListener(new MouseMotionListener() {
#Override
public void mouseDragged(MouseEvent e) {
x = e.getX();
y = e.getY();
puntos.add(new Point(x, y));
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
}
});
}
#Override
protected void paintComponent(Graphics g) {
g.drawImage(image, 0, 0, null);
for (Point p : puntos) {
g.setColor(Color.red);
g.fillOval(p.x, p.y, 3, 3);
}
}
}

Add a background image to JPanel with rounded corners

I've just recently extended JPanel for use in a project which we want to appear to be more "3D". That's my bosses' way of requiring shadowing and rounded corners on components. That's been accomplished as shown on many online examples. I did it like this:
public class RoundedPanel extends JPanel
{
protected int _strokeSize = 1;
protected Color _shadowColor = Color.BLACK;
protected boolean _shadowed = true;
protected boolean _highQuality = true;
protected Dimension _arcs = new Dimension(30, 30);
protected int _shadowGap = 5;
protected int _shadowOffset = 4;
protected int _shadowAlpha = 150;
protected Color _backgroundColor = Color.LIGHT_GRAY;
public RoundedPanel()
{
super();
setOpaque(false);
}
#Override
public void setBackground(Color c)
{
_backgroundColor = c;
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
int shadowGap = this._shadowGap;
Color shadowColorA = new Color(_shadowColor.getRed(), _shadowColor.getGreen(), _shadowColor.getBlue(), _shadowAlpha);
Graphics2D graphics = (Graphics2D) g;
if(_highQuality)
{
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
if(_shadowed)
{
graphics.setColor(shadowColorA);
graphics.fillRoundRect(_shadowOffset, _shadowOffset, width - _strokeSize - _shadowOffset,
height - _strokeSize - _shadowOffset, _arcs.width, _arcs.height);
}
else
{
_shadowGap = 1;
}
graphics.setColor(_backgroundColor);
graphics.fillRoundRect(0, 0, width - shadowGap, height - shadowGap, _arcs.width, _arcs.height);
graphics.setStroke(new BasicStroke(_strokeSize));
graphics.setColor(getForeground());
graphics.drawRoundRect(0, 0, width - shadowGap, height - shadowGap, _arcs.width, _arcs.height);
graphics.setStroke(new BasicStroke());
}
}
I am creating a test frame with the following code:
public class UITest
{
private static JFrame mainFrame;
private static ImagePanel mainPanel;
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
mainFrame = new JFrame();
mainFrame.setVisible(true);
try
{
mainPanel = new ImagePanel(ImageIO.read(this.getClass().getResource("/content/diamondPlate_Light.jpg")));
//mainPanel.setBounds(0, 0, 800, 600);
}
catch(IOException e)
{
}
mainPanel.setLayout(null);
RoundedPanel rPanel = new RoundedPanel();
rPanel.setBounds(10, 10, 200, 200);
rPanel.setBackground(new Color(168, 181, 224));
mainPanel.add(rPanel);
rPanel = new RoundedPanel();
rPanel.setBounds(220, 10, 560, 200);
rPanel.setBackground(new Color(168, 224, 168));
mainPanel.add(rPanel);
rPanel = new RoundedPanel();
rPanel.setBounds(10, 220, 770, 300);
rPanel.setBackground(new Color(224, 168, 168));
mainPanel.add(rPanel);
mainFrame.setSize(800, 600);
mainFrame.getContentPane().add(mainPanel);
}
});
}
}
And it results in this (sans the background image of the JFrame's contentPane:
What I would really like to do is generate the red, green, and blue panels with the rounded corners, but filled by a different image instead of the Color. I still want the properly rounded corners, but I'm unsure of how to do this.
If I've got a large texture, can I simply "clip" a piece of it out in the size and shape of the RoundedPanel? I need to evaluate this, since it just occurred to me as I typed, but if I can create a piece of geometry like what is used in graphics.fillRoundRect(...) and then clip the image, this could work.
Are there any other ways of doing this that I'm missing? I'd appreciate any feedback you might be able to offer. Thanks.
Edit:
Based upon the idea in the selected solution below, I've got the following results:
It needs to be whipped into shape for production and the background images are poorly chosen, but as a demo, the following RoundedPanel code gets us to the above results:
public class RoundedPanel extends JPanel
{
protected int strokeSize = 1;
protected Color _shadowColor = Color.BLACK;
protected boolean shadowed = true;
protected boolean _highQuality = true;
protected Dimension _arcs = new Dimension(30, 30);
protected int _shadowGap = 5;
protected int _shadowOffset = 4;
protected int _shadowAlpha = 150;
protected Color _backgroundColor = Color.LIGHT_GRAY;
protected BufferedImage image = null;
public RoundedPanel(BufferedImage img)
{
super();
setOpaque(false);
if(img != null)
{
image = img;
}
}
#Override
public void setBackground(Color c)
{
_backgroundColor = c;
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
int shadowGap = this._shadowGap;
Color shadowColorA = new Color(_shadowColor.getRed(), _shadowColor.getGreen(), _shadowColor.getBlue(), _shadowAlpha);
Graphics2D graphics = (Graphics2D) g;
if(_highQuality)
{
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
if(shadowed)
{
graphics.setColor(shadowColorA);
graphics.fillRoundRect(_shadowOffset, _shadowOffset, width - strokeSize - _shadowOffset,
height - strokeSize - _shadowOffset, _arcs.width, _arcs.height);
}
else
{
_shadowGap = 1;
}
RoundRectangle2D.Float rr = new RoundRectangle2D.Float(0, 0, (width - shadowGap), (height - shadowGap), _arcs.width, _arcs.height);
Shape clipShape = graphics.getClip();
if(image == null)
{
graphics.setColor(_backgroundColor);
graphics.fill(rr);
}
else
{
RoundRectangle2D.Float rr2 = new RoundRectangle2D.Float(0, 0, (width - strokeSize - shadowGap), (height - strokeSize - shadowGap), _arcs.width, _arcs.height);
graphics.setClip(rr2);
graphics.drawImage(this.image, 0, 0, null);
graphics.setClip(clipShape);
}
graphics.setColor(getForeground());
graphics.setStroke(new BasicStroke(strokeSize));
graphics.draw(rr);
graphics.setStroke(new BasicStroke());
}
}
Thanks for the help.
Try "clipping area" (see the g.setClip() call):
public static void main(String[] args) {
JFrame f = new JFrame();
f.setSize(new Dimension(600, 400));
f.getContentPane().setLayout(null);
RoundPanel rp = new RoundPanel();
rp.setBounds(100, 50, 400, 300);
f.getContentPane().add(rp);
f.setVisible(true);
}
static class RoundPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
// Prepare a red rectangle
BufferedImage bi = new BufferedImage(400, 300, BufferedImage.TYPE_INT_ARGB);
Graphics2D gb = bi.createGraphics();
gb.setPaint(Color.RED);
gb.fillRect(0, 0, 400, 300);
gb.dispose();
// Set a rounded clipping region:
RoundRectangle2D r = new RoundRectangle2D.Float(0, 0, 400, 300, 20, 20);
g.setClip(r);
// Draw the rectangle (and see whether it has round corners)
g.drawImage(bi, 0, 0, null);
}
}
Beware of the restrictions mentioned in the API doc for Graphics.setClip:
Sets the current clipping area to an arbitrary clip shape. Not all objects that implement the Shape interface can be used to set the clip. The only Shape objects that are guaranteed to be supported are Shape objects that are obtained via the getClip method and via Rectangle objects.

Categories

Resources