Reputation: 20244
My current program lets the user move a circle around the JFrame and also change its color by pressing one of the colors presented in the JPanel at the bottom of the JFrame.
My code:
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.border.Border;
import javax.swing.BorderFactory;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.FlowLayout;
import java.awt.BorderLayout;
import java.awt.GridLayout;
public class SixthProgram
{
public static void main(String[] args)
{
GUI prog=new GUI("SixthProgram");
prog.setBounds(350,250,500,250);
prog.setVisible(true);
}
}
class GUI extends JFrame implements MouseListener, MouseMotionListener
{
JButton button;
JPanel colorPan, color1, color2, color3 ,color4 ,color5;
Color color=Color.BLACK;
int x=3,y=30;
public GUI(String header)
{
super(header);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
maker();
addMouseListener(this);
addMouseMotionListener(this);
add(colorPan, BorderLayout.SOUTH);
}
public void maker()
{
colorPan = new JPanel();
Border raisedbevel = BorderFactory.createRaisedBevelBorder();
Border loweredbevel = BorderFactory.createLoweredBevelBorder();
Border compound = BorderFactory.createCompoundBorder(raisedbevel, loweredbevel);
colorPan.setBorder(compound);
colorPan.setLayout(new GridLayout(1, 0));
color1 = new JPanel();
color2 = new JPanel();
color3 = new JPanel();
color4 = new JPanel();
color5 = new JPanel();
color1.setBackground(Color.WHITE);
color2.setBackground(Color.GREEN);
color3.setBackground(Color.RED);
color4.setBackground(Color.BLUE);
color5.setBackground(Color.BLACK);
colorPan.add(color1);
colorPan.add(color2);
colorPan.add(color3);
colorPan.add(color4);
colorPan.add(color5);
}
@Override
public void paint(Graphics g)
{
//g.setColor(Color.WHITE);
//g.fillRect(0,0,getWidth(),getHeight());
super.paint(g); //Do the same thing as above(Clear jframe)
g.setColor(color);
g.fillOval(x,y,50,50);
}
public void mouseExited(MouseEvent e) //MouseListener overrided methods
{}
public void mouseEntered(MouseEvent e)
{}
public void mouseReleased(MouseEvent e)
{}
public void mousePressed(MouseEvent e)
{
System.out.println("Press");
if(e.getX()+50 < getWidth() && e.getY()+50 < getHeight()) // Preventing out of bounds
{
x=e.getX();
y=e.getY();
repaint();
}
}
public void mouseClicked(MouseEvent e) //Press+Release=Click
{
System.out.println("Click");
if((e.getX()>=8 && e.getX()<=105) && (e.getY()>=232 && e.getY()<=243))
color=Color.WHITE;
else if((e.getX()>=106 && e.getX()<=203) && (e.getY()>=232 && e.getY()<=243))
color=Color.GREEN;
else if((e.getX()>=204 && e.getX()<=301) && (e.getY()>=232 && e.getY()<=243))
color=Color.RED;
else if((e.getX()>=302 && e.getX()<=399) && (e.getY()>=232 && e.getY()<=243))
color=Color.BLUE;
else if((e.getX()>=400 && e.getX()<=489) && (e.getY()>=232 && e.getY()<=243))
color=Color.BLACK;
repaint();
}
public void mouseDragged(MouseEvent e) //MouseMotionListener overrided methods
{
System.out.println("Dragged to ("+ e.getX() +","+ e.getY() +")");
if((e.getX()>=3 && e.getY()>=30) && (e.getX()+50<getWidth() && e.getY()+50<getHeight())) //If circle is dragged in the JFrame
{
x=e.getX();
y=e.getY();
repaint();
}
}
public void mouseMoved(MouseEvent e)
{}
}
The above code works as expected and produces the output:
When I click the colors in the JPanel in the bottom too, the program works as expected and changes the color of the circle.
The two problems that appears are:
When I resize the JFrame, the color chooser doesn't work as expected. This is due to my stupid way of hardcoding in the mouseClicked
method:
public void mouseClicked(MouseEvent e) //Press+Release=Click
{
System.out.println("Click");
if((e.getX()>=8 && e.getX()<=105) && (e.getY()>=232 && e.getY()<=243))
color=Color.WHITE;
else if((e.getX()>=106 && e.getX()<=203) && (e.getY()>=232 && e.getY()<=243))
color=Color.GREEN;
else if((e.getX()>=204 && e.getX()<=301) && (e.getY()>=232 && e.getY()<=243))
color=Color.RED;
else if((e.getX()>=302 && e.getX()<=399) && (e.getY()>=232 && e.getY()<=243))
color=Color.BLUE;
else if((e.getX()>=400 && e.getX()<=489) && (e.getY()>=232 && e.getY()<=243))
color=Color.BLACK;
repaint();
}
I would prefer not to use setResizable(false)
and that the JFrame to be resizeable.
How do I fix the mentioned problems?
Upvotes: 1
Views: 278
Reputation: 1634
I've just re implemented your problem in a better way. Here is how it looks like now: Problems are solved.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class CirclePainter implements MouseMotionListener, ActionListener {
private JFrame mainFrame;
private JPanel colorPanel, circlePanel;
private JButton whiteColorButton, redColorButton, greenColorButton,
blueColorButton;
private int circleWidth = 3, circleHeight = 15;
private Color circleColor = Color.black;
public CirclePainter() {
initGui();
}
public void initGui() {
mainFrame = new JFrame("Circle");
mainFrame.setLayout(new BorderLayout());
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setSize(500, 400);
colorPanel = new JPanel(new FlowLayout());
whiteColorButton = new JButton();
whiteColorButton.setBackground(Color.white);
whiteColorButton.setActionCommand("white");
whiteColorButton.addActionListener(this);
redColorButton = new JButton();
redColorButton.setBackground(Color.red);
redColorButton.setActionCommand("red");
redColorButton.addActionListener(this);
greenColorButton = new JButton();
greenColorButton.setBackground(Color.green);
greenColorButton.setActionCommand("green");
greenColorButton.addActionListener(this);
blueColorButton = new JButton();
blueColorButton.setBackground(Color.blue);
blueColorButton.setActionCommand("blue");
blueColorButton.addActionListener(this);
colorPanel.add(whiteColorButton);
colorPanel.add(redColorButton);
colorPanel.add(greenColorButton);
colorPanel.add(blueColorButton);
circlePanel = new JPanel() {
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(circleColor);
g.fillOval(circleWidth, circleHeight, 50, 50);
}
};
circlePanel.addMouseMotionListener(this);
circlePanel.setBackground(Color.yellow);
mainFrame.add(circlePanel, BorderLayout.CENTER);
mainFrame.add(colorPanel, BorderLayout.PAGE_END);
mainFrame.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case "white":
circleColor = Color.white;
circlePanel.repaint();
break;
case "red":
circleColor = Color.red;
circlePanel.repaint();
break;
case "green":
circleColor = Color.green;
circlePanel.repaint();
break;
case "blue":
circleColor = Color.blue;
circlePanel.repaint();
break;
default:
break;
}
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new CirclePainter();
}
});
}
@Override
public void mouseDragged(MouseEvent e) {
if ((e.getX() >= 0 && e.getY() >= 0)
&& (e.getX() <= mainFrame.getWidth() - 60)
&& (e.getY() <= mainFrame.getHeight() - 110)) {
circleWidth = e.getX();
circleHeight = e.getY();
circlePanel.repaint();
}
}
@Override
public void mouseMoved(MouseEvent arg0) {
}
}
Here is the output:
Upvotes: 2
Reputation: 324098
You should NOT override the paint() method of a JFrame. Custom painting is done by overriding the paintComponent() method of a JPanel (or JComponent) and then you add the panel to the frame. You would add this panel to the frame using BorderLayout.CENTER
.
For your colors you should create a separate panel and add buttons to the panel to represent each color. You would set the background of each button to the specific color. You could use a GridLayout. Then you add this panel to the BorderLayout.PAGE_END
of the frame.
Then, instead of using a MouseListener you would add an ActionListener
to each button. The basic code would be:
public void actionPerformed(ActionEvent e)
{
JButton button = (JButton)e.getSource();
color = button.getBackground();
repaint();
}
Upvotes: 3