I cannot get the code linked below to do exactly what I want it to do.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Gui {
static JFrame frame;
static JLabel label;
public static void main (String[] args) {
Gui gui = new Gui();
gui.go();
}
public void go () {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,300);
frame.setVisible(true);
MyDrawPanel panel = new MyDrawPanel();
frame.getContentPane().add(BorderLayout.CENTER, panel);
label = new JLabel("I'm a label");
frame.getContentPane().add(BorderLayout.WEST, label);
JButton colorButton = new JButton("Change Colors");
ColorButtonListener colorButtonListener = new ColorButtonListener();
colorButton.addActionListener(colorButtonListener);
frame.getContentPane().add(BorderLayout.SOUTH, colorButton);
JButton labelButton = new JButton("Change Label");
LabelButtonListener labelButtonListener = new LabelButtonListener();
labelButton.addActionListener(labelButtonListener);
frame.getContentPane().add(BorderLayout.EAST, labelButton);
}
}
class ColorButtonListener implements ActionListener {
JFrame frame = Gui.frame;
public void actionPerformed (ActionEvent event) {
frame.repaint();
}
}
class LabelButtonListener implements ActionListener {
JLabel label = Gui.label;
public void actionPerformed (ActionEvent event) {
if (label.getText() == "That hurt") {
label.setText("I'm a label");
} else {
label.setText("That hurt");
}
}
}
class MyDrawPanel extends JPanel {
public void paintComponent (Graphics g) {
Graphics2D g2d = (Graphics2D) g;
int red = (int) (Math.random() * 256);
int green = (int) (Math.random() * 256);
int blue = (int) (Math.random() * 256);
Color startColor = new Color(red, green, blue);
red = (int) (Math.random() * 256);
green = (int) (Math.random() * 256);
blue = (int) (Math.random() * 256);
Color endColor = new Color(red, green, blue);
GradientPaint gradient = new GradientPaint(70, 70, startColor, 150, 150, endColor);
g2d.setPaint(gradient);
g2d.fillOval(0, 0, this.getWidth(), this.getHeight());
}
}
There is a panel class used to draw a circle and then the panel is positioned in the center region of the frame.
A label is positioned in the west region of the frame, two buttons colorButton(positioned south) and labelButton(positioned east) should control the circle and the label respectively. 2 classes ColorButtonListener and LabelButtonListener implement the ActionListener interface and are registered with the colorButton and labelButton respectively. The color button when clicked should paint a circle with random colors and the label button when clicked should toggle between the text "I'm a label" and "That hurt".
Now, the issue I am having is with the label button. When clicking it, it not only changes the text(as expected), but also redraws the circle. This button should not be redrawing the circle. The color button works as expected.
The problem is you don't control when a repaint might occur. Instead of changing the color every time paintComponent is called, which you can't control, change the color only when you want to and reference from within the paintComponent method, for example
class MyDrawPanel extends JPanel {
private Color startColor;
private Color endColor;
// And setters or some other way
// to randomise the colors
public void paintComponent (Graphics g) {
Graphics2D g2d = (Graphics2D) g;
GradientPaint gradient = new GradientPaint(70, 70, startColor, 150, 150, endColor);
g2d.setPaint(gradient);
g2d.fillOval(0, 0, this.getWidth(), this.getHeight());
}
}
Check out Painting in AWT and Swing for more details
This is because setText() methods internally calls repaint() if new text is not same as old text. So results in color change whenever you click that button too.
Related
I have to draw a JLabel with an onclick event on an drawn circle. The newly created JLabel should be placed placed very closed a line which is already created. I was trying to draw this JLabel at the middle position of the line. But problem is, even after setting fixed calculated coordinates(x,y), the JLabel is not drawn in the given location.(unlike g.drawLine() or g.drawOval()). My code is given below: need help to fix it.
public class ButtonExample extends JFrame{
JFrame frame;
JLabel label1, label2, label3;
private Shape myShape;
private int arrowAdded = 0;
public ButtonExample() {
super("Location test of JLabel and Graphics objects");
label1 = new JLabel("0,0");
//label2 = new JLabel("40,40");
label1.setBounds(0, 0, 50, 50);
label1.setBorder(BorderFactory.createLineBorder(Color.black));
//label2.setBounds(100, 100, 50, 50);
//label2.setBorder(BorderFactory.createLineBorder(Color.black));
add(label1);
//add(label2);
repaint();
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent me) {
super.mouseClicked(me);
if (myShape.contains(me.getPoint())) {
arrowAdded = 1;
repaint();
}
}
});
setLayout(null);
setSize(1000,600);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(1000, 600);
}
public void paint(Graphics g){
super.paint(g);
int startX = 100;
int startY = 100;
int endX = 180;
int endY = 120;
g.setColor(new Color(0, 255, 0));
myShape = new Ellipse2D.Double(startX, startY, 30, 30);
Graphics2D g2d = (Graphics2D) g;
g2d.draw(myShape);
g.drawLine(startX, startY, endX, endY);
int lX = (int)Math.abs(endX-startX)/2;
int lY = (int)Math.abs(endY-startY)/2;
if(endX>startX) {
lX = lX+startX;
}else {
lX = lX+endX;
}
if(endY>startY) {
lY = lY+startY;
}else {
lY = lY+endY;
}
if(arrowAdded == 1) {
label3 = new JLabel();
label3.setBounds(lX, lY, 20, 15);
label3.setBorder(BorderFactory.createLineBorder(Color.black));
add(label3);
g.drawRect(lX, lY, 20, 15);
}enter code here
}
public static void main(String[] args) {
new ButtonExample();
}
}
Don't override paint() on a JFrame!
The frame includes the title bar and borders, so you can't just paint at (0, 0). You would need your painting to be offset by the frame decorations.
Instead, custom painting should be done by overriding the paintComponent(...) method of a JPanel and then you add the panel to the frame. Now the offsets will be relative to the panel, so you can use (0, 0). Of course you would also add the label to the panel at your desired location.
Read the section from the Swing tutorial on Custom Painting for more information and working examples.
Change your code
int lX = (int)Math.abs(endX-startX) / 2;
int lY = (int)Math.abs(endY-startY) / 2;
to
int lX = (endX-startX) / 2;
int lY = (endY-startY) / 2;
and your rectangle (left upper corner) will be placed in the middle position of the line (you can still set an offset if it´s too close :-) )
I have a drawing panel with some color buttons. I can draw with different colors in the drawing panel. There is also a save button. I want to capture the image drawn on the panel and save the captured image inside a directory in my pc, when I will click the save button. I don't know much about java. How can I do this?
This is my code:
package paint;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class paint{
public static void main(String[] args){
Icon iconB = new ImageIcon("blue.gif");
Icon iconM = new ImageIcon("magenta.gif");
Icon iconR = new ImageIcon("red.gif");
Icon iconBl = new ImageIcon("black.gif");
Icon iconG = new ImageIcon("green.gif");
JFrame frame = new JFrame("Paint It");
//Creates a frame with a title of "Paint it"
Container content = frame.getContentPane();
//Creates a new container
content.setLayout(new BorderLayout());
//sets the layout
final PadDraw drawPad = new PadDraw();
//creates a new padDraw, which is pretty much the paint program
content.add(drawPad, BorderLayout.CENTER);
//sets the padDraw in the center
JPanel panel = new JPanel();
//creates a JPanel
panel.setPreferredSize(new Dimension(32, 68));
panel.setMinimumSize(new Dimension(32, 68));
panel.setMaximumSize(new Dimension(32, 68));
//This sets the size of the panel
JButton clearButton = new JButton("Clear");
//creates the clear button and sets the text as "Clear"
clearButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
drawPad.clear();
}
});
//this is the clear button, which clears the screen. This pretty
//much attaches an action listener to the button and when the
//button is pressed it calls the clear() method
JButton saveButton = new JButton("save");
JButton redButton = new JButton(iconR);
//creates the red button and sets the icon we created for red
redButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
drawPad.red();
}
});
//when pressed it will call the red() method. So on and so on =]
JButton blackButton = new JButton(iconBl);
//same thing except this is the black button
blackButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
drawPad.black();
}
});
JButton magentaButton = new JButton(iconM);
//magenta button
magentaButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
drawPad.magenta();
}
});
JButton blueButton = new JButton(iconB);
//blue button
blueButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
drawPad.blue();
}
});
JButton greenButton = new JButton(iconG);
//green button
greenButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
drawPad.green();
}
});
blackButton.setPreferredSize(new Dimension(16, 16));
magentaButton.setPreferredSize(new Dimension(16, 16));
redButton.setPreferredSize(new Dimension(16, 16));
blueButton.setPreferredSize(new Dimension(16, 16));
greenButton.setPreferredSize(new Dimension(16,16));
//sets the sizes of the buttons
panel.add(greenButton);
panel.add(blueButton);
panel.add(magentaButton);
panel.add(blackButton);
panel.add(redButton);
panel.add(clearButton);
panel.add(saveButton);
//adds the buttons to the panel
content.add(panel, BorderLayout.SOUTH);
//sets the panel to the left
frame.setSize(300, 300);
//sets the size of the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//makes it so you can close
frame.setVisible(true);
//makes it so you can see it
}
}
class PadDraw extends JComponent{
Image image;
//this is gonna be your image that you draw on
Graphics2D graphics2D;
//this is what we'll be using to draw on
int currentX, currentY, oldX, oldY;
//these are gonna hold our mouse coordinates
//Now for the constructors
public PadDraw(){
setDoubleBuffered(false);
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
oldX = e.getX();
oldY = e.getY();
}
});
//if the mouse is pressed it sets the oldX & oldY
//coordinates as the mouses x & y coordinates
addMouseMotionListener(new MouseMotionAdapter(){
public void mouseDragged(MouseEvent e){
currentX = e.getX();
currentY = e.getY();
if(graphics2D != null)
graphics2D.drawLine(oldX, oldY, currentX, currentY);
repaint();
oldX = currentX;
oldY = currentY;
}
});
//while the mouse is dragged it sets currentX & currentY as the mouses x and y
//then it draws a line at the coordinates
//it repaints it and sets oldX and oldY as currentX and currentY
}
public void paintComponent(Graphics g){
if(image == null){
image = createImage(getSize().width, getSize().height);
graphics2D = (Graphics2D)image.getGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
clear();
}
g.drawImage(image, 0, 0, null);
}
//this is the painting bit
//if it has nothing on it then
//it creates an image the size of the window
//sets the value of Graphics as the image
//sets the rendering
//runs the clear() method
//then it draws the image
public void clear(){
graphics2D.setPaint(Color.white);
graphics2D.fillRect(0, 0, getSize().width, getSize().height);
graphics2D.setPaint(Color.black);
repaint();
}
//this is the clear
//it sets the colors as white
//then it fills the window with white
//thin it sets the color back to black
public void red(){
graphics2D.setPaint(Color.red);
repaint();
}
//this is the red paint
public void black(){
graphics2D.setPaint(Color.black);
repaint();
}
//black paint
public void magenta(){
graphics2D.setPaint(Color.magenta);
repaint();
}
//magenta paint
public void blue(){
graphics2D.setPaint(Color.blue);
repaint();
}
//blue paint
public void green(){
graphics2D.setPaint(Color.green);
repaint();
}
//green paint
}
I have written save() method copy it to PadDraw class and call save() when ever you need to save the image.
public void save(){
try {
BufferedImage bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
// Draw the image on to the buffered image
Graphics2D bGr = bimage.createGraphics();
bGr.drawImage(image, 0, 0, null);
javax.imageio.ImageIO.write(bimage , "PNG", new File("test.png"));
bGr.dispose();
} catch (Exception ex) {
Logger.getLogger(PadDraw.class.getName()).log(Level.SEVERE, null, ex);
}
}
The basics for creating an image of any Swing component is use:
BufferedImage image = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = image.createGraphics();
component.print( g2d );
g2d.dispose();
Then you can save the "image" using ImageIO.
Or you can use the Screen Image which has extra functionality to:
handle transparent components
create an image of an area of the component
create an image of a component not displayed on a visible window
write to image to a file
I am making a game called Mastermind. To create the game board, I am using paintComponent to paint onto a frame that was passed as a parameter from a different class. Why doesn't it print anything besides the back button?
public class mastermindColor extends JPanel //running color game
{
Rectangle rect = new Rectangle(100, 100, 150, 75);
private JButton backButton = new JButton();
JFrame f = new JFrame();
public mastermindColor(final JFrame frame) //creating color game frame
{
String back = BorderLayout.CENTER;
backButton.setText("back");
frame.add(backButton, BorderLayout.NORTH);
frame.add(this, BorderLayout.CENTER);
backButton.setVisible(true);
backButton.addActionListener(new ActionListener() //if back button is selected
{
public void actionPerformed(ActionEvent e)
{
frame.getContentPane().removeAll();
mastermindRunner run = new mastermindRunner();
}
});
frame.setVisible(true);
}
public void paintComponent(Graphics g) //printing the game set up
{
super.paintComponents(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.draw(rect);
}
I am making a GUI with Swing and would like to configure the Graphics2D objects with relative positioning. I want to do this in a way that when I resize the window the objects are repainted in a new location relative to the initial anchor position (probably in the top left corner somewhere). I have tried using layout managers to do this but it doesn't impact the actual drawing because the points are pretty much hard coded.
What is the best way to do this? Can anyone provide an good example? Thanks.
Here is my self contained example:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class DrawPanelMain extends JPanel {
public static final double version = 0.0;
private JPanel btnPanel = new JPanel();
private JPanel switchPanel = new JPanel();
private JScrollPane switchPanelScrollPane = new JScrollPane(switchPanel);
//private JPanel[] panelArray = new JPanel[3];
DrawEllipses drawEllipses = new DrawEllipses(POINT_LIST);
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
initializePointList();
createAndShowGui();
}
});
}
public static java.util.List<Point> POINT_LIST = new ArrayList<>();
/*
* This loop will initialize POINT_LIST with the set of points for drawing the ellipses.
* The for each loop initializes points for the top row and the second for loop draws the
* right triangle.
*/
private static void initializePointList() {
int ellipsePointsYCoordinate[] = {140, 200, 260, 320, 380, 440, 500, 560, 620};
int ellipsePointsXCoordinate[] = {140, 200, 260, 320, 380, 440, 500, 560, 620, 680};
int xx = 80;
for (int aXt : ellipsePointsXCoordinate) {
POINT_LIST.add(new Point(aXt, xx));
}
for (int i = 0; i < ellipsePointsYCoordinate.length; i++) {
for (int j = i; j < ellipsePointsYCoordinate.length; j++) {
POINT_LIST.add(new Point(ellipsePointsXCoordinate[i], ellipsePointsYCoordinate[j]));
}
}
}
public DrawPanelMain() {
switchPanel.setBorder(BorderFactory.createLoweredSoftBevelBorder());
switchPanel.setBackground(Color.DARK_GRAY);
switchPanel.add(drawEllipses);
switchPanelScrollPane.setPreferredSize(new Dimension(600,600));
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
// first column
c.gridx = 0;
add(switchPanelScrollPane, c);
// second column
c.gridx = 1;
// first row
c.gridy = 0;
// second row
c.gridy = 1;
c.gridx = 0;
add(btnPanel, c);
btnPanel.add(new JButton(new AddSwitchAction("Add Switch Panel")));
}
public static void createAndShowGui() {
JFrame frame = new JFrame("RF Connection Panel " + version);
frame.setLayout(new BorderLayout());
frame.add(new DrawPanelMain());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(false);
//frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
/*
* AddSwitchAction will add a new pane to the tabbedPane when the add switch button is clicked
*/
private class AddSwitchAction extends AbstractAction {
public AddSwitchAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
String title = "Switch ";
DrawEllipses tabComponent = new DrawEllipses(POINT_LIST);
switchPanel.add(title, tabComponent);
}
}
}
#SuppressWarnings("serial")
class DrawEllipses extends JPanel {
private final int PREF_W = 750; //Window width
private final int PREF_H = 750; //Window height
private final int OVAL_WIDTH = 30;
private static final Color INACTIVE_COLOR = Color.RED;
private static final Color ACTIVE_COLOR = Color.green;
private java.util.List<Point> points;
private java.util.List<Ellipse2D> ellipses = new ArrayList<>();
private Map<Ellipse2D, Color> ellipseColorMap = new HashMap<>();
/*
* This method is used to populate "ellipses" with the initialized ellipse2D dimensions
*/
public DrawEllipses(java.util.List<Point> points) {
this.points = points;
for (Point p : points) {
int x = p.x - OVAL_WIDTH / 2;
int y = p.y - OVAL_WIDTH / 2;
int w = OVAL_WIDTH;
int h = OVAL_WIDTH;
Ellipse2D ellipse = new Ellipse2D.Double(x, y, w, h);
ellipses.add(ellipse);
ellipseColorMap.put(ellipse, INACTIVE_COLOR);
}
MyMouseAdapter mListener = new MyMouseAdapter();
addMouseListener(mListener);
addMouseMotionListener(mListener);
}
/*
* paintComponent is used to paint the ellipses
*/
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); // paints the background
setBackground(Color.DARK_GRAY);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (Ellipse2D ellipse : ellipses) {
g2.setColor(ellipseColorMap.get(ellipse));
g2.fill(ellipse);
g2.setColor(Color.BLACK);
g2.setStroke(new BasicStroke(2));
g2.draw(ellipse);
}
/*
* Set the font characteristics, color, and draw the row labels.
*/
g.setFont(new Font("TimesRoman", Font.BOLD, 18));
g.setColor(Color.BLACK);
//Along the top row
g.drawString("External Port", 10, 50);
g.drawString("1", 135, 50);
g.drawString("2", 195, 50);
g.drawString("3", 255, 50);
g.drawString("4", 315, 50);
g.drawString("5", 375, 50);
g.drawString("6", 435, 50);
g.drawString("7", 495, 50);
g.drawString("8", 555, 50);
g.drawString("9", 615, 50);
g.drawString("10", 672, 50);
//Along the Y-axis
g.drawString("Radio 2", 40, 145);
g.drawString("3", 90, 205);
g.drawString("4", 90, 265);
g.drawString("5", 90, 325);
g.drawString("6", 90, 385);
g.drawString("7", 90, 445);
g.drawString("8", 90, 505);
g.drawString("9", 90, 565);
g.drawString("10", 90, 625);
//Along the X-Axis
g.drawString("1", 135, 670);
g.drawString("2", 195, 670);
g.drawString("3", 255, 670);
g.drawString("4", 315, 670);
g.drawString("5", 375, 670);
g.drawString("6", 435, 670);
g.drawString("7", 495, 670);
g.drawString("8", 555, 670);
g.drawString("9", 615, 670);
//Draws a 3DRect around the top row of ellipse2D objects
g2.setColor(Color.lightGray);
g2.draw3DRect(120, 60, 580, 40, true);
g2.draw3DRect(121, 61, 578, 38, true);
g2.draw3DRect(122, 62, 576, 36, true);
}
/*
* MouseAdapter is extended for mousePressed Event that detects if the x, y coordinates
* of a drawn ellipse are clicked. If the color is INACTIVE it is changed to ACTIVE and
* vice versa.
*/
private class MyMouseAdapter extends MouseAdapter {
#Override
/*
* When mousePressed event occurs, the color is toggled between ACTIVE and INACTIVE
*/
public void mousePressed(MouseEvent e) {
Color c;
for (Ellipse2D ellipse : ellipses) {
if (ellipse.contains(e.getPoint())) {
c = (ellipseColorMap.get(ellipse) == INACTIVE_COLOR) ? ACTIVE_COLOR : INACTIVE_COLOR;
ellipseColorMap.put(ellipse, c);
}
}
repaint();
}
}
/*
* This method will set the dimensions of the JFrame equal to the preferred H x W
*/
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
/*
* Used for button click action to change all ellipses to ACTIVE_COLOR
*/
public void activateAll(){
for (Ellipse2D ellipse : ellipses){
ellipseColorMap.put(ellipse, ACTIVE_COLOR);
}
repaint();
}
/*
* Used for button click action to change all ellipses to INACTIVE_COLOR
*/
public void deactivateAll(){
for (Ellipse2D ellipse : ellipses){
ellipseColorMap.put(ellipse, INACTIVE_COLOR);
}
repaint();
}
}
As I suggested earlier if you want relative positioning then you need to calculate the relative location every time your paint (or when the component is resized).
Basically you know that widthwise you have 10 circle you want to paint at 30 pixels each and a label at a fixed width of say 100. So that means you have a minimum width of 400 pixels.
Of course that is not reasonable as you want a gap between each circle, so you need to decide what your preferred gap is and multiply that by 9 to determine your true minimum size. Looks like you have about a 30 pixel gap so that is another 270 pixels giving a preferred size of 670 pixels.
So the question is what do you do when the width is greater than 670? Do you increase the gap or leave it at 30?
The harder case is when the width is less than 670, as you will now need to adjust the gap smaller, down to some minimum value.
Once you determine the horizontal gap to use, you go through the same analysis for the vertical gap.
Now when you do your painting you have your starting location and every row you paint will be increased by your vertical gap. And every circle on the row will be increased by the horizontal gap.
I have never tried it but I believe you can use the setFrame(...) method of your Ellipse to dynamically move its location. So when you do your painting the Ellipse will no be in the correct spot and it should respond to mouse events correctly.
So basically you are writing your own custom layout manager for Graphics.
The second approach, instead of doing custom painting, is to use real components.
You can easily create a custom Icon to represent the circles. Then maybe you can use a JToggleButton. Then your logic of changing color can be handled by the toggle button and two different colored Icons.
Now the hard part. I have never tried it before, but I believe you can use the Spring Layout.
SpringLayout positions components relative to one another. It also contains "springs" between the components to allow the gap to grow/shrink.
Those are the two approaches as I see it.
Well the title is quite self explanatory. I want to build two panels one on-top of each other in layers using java. I want the top layer to contain a JPanel which will contain a graphics2d object. I'd like both the JPanel and graphics2d to have transparent background (I still want the content drawn by the graphics2d visible). Does anyone have an idea how it can be done?
Call setOpaque(false) on the JPanel - that will not paint the JPanel's background.
Depending on what method you're overriding to get at the Graphics2D (JPanel's don't contain a Graphics2D object like a component - a Graphics2D object is used to paint the JPanel) - if it's paintComponent() you should read the JavaDocs for JComponent - and call super.paintComponent(g) first so that opacity is honored - and then do the rest of your painting.
Working example:
package com.stackoverflow.opaque;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class OpaqueExample extends JFrame {
private JLayeredPane layers;
private JPanel up, down;
private JButton toggleOpaque;
public OpaqueExample() {
layers = new JLayeredPane();
down = new JPanel();
down.setBackground(Color.GREEN);
down.setBounds(100, 100, 200, 200);
layers.add(down, new Integer(1));
up = new JPanel() {
public void paintComponent(Graphics og) {
super.paintComponent(og);
Graphics2D g = (Graphics2D)og;
GradientPaint gradient = new GradientPaint(0, 0, Color.BLUE, 10, 0,
Color.WHITE, true );
Polygon poly = new Polygon();
poly.addPoint(10, 10);
poly.addPoint(100, 50);
poly.addPoint(190, 10);
poly.addPoint(150, 100);
poly.addPoint(190, 190);
poly.addPoint(100, 150);
poly.addPoint(10, 190);
poly.addPoint(50, 100);
poly.addPoint(10, 10);
g.setPaint(gradient);
g.fill(poly);
g.setPaint(Color.BLACK);
g.draw(poly);
}
};
up.setBackground(Color.RED);
up.setBounds(150, 150, 200, 200);
layers.add(up, new Integer(2));
getContentPane().add(layers, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
toggleOpaque = new JButton("Toggle Opaque");
toggleOpaque.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
up.setOpaque(!up.isOpaque());
layers.repaint();
}
});
buttonPanel.add(toggleOpaque);
getContentPane().add(buttonPanel, BorderLayout.EAST);
}
public static void main(String[] args) {
JFrame f = new OpaqueExample();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(500, 500);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}