How could I make non-rectangular windows with soft borders in Java?
Soft borders (also known as soft clipping) are borders without aliasing artifacts.
I searched the web a lot and found several posts about translucent and/or
non-rectangular windows.
The topic "soft border" is confusing. It seems that the information I found deals
with applying soft borders to component which are inside another Java components.
But, can I, or can I not apply soft borders to custom shaped JWindow which is
placed just on the desktop?
I am primely referring to following post:
http://today.java.net/pub/a/today/2008/03/18/translucent-and-shaped-swing-windows.html
When it comes to soft clipping, the article forwards to
http://weblogs.java.net/blog/campbell/archive/2006/07/java_2d_tricker.html
But here, soft clipping on an existing Graphics2D object is described.
Here's my take on a soft-clipped, shaped, top-level window. Note: shaped windows use a proprietary API (com.sun.awt.AWTUtilities) and is not guaranteed to work on non-Sun JVMs. However, in JDK 7 it becomes part of the Window class.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class MySoftClippedWindow extends JPanel {
public MySoftClippedWindow() {
super();
setLayout(new GridBagLayout());
JButton button = new JButton(new AbstractAction("Close") {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
button.setOpaque(false);
add(button);
}
#Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
int width = getWidth();
int height = getHeight();
// Create a soft clipped image for the background
BufferedImage img = java_2d_tricker(g2d, width, height);
g2d.drawImage(img, 0, 0, null);
g2d.dispose();
}
public static void main(String[] args) {
JFrame.setDefaultLookAndFeelDecorated(true);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final JWindow w = new JWindow();
Container cp = w.getContentPane();
cp.setLayout(new BorderLayout());
cp.add(new MySoftClippedWindow());
w.setAlwaysOnTop(true);
com.sun.awt.AWTUtilities.setWindowOpaque (w, false);
w.setSize(200, 200);
w.setVisible(true);
}
});
}
/*
* This code is taken from
* http://weblogs.java.net/blog/campbell/archive/2006/07/java_2d_tricker.html
*/
private BufferedImage java_2d_tricker(Graphics2D g2d, int width, int height) {
GraphicsConfiguration gc = g2d.getDeviceConfiguration();
BufferedImage img = gc.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
Graphics2D g2 = img.createGraphics();
g2.setComposite(AlphaComposite.Clear);
g2.fillRect(0, 0, width, height);
g2.setComposite(AlphaComposite.Src);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.WHITE);
g2.fillOval(width / 4, height / 4, width / 2, height / 2);
g2.setComposite(AlphaComposite.SrcAtop);
g2.setPaint(new GradientPaint(0, 0, Color.RED, 0, height, Color.YELLOW));
g2.fillRect(0, 0, width, height);
g2.dispose();
return img;
}
}
Have you read this article:
http://www.pushing-pixels.org/?p=272
It mentions soft clipping and the previous articles you mentioned, but also includes some source code to implement a soft clipped window, the direct link is here:
http://www.pushing-pixels.org/wp-content/uploads/2008/03/softclippedwindow.java
That should provide you with a possible solution for what you want to do.
import java.awt.*;
public class First extends Applet
{
public void paint(Graphics g)
{
g.drawRect(100,50,500,800);
}
}
/*<Applet code="First.class"height=500 width=500>
</Applet>
*/
Related
can someone help me to know why the whole jtextfield is not visible when adding it to a jpanel that has a painted image icon? here is my code for the sample. thanks :)
without typing anything on it, only part of it is visible.
import java.awt.*;
import javax.swing.*;
public class GraphicsMain extends JFrame{
Panel panel = new Panel();
JTextField tf = new JTextField(10);
public GraphicsMain() {
tf.setBackground(Color.red);
panel.setLayout(new FlowLayout());
panel.add(tf);
this.add(panel);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
}
public static void main(String[] args) {
new GraphicsMain();
}
}
class Panel extends JPanel{
int pixel;
Image image;
public Panel() {
//#1 create icon
image = new ImageIcon("sample.png").getImage();
this.setPreferredSize(new Dimension(250,250));
}
//#2 paint
public void paint(Graphics g){
Graphics g2d = (Graphics2D)g;
g2d.drawImage(image, 0, 0, null);
}
}
You've broken the paint chain (responsibility).
Take a look at:
Performing Custom Painting
Painting in AWT and Swing
to get a better understand of how painting works and how you're suppose to use.
You "could" try and fix it by doing something like...
#Override
public void paint(Graphics g){
super.paint(g);
Graphics g2d = (Graphics2D)g;
g2d.drawImage(image, 0, 0, this);
}
but this is just painting the image over the top of what was previously paint.
You "could" try and fix it by doing something like...
#Override
public void paint(Graphics g){
Graphics g2d = (Graphics2D)g;
g2d.drawImage(image, 0, 0, this);
super.paint(g);
}
But now the image isn't getting painted (because part of the paint workflow is to fill the component with the background color of the component)
Instead, you need to inject your code into a different point in the paint process.
You should be using paintComponent, as it's primary responsibility is to "paint the component", this is called before the children are painted, so it's a great place for painting the background, for example...
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics g2d = (Graphics2D)g;
g2d.drawImage(image, 0, 0, this);
}
Helo guys,
my problem is that sometimes if my Rectangle2D gets a big width or height its bottom,left border splits and no longer makes a continous border and if I even make it wider the border goes smaller and smaller, like if there were a limitation of how long a rectangles border can be... It is really confusing and so far I have not found the solution :S I put there a link to a picture so you can see for yourself.
new Rectangle2D.Double(mojrectangle.getUpperleftPointmojRectangle().getX(), mojrectangle.getUpperleftPointmojRectangle().getY(),1000,1000)
repaint();
thanks for your help..
BTW I have the same problem with Arc2D if it gets really big
UPDATE: I removed from the function the setStroke command and now it draws it correctly, but in the future I will need to set the Rectangles stroke so it leaves me sad.
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2=(Graphics2D)g;
//g2.setStroke(stroke);
g2.draw(rectangle);
}
Here I put an example code of my project, please try it with g2.setStroke(selectedstroke)- it wont work, and without it...I hope I explained myself clear .
package com.awtgraphicsdemo;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.JComboBox;
public class AWTgraphicsdemo extends Frame {
final float dash[] = {10.0f};
final float solid[] = {1000.0f}; // these must be in an Array
float lineWidth[]={2.0f,4.0f,6.0f,8.0f,10.0f}; // width of the drawing line
String[] lineWidthString={"2.0","4.0","6.0","8.0","10.0"};
JComboBox strokecombobox=new JComboBox(lineWidthString);
BasicStroke selectedStroke = new BasicStroke(lineWidth[0],BasicStroke.CAP_BUTT,BasicStroke.JOIN_MITER, 10.0f, solid, 0.0f);
public AWTgraphicsdemo(){
super("Java AWT Examples");
prepareGUI();
}
public static void main(String[] args){
AWTgraphicsdemo awtGraphicsDemo = new AWTgraphicsdemo();
awtGraphicsDemo.setVisible(true);
}
private void prepareGUI(){
setSize(400,400);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowEvent){
System.exit(0);
}
});
}
#Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(selectedStroke);
g2.draw (new Rectangle2D.Double(10, 10, 1000, 900));
Font font = new Font("Serif", Font.PLAIN, 24);
g2.setFont(font);
g.drawString("Welcome to TutorialsPoint", 50, 70);
g2.drawString("Rectangle2D.Rectangle", 100, 120);
}
}
Helo again,
I figured out my problem, it was in the properties of stroke,so after some lenght of the compoment the stroke got activated which made changed to the drawn shape.By modifying the strokes solid array I was able the get the result I wanted.
Thank you for your help and suggestions :)
Take Care
Better to:
Not override paint(...) in top level windows (as MadProgrammer states) since this also changes painting of borders and child components -- a dangerous thing to do.
Instead override paintComponent(...) of a JPanel (again as MadProgrammer states) and place that JPanel into your top level window.
Don't set the Stroke of the Graphics object passed into your painting method, but rather a copy of the Graphics object so not to have side effects down the road.
e.g.,
public class MyPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
g2.setStroke(....);
// do drawing with g2 here
g2.dispose();
}
}
My question is a bit strange.
I want my created form (with JFrame) coloration should be like to this picture:
Should i use a special look and feel ?
Should i use a special look and feel ?
there is no such built-in Look&Feel available as much as i know. However for "Look&Feel", "Look" refers to the appearance of GUI widgets (more formally, JComponents) and "feel" refers to the way the widgets behave. If so, then we can always make our Swing component to be appeared as we want in the GUI.
Advanced responsive applications which are graphically rich ooze cool, sucking users in from the outset and hang onto them with a death grip of excitement. They make users tell their friends about the applications.
However, to develop graphically rich Swing application we must know how to render custom graphics on component, making them to appear as we want( with shiny color, beautiful texture, moving animation, nice typography). We need to learn how to layout the component properly to arrange them one relative to another. From answering your various question, i came to understand that you want to be a swing geek. Well:
First, Learn about the Swing JComponent(JPanel, JLabel, JButton, JList, JTable, JTextPane etc) and various type of Event listeners and how they responds with the component.
Second, Learn about the Layout Managers. There are other advanced level layout manager available which makes life easier but learn about the standard managers first.
Third, Learn about rendering custom graphics on swing components and swing painting mechanism. Then about the Font Concept.
Fourth, Learn about Graphics and Graphics2D class for rendering carious type of geometric object, image rendering, texturing, gradient painting etc.
Five, Learn about Concurrency in Swing. Swing is not thread safe, it maintain single threading rules. A good knowledge about threading is required, StackOverflow overflowed almost every day with the threading issues with Swing.
Six, collect the book Filthy Rich Clients and read it thoroughly when you will have nearly finished all of the above.
Now, A Demo Example for you:
I have tried to make the application as much short and simple as possible. But there are somethings i have done to achieve your requested GUI, which you should not do, if you don't know how they work, (for example overriding the paint() function). In this example i could not collect a texture as the image you have provided. But i have used a fabric texture. The application needs to load the texture image first. keep your eye on the console. It will show following message prior to run the application:
Please wait, Loading Texture :
http://www.brewsterwallcovering.com/data/default/images/catalog/original/289-5757.jpg
Loading finished. Starting the Demo!
I have used: GridBagLayout as the MainContainer's pane layout manager. Have a look at the code thoroughly and read about corresponding extension(extending JCompononent and JButton) and painting i have made to achieve a nicer GUI(Well not so much nicer to many critics, but for DEMO....)
Demo Source code:
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.logging.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.*;
/// creating the Button with custom look
class CButton extends JButton
{
BasicStroke basicStroke = new BasicStroke(2.0f);
public CButton(String txt) {
super(txt);
setForeground(Color.WHITE);
setFont(getFont().deriveFont(Font.BOLD, 13));
setContentAreaFilled(false);
setBorder(null);
setCursor(new Cursor(Cursor.HAND_CURSOR));
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(new Color(0xFFAA00));
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setStroke(basicStroke);
int archH = (getHeight()-4)/2;
g2d.drawRoundRect(3, 3, getWidth()-4, getHeight()-4, archH, archH);
if(getModel().isRollover())
{
g2d.fillRoundRect(3, 3, getWidth()-4, getHeight()-4, archH, archH);
setForeground(Color.black);
}
else
{
setForeground(Color.white);
}
g2d.dispose();
super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
}
}
/** creating the MainContainer panel with custom look **/
// custom painting to with paintComponent(Graphics g) and paint(Graphics g)
class MainContainer extends JPanel
{
public BufferedImage gradientImage = null;
public static BufferedImage textureImg; // made it static just for easyness
public static boolean loadingFinished = false;
public MainContainer() {
setBorder(new EmptyBorder(50, 50, 50, 50)); // setting the insets
// learn about GridBagLayout from the linked page about LayoutManager
setLayout(new GridBagLayout());
JLabel usrNameLabel = new JLabel("User Name");
changeCompFont(usrNameLabel);
JTextField usrNameFeild = new JTextField("user name");
changeCompFont(usrNameFeild);
// create compund border for text and password feild with left padding 5 px
Border compundBorder = BorderFactory.createCompoundBorder(
new LineBorder(Color.white, 2),
new EmptyBorder(2, 5, 2, 2));
usrNameFeild.setBorder(compundBorder);
usrNameFeild.setOpaque(false);
usrNameLabel.setLabelFor(usrNameFeild);
JLabel passwordLabel = new JLabel("Password");
changeCompFont(passwordLabel);
JPasswordField passFeild = new JPasswordField("Password");
changeCompFont(passFeild);
passFeild.setBorder(compundBorder);
passFeild.setOpaque(false);
passwordLabel.setLabelFor(passFeild);
// working with GridBagConstraints, please check out the linked online tutorial
GridBagConstraints labCnst = new GridBagConstraints();
GridBagConstraints txtCnst = new GridBagConstraints();
labCnst.insets = new Insets(0, 0, 5, 10);
txtCnst.insets = new Insets(0, 0, 5, 10);
labCnst.ipady = txtCnst.ipady = 10;
txtCnst.fill = labCnst.fill = GridBagConstraints.HORIZONTAL;
labCnst.gridx = 0;
txtCnst.gridx = 1;
labCnst.gridwidth = 1;
txtCnst.gridwidth = 2;
labCnst.weightx = 0.3;
txtCnst.weightx = 0.7;
txtCnst.gridy = labCnst.gridy = 0;
add(usrNameLabel, labCnst);
add(usrNameFeild, txtCnst);
txtCnst.gridy = labCnst.gridy = 1;
add(passwordLabel, labCnst);
add(passFeild, txtCnst);
labCnst.gridx = 2;
labCnst.gridy = 2;
labCnst.ipady = 13;
labCnst.insets = new Insets(0, 0, 0, 150);
JButton submitButt = new CButton("Log IN");
add(submitButt, labCnst);
}
public void changeCompFont(JComponent comp)
{
comp.setForeground(Color.WHITE);
comp.setFont(getFont().deriveFont(Font.BOLD, 13));
}
// To PAINT THE TEXTURE ABOVE THE COMPONENTS,
//DON'T DO IT UNTIL YOU UNDERSTAND PAINTING MECHANISM FULLY
#Override
public void paint(Graphics g) {
super.paint(g); //To change body of generated methods, choose Tools | Templates.
Graphics2D g2d = (Graphics2D)g.create(); // cloning to work, it is safer aproach
Rectangle2D txRect = new Rectangle2D.Double(0, 0, textureImg.getWidth(), textureImg.getHeight());
TexturePaint txPaint = new TexturePaint(textureImg, txRect);
g2d.setPaint(txPaint);
//make the texture transparent
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f));
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();// disposing the graphics object
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
Graphics2D g2d = (Graphics2D) g.create();
if(gradientImage==null || gradientImage.getHeight() != getHeight())
{
gradientImage = createGradientImg();
}
g2d.drawImage(gradientImage, 0, 0, getWidth(), getHeight(), this);
g2d.dispose();
}
public BufferedImage createGradientImg()
{
BufferedImage image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
/// background gradient paint, linear gradient paint for the background
/// Gradient paint rendering could be made more optimized
LinearGradientPaint lgrPaint = new LinearGradientPaint(0.0f, 0.0f, getWidth(), getHeight(),
new float[] { 0.0f, 0.5f, 0.6f, 1.0f },
new Color[] { new Color(0x002AFF),
new Color(0x0CAAF9),
new Color(0x0CAAF9),
new Color(0x002AFF) });
Graphics2D g2d = (Graphics2D) image.getGraphics();
g2d.setPaint(lgrPaint);
//g2d.shear(0.2, 0);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();
//g2d.drawImage(textureImg, 0, 0, getWidth(), getHeight(), null);
return image;
}
}
public class CustomApp {
public static void main(String[] args) throws IOException {
// load the texture resource image
System.out.println("Please wait, Loading Texture : http://www.brewsterwallcovering.com/data/default/images/catalog/original/289-5757.jpg");
MainContainer.textureImg = ImageIO.read(new URL("http://www.brewsterwallcovering.com/data/default/images/catalog/original/289-5757.jpg"));
System.out.println("Loading finished. Starting the Demo!");
MainContainer.textureImg = MainContainer.textureImg.getSubimage(0, 0, 200, 200);
// Starting the Swing GUI in the EDT, learn about it
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Demo: LogIn Dialogue");
// set frame size as Demo perposes, otherwise not recommended
frame.setSize(new Dimension(500, 300));
MainContainer container = new MainContainer();
frame.add(new MainContainer());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
You can use JavaFX which make you available some great look and feel.
I think it is better to go with JavaFX if you are looking for a great designs in Java Swing which provide better Look and Feels and animations also.
you can refer this links hope this will be helpful to you.
getting started with FXML
Swing with JavaFX
I want to change JButton gradient color,
i found this, http://java2everyone.blogspot.com/2009/01/set-jbutton-gradient-color.html, but i want to change gradient for only one button, not all button
You can override the paintComponent method of the JButton instance and paint its Graphics object with one of the following classes that implement the Paint interface:
GradientPaint.
LinearGradientPaint
MultipleGradientPaint
RadialGradientPaint
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public final class JGradientButtonDemo {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
final JFrame frame = new JFrame("Gradient JButton Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new FlowLayout());
frame.add(JGradientButton.newInstance());
frame.setSize(new Dimension(300, 150)); // used for demonstration
//frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static class JGradientButton extends JButton {
private JGradientButton() {
super("Gradient Button");
setContentAreaFilled(false);
setFocusPainted(false); // used for demonstration
}
#Override
protected void paintComponent(Graphics g) {
final Graphics2D g2 = (Graphics2D) g.create();
g2.setPaint(new GradientPaint(
new Point(0, 0),
Color.WHITE,
new Point(0, getHeight()),
Color.PINK.darker()));
g2.fillRect(0, 0, getWidth(), getHeight());
g2.dispose();
super.paintComponent(g);
}
public static JGradientButton newInstance() {
return new JGradientButton();
}
}
}
A little improvement over mre answer:
private static final class JGradientButton extends JButton{
private JGradientButton(String text){
super(text);
setContentAreaFilled(false);
}
#Override
protected void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D)g.create();
g2.setPaint(new GradientPaint(
new Point(0, 0),
getBackground(),
new Point(0, getHeight()/3),
Color.WHITE));
g2.fillRect(0, 0, getWidth(), getHeight()/3);
g2.setPaint(new GradientPaint(
new Point(0, getHeight()/3),
Color.WHITE,
new Point(0, getHeight()),
getBackground()));
g2.fillRect(0, getHeight()/3, getWidth(), getHeight());
g2.dispose();
super.paintComponent(g);
}
}
TL;DR: it's not possible directly, but can be done with a workaround like in Luca's answer, however his/her answer uses the incorrect gradient steps. The correct ones are listed below.
The way it works
In the Metal LAF there is a hardcoded exception. If the background property is a subclass of UIResource, it's ignored* and the button is instead painted with the (also hardcoded) gradient from the UI property Button.gradient. Otherwise, if background is not a UIResource, that background is painted as-is.
*unless the button is disabled, in which case there is no gradient and the color inside the UIResource is used for the background.
The gradient
Following the logic of MetalButtonUI, I found out the used gradient it uses comes from the UI property Button.gradient, which contains the ArrayList:
0 = {Float} 0.3
1 = {Float} 0.0
2 = {ColorUIResource} "[221,232,243]"
3 = {ColorUIResource} "[255,255,255]"
4 = {ColorUIResource} "[184,207,229]"
Following the logic even further, I ended up in MetalUtils.GradientPainter.drawVerticalGradient(). This implementation interprets the above data as*:
Gradient from 0% to 30%: color1 to color2
Gradient from 30% to 60%: color2 to color1
Gradient from 60% to 100%: color1 to color3
*assuming the second float is 0.0, otherwise more gradients are drawn.
Since this is a multi-stage gradient, it can't be done with a simple GradientPaint but can be done with a LinearGradientPaint. However the background property only accepts Color. It cannot even be spoofed/hacked because the actual value is eventually given to Graphics.setColor() and not Graphics2D.setPaint() (even though Metal is Swing-based and not AWT) Dead End. The only solution seems to subclass JButton altogether.
Here's my canvas class extending JPanel:
package start;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Board extends JPanel
{
private static final long serialVersionUID = 1L;
public Board() {}
public void paintComponent(Graphics g)
{
int width = getWidth();
int height = getHeight();
this.setBackground(Color.green);
g.setColor(Color.black);
g.drawOval(0, 0, width, height);
}
}
Here's the method where I'm calling it:
private static void createAndShowGUI()
{
JFrame frame = new JFrame("Hello");
frame.setPreferredSize(new Dimension(700, 700));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Board b = new Board();
frame.getContentPane().add(b);
frame.pack();
frame.setVisible(true);
}
But this shows the oval on the default colour. I also tried without the this., and then tried setting the colour of b, and setting the colour inside the constructor, but none of these worked. What's wrong?
EDIT: Sorry for not making thing clear, my goal was to display a thin black oval on a green background.
In the paintComponent method you do not have to use setBackground to change the colour of the JPanel. That should be done outside of paintComponent. paintComponent will probably use the colour of the background before you change it.
There are a number of things you can try. One, is to set the colour in the constructor and then call the super class' paintComponent first like this:
public Board() {
this.setBackground(Color.GREEN);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
g.setColor(Color.BLACK);
g.drawOval(0, 0, width, height);
}
Also note the color constants are all upper case. i.e. BLACK or GREEN.
If you want to change the background colour dynamically then you can do so in the event handler such as mouseEntered or actionPerformed etc.
While the code does not exactly make clear what's your intent i try to fix some issues:
If you want a green background, do as #vincent told you. YOu should see a black oval in green background. The "super.paintComponent" will fill its area with the components background automatically if the panel is opaque.
If you want a green oval on white background, maybe with black border
public void paintComponent(Graphics g)
{
int width = getWidth();
int height = getHeight();
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillOval(0, 0, width, height);
g.setColor(Color.BLACK);
g.drawOval(0, 0, width, height);
}
EDIT
i forgot super