Hi I am programming a game and i thought a rounded button would look nice but i am curious how do i change the size of said button to something bigger? here is my code
public JavaApplication3(String label) {
super(label);
Dimension size = getPreferredSize();
size.width = size.height = Math.max(size.width,size.height);
setPreferredSize(size);
setContentAreaFilled(false);
}
protected void paintComponent(Graphics g) {
if (getModel().isArmed()) {
g.setColor(Color.RED);
} else {
g.setColor(Color.yellow);
}
g.fillOval(0, 0, getSize().width-1,getSize().height-1);
super.paintComponent(g);
}
protected void paintBorder(Graphics g) {
g.setColor(getForeground());
g.drawOval(0, 0, getSize().width-1, getSize().height-1);
}
Shape shape;
public boolean contains(int x, int y) {
if (shape == null ||
!shape.getBounds().equals(getBounds())) {
shape = new Ellipse2D.Float(0, 0, getWidth(), getHeight());
}
return shape.contains(x, y);
}
Hope someone can help :)
this changes the size of your button with every time you click on it.
addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("klick");
setSize(new Dimension(newSizeWidth, newSizeHeight));
}
});
}
just call the
setSize(new Dimension(newSizeWidth, newSizeHeight));
method.
here is some working code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JButton;
import javax.swing.JFrame;
public class test2 extends JButton {
int width = 100;
int height = 100;
public test2(String label) {
super(label);
setSize(width, height);
setContentAreaFilled(false);
addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("klick");
setSize(new Dimension(width--, height--));
}
});
}
protected void paintComponent(Graphics g) {
if (getModel().isArmed()) {
System.out.println(width + " " + height);
g.setColor(Color.RED);
} else {
g.setColor(Color.yellow);
}
g.fillOval(0, 0, getSize().width - 1, getSize().height - 1);
super.paintComponent(g);
}
protected void paintBorder(Graphics g) {
g.setColor(getForeground());
g.drawOval(0, 0, getSize().width - 1, getSize().height - 1);
}
Shape shape;
public boolean contains(int x, int y) {
if (shape == null || !shape.getBounds().equals(getBounds())) {
shape = new Ellipse2D.Float(0, 0, getWidth(), getHeight());
}
return shape.contains(x, y);
}
static JFrame f;
public static void main(String[] args) {
f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationRelativeTo(null);
f.setSize(200, 200);
f.add(new test2("label"));
f.setLayout(new BorderLayout());
f.setVisible(true);
}
}
Related
I want to create a continuous animation of a moving truck in java applets. In this the truck should reappear from the other side as soon as it disappears.
I tried using one truck but then it appears on the other side only after completely disappearing from one side. Hence, I used two.
Following is my code:
public class prc1 extends Applet implements Runnable{
Thread t;
int x=0;
int y=0;
int i;
public void start(){
t = new Thread(this);
t.start();
}
public void paint(Graphics g){
g.setColor(Color.gray);
g.fillRect(x,10,70,45);
g.setColor(Color.yellow);
g.fillRoundRect(50+x,15,35,35,10,10);
g.setColor(Color.black);
g.fillArc(5+x,50,10,10,0,360);
g.fillArc(55+x,50,10,10,0,360);
g.setColor(Color.gray);
g.fillRect(y,10,70,45);
g.setColor(Color.yellow);
g.fillRoundRect(50+y,15,35,35,10,10);
g.setColor(Color.black);
g.fillArc(5+y,50,10,10,0,360);
g.fillArc(55+y,50,10,10,0,360);
}
public void run(){
try{
y=-90;
x=0;
for(; ;){
Thread.sleep(100);
repaint();
run();
x=x+5;
if(x==400){
for(; ;){
y=y+5;
Thread.sleep(100);
repaint();
run();
x=x-5;
if(x==0){
y=-90;
break;
}
}
}
}
}catch(InterruptedException e){ }
}
}
Now the problem is that the truck does not move at all.
So the basic idea is, you need to determine when the truck begins to leave the viewable area and then calculate the amount of "overflow", which would then allow you to paint the truck a second time at a new position subtracted from the overflow.
I've broken you code down so the Truck is it's own class, this makes it easier to deal with and allows a little more control over the painting process.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Truck truck;
public TestPane() {
truck = new Truck();
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
truck.update(getSize());
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
truck.paint(g2d);
g2d.dispose();
}
}
public class Truck {
private int x, y;
// I had to calculate these
private int width = 85;
private int height = 65;
private int xDelta = 4;
private int xOverFlow = 0;
public void update(Dimension bounds) {
x += xDelta;
if (x > bounds.width) {
x = 0;
}
if (x + width > bounds.width) {
xOverFlow = (x + width) - bounds.width;
} else {
xOverFlow = -1;
}
}
public void paint(Graphics2D g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.translate(x, y);
paintTruck(g2d);
g2d.dispose();
if (xOverFlow > 0) {
g2d = (Graphics2D) g.create();
g2d.translate(xOverFlow - width, y);
paintTruck(g2d);
g2d.dispose();
}
}
protected void paintTruck(Graphics2D g2d) {
g2d.setColor(Color.gray);
g2d.fillRect(0, 10, 70, 45);
g2d.setColor(Color.yellow);
g2d.fillRoundRect(50, 15, 35, 35, 10, 10);
g2d.setColor(Color.black);
g2d.fillArc(5, 50, 10, 10, 0, 360);
g2d.fillArc(55, 50, 10, 10, 0, 360);
g2d.setColor(Color.gray);
g2d.fillRect(0, 10, 70, 45);
g2d.setColor(Color.yellow);
g2d.fillRoundRect(50, 15, 35, 35, 10, 10);
g2d.setColor(Color.black);
g2d.fillArc(5, 50, 10, 10, 0, 360);
g2d.fillArc(55, 50, 10, 10, 0, 360);
}
}
}
Another option might be to have more than one instance of truck, so as the second one begins to leave the viewable you could create another one
For example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private List<Truck> trucks;
public TestPane() {
trucks = new ArrayList<>(2);
trucks.add(new Truck());
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Truck[] truckArray = trucks.toArray(new Truck[trucks.size()]);
for (Truck truck : truckArray) {
truck.update(getSize());
if (truck.getX() > getWidth()) {
trucks.remove(truck);
} else if (truck.getX() + truck.getWidth() > getWidth() && trucks.size() == 1) {
trucks.add(new Truck());
}
}
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (Truck truck : trucks) {
truck.paint(g2d);
}
g2d.dispose();
}
}
public class Truck {
// I had to calculate these
private int width = 85;
private int height = 65;
private int x = -width;
private int y;
private int xDelta = 4;
public void update(Dimension bounds) {
x += xDelta;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public void paint(Graphics2D g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.translate(x, y);
paintTruck(g2d);
g2d.dispose();
}
protected void paintTruck(Graphics2D g2d) {
g2d.setColor(Color.gray);
g2d.fillRect(0, 10, 70, 45);
g2d.setColor(Color.yellow);
g2d.fillRoundRect(50, 15, 35, 35, 10, 10);
g2d.setColor(Color.black);
g2d.fillArc(5, 50, 10, 10, 0, 360);
g2d.fillArc(55, 50, 10, 10, 0, 360);
g2d.setColor(Color.gray);
g2d.fillRect(0, 10, 70, 45);
g2d.setColor(Color.yellow);
g2d.fillRoundRect(50, 15, 35, 35, 10, 10);
g2d.setColor(Color.black);
g2d.fillArc(5, 50, 10, 10, 0, 360);
g2d.fillArc(55, 50, 10, 10, 0, 360);
}
}
}
I am currently in the process of developing an app, that needs the functionality to select screen area. I've come up with creating a transparent, undecorated, fullscreen JFrame, and adding a translucent, non-opaque JPanel inside of it, where a half-translucent dark background, as well as the selection is painted.
And while the idea (and the code) runs fine on Windows, its not the same story on linux, where the background of the JPanel does not seem to be cleared upon calling repaint() (even though i tell it to via various methods) - upon each repaint method, the background and the component get darker and darker, etc.
Here's the MVCE:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ExampleFrame extends JFrame{
private ExamplePanel selectionPane;
public ExampleFrame(){
this.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
ExampleFrame.this.dispatchEvent(new WindowEvent(ExampleFrame.this, WindowEvent.WINDOW_CLOSING));
}
}
});
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
this.setSize(screenSize);
this.setUndecorated(true);
this.setBackground(new Color(255, 255, 255, 0));
populate();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setType(Window.Type.UTILITY);
this.setVisible(true);
}
private void populate(){
this.selectionPane = new ExamplePanel();
this.setContentPane(selectionPane);
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new ExampleFrame();
}
});
}
public static class ExamplePanel extends JPanel{
private static Color bg = new Color(0,0,0,0.5f);
private int sx = -1, sy = -1, ex = -1, ey = -1;
public ExamplePanel(){
MouseAdapter mouseAdapter = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
sx = sy = ex = ey = -1;
sx = e.getX();
sy = e.getY();
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
ex = e.getX();
ey = e.getY();
repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
ex = e.getX();
ey = e.getY();
repaint();
}
};
this.addMouseListener(mouseAdapter);
this.addMouseMotionListener(mouseAdapter);
this.setDoubleBuffered(false);
this.setOpaque(false);
this.setBackground(bg);
}
#Override
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D)g.create();
g2.setComposite(AlphaComposite.Clear);
g2.setBackground(new Color(255, 255, 255, 0));
g2.fillRect(0, 0, getWidth(), getHeight());
//g2.clearRect(0, 0, getWidth(), getHeight()); //neither of them work
g2.setComposite(AlphaComposite.Src.derive(.5f));
g2.setPaint(getBackground());
g2.fillRect(0, 0, getWidth(), getHeight());
g2.setComposite(AlphaComposite.Src.derive(1f));
g2.setPaint(Color.WHITE);
g2.drawString("Press Escape to exit", 10, 20);
if(!(sx == -1 || sy == -1 || ex == -1 || ey == -1)){
int asx = Math.min(sx, ex);
int asy = Math.min(sy, ey);
int w = Math.abs(ex - sx);
int h = Math.abs(ey - sy);
g2.setComposite(AlphaComposite.Src);
g2.setPaint(new Color(255, 255, 255, 0));
g2.fillRect(asx, asy, w, h);
g2.setPaint(new Color(0, 0, 0, 1));
g2.fillRect(asx, asy, w, h);
g2.setComposite(AlphaComposite.SrcOver);
g2.setStroke(new BasicStroke(2));
g2.setPaint(new Color(1, 1, 1, 0.15f));
g2.drawRect(asx-1,asy-1, w+2, h+2);
}
}
}
}
Any ideas as to what might cause this? Or maybe this is a bug with Java on linux? I had tested this under Windows 10, and Ubuntu 14.04 LTS as well as unknown version of Arch Linux running with KDE gui (tested by a friend)
EDIT: also tested under OSX (Yosemite & El capitan), both worked fine.
this.setBackground(new Color(255, 255, 255, 0));
If you want a component completely transparent then just use:
component.setOpaque( false );
This tells Swing to look for the parent component and paint it first so you don't get the painting artifacts.
private static Color bg = new Color(0,0,0,0.5f);
If you want semi-transparent backgrounds then need to do custom coding since Swing doesn't support this.
Check out Backgrounds With Transparency for more information on this topic and a couple of solutions.
One is to do your own custom painting with code like:
JPanel panel = new JPanel()
{
protected void paintComponent(Graphics g)
{
g.setColor( getBackground() );
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
};
The other solution is a reusable class that can be used with any component so you don't need to customize every component.
panel.setOpaque(false); // background of parent will be painted first
panel.setBackground( new Color(255, 0, 0, 20) );
frame.add(panel);
It's difficult to know the exact cause of the problem without been able to replicate it. There are a number of areas of concern within the code...
Not honouring the paint call chain by not calling super.paintComponent
The use of setDoubleBuffered(false)
The use of this.setBackground(bg); on a JPanel and passing an alpha based color to it
The extensive use of AlphaComposite and it's scrupulous use to try and clear the Graphics context
The basic course of action would be to simplify the paint process until such a time as you can identify the action or combination of actions which are causing the issues.
Or take another approach. Rather than using a combination of different AlphaComposite settings, you might consider just using a Area and subtract the area you want exposed from it....
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.geom.Area;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ExampleFrame extends JFrame {
private ExamplePanel selectionPane;
public ExampleFrame() {
this.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
ExampleFrame.this.dispatchEvent(new WindowEvent(ExampleFrame.this, WindowEvent.WINDOW_CLOSING));
}
}
});
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
this.setSize(screenSize);
this.setUndecorated(true);
this.setBackground(new Color(255, 255, 255, 0));
populate();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setType(Window.Type.UTILITY);
this.setVisible(true);
}
private void populate() {
this.selectionPane = new ExamplePanel();
this.setContentPane(selectionPane);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new ExampleFrame();
}
});
}
public static class ExamplePanel extends JPanel {
private static Color bg = new Color(0, 0, 0);
private int sx = -1, sy = -1, ex = -1, ey = -1;
public ExamplePanel() {
MouseAdapter mouseAdapter = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
sx = sy = ex = ey = -1;
sx = e.getX();
sy = e.getY();
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
ex = e.getX();
ey = e.getY();
repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
ex = e.getX();
ey = e.getY();
repaint();
}
};
this.addMouseListener(mouseAdapter);
this.addMouseMotionListener(mouseAdapter);
this.setOpaque(false);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
Area area = new Area(new Rectangle(0, 0, getWidth(), getHeight()));
if (!(sx == -1 || sy == -1 || ex == -1 || ey == -1)) {
int asx = Math.min(sx, ex);
int asy = Math.min(sy, ey);
int w = Math.abs(ex - sx);
int h = Math.abs(ey - sy);
area.subtract(new Area(new Rectangle(asx - 1, asy - 1, w + 2, h + 2)));
}
g2.setComposite(AlphaComposite.Src.derive(.25f));
g2.setPaint(bg);
g2.fill(area);
g2.setComposite(AlphaComposite.Src.derive(1f));
g2.setPaint(Color.WHITE);
g2.drawString("Press Escape to exit", 10, 20);
g2.dispose();
}
}
}
Be sure to call super.paintComponent() if you want to clear the background.
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g.create();
I have a question. I created the Round Button, the code references from someone else cause I'm beginner. I want to set the position for it, but It seem to be unsuccessful. I thought the error is from its contains.
public final class ButtonDesigned extends JButton {
public ButtonDesigned (String label) {
super(label);
Dimension size = getPreferredSize();
size.width = size.height = Math.max(size.width,size.height);
setPreferredSize(size);
setContentAreaFilled(false);
}
protected void paintComponent(Graphics g) {
if (getModel().isArmed()) {
g.setColor(Color.lightGray);
} else {
g.setColor(getBackground());
}
g.fillOval(0, 0, getSize().width-1,getSize().height-1);
super.paintComponent(g);
}
protected void paintBorder(Graphics g) {
g.setColor(getForeground());
g.drawOval(0, 0, getSize().width-1, getSize().height-1);
}
Shape shape;
public boolean contains(int x, int y) {
if (shape == null ||
!shape.getBounds().equals(getBounds())) {
shape = new Ellipse2D.Float(0, 0, getWidth(), getHeight());
}
return shape.contains(x, y);
}
public static void main(String[] args) {
JButton button = new ButtonDesigned ("Click");
button.setBackground(Color.gray);
button.setLocation(70, 70);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "you have clicked");
}
});
enter code here
JFrame frame = new JFrame();
frame.getContentPane().add(button);
frame.getContentPane().setLayout(new FlowLayout());
frame.setSize(300, 300);
frame.setVisible(true);
}
}
I want to make JTextArea has a rounded corners, and i did this code :
public BPosTxtArea() {
super();
setOpaque(false);
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(getBackground());
g2.fillRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 15, 15);
super.paintComponent(g);
}
#Override
protected void paintBorder(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(new Color(102, 102, 102));
g2.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 15, 15);
}
but it still has a square border outside like picture bellow :
Can anyone help me?
Start by having a look at How to Use Borders
This is a very simple example:
public class RoundBorder implements Border {
private int radius;
public RoundBorder(int radius) {
this.radius = radius;
}
public int getRadius() {
return radius;
}
#Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.draw(new RoundRectangle2D.Double(x, y, width - 1, height - 1, getRadius(), getRadius()));
g2d.dispose();
}
#Override
public Insets getBorderInsets(Component c) {
int value = getRadius() / 2;
return new Insets(value, value, value, value);
}
#Override
public boolean isBorderOpaque() {
return false;
}
}
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
public class Example {
public static void main(String[] args) {
new Example();
}
public Example() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
JTextArea ta = new JTextArea(10, 20);
ta.setBorder(new RoundBorder(20));
JScrollPane sp = new JScrollPane(new JTextArea(10, 20));
sp.setBorder(new RoundBorder(20));
add(ta, gbc);
add(sp, gbc);
}
}
public class RoundBorder implements Border {
private int radius;
public RoundBorder(int radius) {
this.radius = radius;
}
public int getRadius() {
return radius;
}
#Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.draw(new RoundRectangle2D.Double(x, y, width - 1, height - 1, getRadius(), getRadius()));
g2d.dispose();
}
#Override
public Insets getBorderInsets(Component c) {
int value = getRadius() / 2;
return new Insets(value, value, value, value);
}
#Override
public boolean isBorderOpaque() {
return false;
}
}
}
Problems, the border is painted "within" the component fill area, meaning that the corners will be the same color as the fill area. There's no way around it using Border.
The trick would be to create a second component, onto which you could paint the border (via the paintComponent, filling the area within the border the same color as the text area) and then add the component into that.
Updated
Based on you code example, you're not overriding getInsets, which is going to be very important, the other thing is, it appears that your JTextArea is within a JScrollPane...
public class BPosTextArea extends JTextArea {
private int radius;
public BPosTextArea() {
super(10, 20);
setOpaque(false);
setBorder(null);
setRadius(20);
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(getBackground());
g2.fillRoundRect(0, 0, getWidth() - 1, getHeight() - 1, getRadius(), getRadius());
super.paintComponent(g);
}
#Override
protected void paintBorder(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(new Color(102, 102, 102));
g2.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, getRadius(), getRadius());
}
public void setRadius(int radius) {
this.radius = radius;
repaint();
}
public int getRadius() {
return radius;
}
#Override
public Insets getInsets() {
int value = getRadius() / 2;
return new Insets(value, value, value, value);
}
}
A solution is to set the border to null for the JScrollPane
My problem is the following: i'm trying to make a paint application in java. I get this error code:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at areacalc.DrawArea.clear(Form.java:67)
at areacalc.DrawArea.mouseMoved(Form.java:115)
when i'm clearing the drawing surface.
Here is my code, could you please help me to avoid the null pointer? Where should i place the event handlers to not to get null pointer?
Thank you so much!
Regards, Stanley.
package areacalc;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import javax.swing.JComponent;
import javax.swing.JFrame;
class DrawArea extends JComponent implements MouseListener, MouseMotionListener
{
private Image image;
private Graphics2D g2;
private int currentX, currentY, oldX, oldY, X, Y;
private ArrayList<Integer[]> points = new ArrayList<Integer[]>();
private boolean stopped = false;
public boolean crtl_pressed = false;
public DrawArea()
{
setDoubleBuffered(false);
initEventHandlers();
}
public void initEventHandlers()
{
addMouseListener(this);
addMouseMotionListener(this);
}
public double length(int x1, int x2)
{
return Math.abs(x1-x2);
}
protected void paintComponent(Graphics g)
{
//System.out.println("paintComponent");
if (image == null)
{
image = createImage(getSize().width, getSize().height);
g2 = (Graphics2D) image.getGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
clear();
}
g.drawImage(image, 0, 0, null);
}
public void clear()
{
g2.setPaint(Color.black);
g2.fillRect(0, 0, getSize().width, getSize().height);
repaint();
}
#Override
public void mousePressed(MouseEvent e)
{
if(e.getButton() == MouseEvent.BUTTON1&&(!stopped))
{
oldX = e.getX();
oldY = e.getY();
if((currentX!=oldX)&&(currentY!=oldY)&&(currentX!=0)&&(currentY!=0))
{
g2.setPaint(Color.green);
Integer i[] = { currentX, currentY, e.getX(), e.getY() };
points.add(i);
g2.drawLine(currentX, currentY, e.getX(), e.getY());
repaint();
}
}
else if(e.getButton() == MouseEvent.BUTTON3&&points.size()>0)
{
g2.setPaint(Color.green);
g2.drawLine(currentX, currentY, e.getX(), e.getY());
if(points.size()>0)
{
Integer i[] = points.get(0);
g2.drawLine(e.getX(), e.getY(), i[0], i[1]);
}
repaint();
stopped = true;
}
}
#Override
public void mouseMoved(MouseEvent e)
{
if((!stopped))
{
//label.setText(e.getX() + ";" + e.getY());
currentX = oldX;
currentY = oldY;
clear();
for(int j = 0; j < points.size(); j++)
{
g2.setPaint(Color.green);
Integer i[] = points.get(j);
g2.drawLine(i[0], i[1], i[2], i[3]);
repaint();
}
if((currentX!=0)&&(currentY!=0))
{
g2.setPaint(Color.yellow);
if(!crtl_pressed)
{
if(points.size()>0)
{
Integer i[] = points.get(0);
g2.drawLine(e.getX(), e.getY(), i[0], i[1]);
}
g2.drawLine(currentX, currentY, e.getX(), e.getY());
}
else
{
if(length(currentX, e.getX())>=length(currentY, e.getY()))
{
if(points.size()>0)
{
Integer i[] = points.get(0);
g2.drawLine(e.getX(), currentY, i[0], i[1]);
}
g2.drawLine(currentX, currentY, e.getX(), currentY);
}
else
{
if(points.size()>0)
{
Integer i[] = points.get(0);
g2.drawLine(currentX, e.getY(), i[0], i[1]);
}
g2.drawLine(currentX, currentY, currentX, e.getY());
}
}
repaint();
}
}
}
public void mouseDragged(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseClicked(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
}
public class Form extends JFrame implements ActionListener
{
public Form()
{
initUI();
}
private void initUI()
{
setTitle("Area Calculator");
setSize(600, 600);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
Container content = getContentPane();
content.setLayout(new BorderLayout());
DrawArea drawArea = new DrawArea();
content.add(drawArea, BorderLayout.CENTER);
addKeyListener(
new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_CONTROL);
//drawArea.crtl_pressed = true;
}
public void keyReleased(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_CONTROL);
//drawArea.crtl_pressed = false;
}
});
}
private void doDrawing(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
g2d.setPaint(Color.blue);
g2d.drawLine(20, 20, 500, 500);
}
public void paintComponent(Graphics g)
{
paintComponent(g);
doDrawing(g);
}
#Override
public void actionPerformed(ActionEvent e)
{
repaint();
}
}
If clear() is called before paintComponent(), the variable g2 is not initialized.
You could initialize your g2 instance in the constructor, but I'm not sure if this works for you because you need the size of the window.
Another option is to insert
if (g2 == null) return;
as first line for clear.
It seems that this is kind of a double buffering implementation. I'm sure Google will help you finding good examples for alternative implementations without this problem.