i'm trying to create a small drawing tool in java. I want the color the user is drawing with to change when they select a button. I tried to set up my buttons to do such. But when I run the app and select a button the color does not change. How can I fix this?
myJPanel.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class myJPanel extends JPanel implements MouseMotionListener, ActionListener
{
JButton red, blue, yellow, eraser;
JPanel p1;
Graphics gg;
public myJPanel()
{
setBackground(Color.white);
setLayout(new BorderLayout());
p1 = new JPanel();
p1.setLayout(new GridLayout(3,3));
red = new JButton("Red");
blue = new JButton("Blue");
yellow = new JButton("Yellow");
eraser = new JButton("Eraser");
p1.add(red);
p1.add(blue);
p1.add(yellow);
p1.add(eraser);
add(p1,"South");
addMouseMotionListener(this);
}
public void mouseMoved(MouseEvent evt)
{
}
public void mouseDragged(MouseEvent evt)
{
Point pt = evt.getPoint();
int x = pt.x;
int y = pt.y;
Graphics gg = getGraphics();
gg.setColor(Color.GREEN);
gg.fillRect(x, y, 5, 5);
}
#Override
public void actionPerformed(ActionEvent event)
{
Object obj = event.getSource();
String choice = event.getActionCommand();
if (obj == red) {
gg.setColor(Color.red);
}
if (obj == blue) {
gg.setColor(Color.blue);
}
if (obj == yellow) {
gg.setColor(Color.yellow);
}
if (obj == eraser) {
gg.setColor(Color.white);
}
}
}
You use a graphics that is not used to paint.
Whatever, don't draw like this, override paintComponent method to make it draw what you like, and call repaintwhen you need the drawing to be made:
public class myJPanel extends JPanel implements MouseMotionListener, ActionListener
{
JButton red, blue, yellow, eraser;
JPanel p1;
Color currentColor;
int x, y;
public myJPanel() {
setBackground(Color.white);
setLayout(new BorderLayout());
p1 = new JPanel();
p1.setLayout(new GridLayout(3,3));
yellow = new JButton("Yellow");
eraser = new JButton("Eraser");
p1.add(yellow);
p1.add(eraser);
add(p1,"South");
addMouseMotionListener(this);
}
public void paintComponent(Graphics g) { // draw something on request
g.setColor(currentColor);
g.fillRect(x, y, 5, 5);
}
public void mouseDragged(MouseEvent evt)
{
Point pt = evt.getPoint();
x = pt.x;
y = pt.y;
repaint(); // a new point to draw, please call me back...
}
#Override
public void actionPerformed(ActionEvent event) {
Object obj = event.getSource();
String choice = event.getActionCommand();
if (obj == yellow) {
currentColor = Color.yellow);
}
if (obj == eraser) {
currentColor = Color.white);
}
}
}
Related
I posted this code earlier, and got a very good answer, but not a working answer. Could someone please show me how to change my code in order to get this fixed? This will run and compile. It is supposed to draw a line on top of a line, but instead it is drawing under the previous line. I have tried using Collections.reverse(segments); but it doesn't take care of element at zero. I also have tried changing to segments.add(new Segment()); but I am not sure what to change in MouseMotionListener to get this to work accordingly. Any help with this would be great! Thank You! :)
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class SimplePaint extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
JButton action = new JButton();
JButton red = new JButton();
JButton blue = new JButton();
JButton yellow = new JButton();
Color initial = Color.MAGENTA;
JButton thin = new JButton();
JButton medium = new JButton();
JButton thick = new JButton();
Stroke stroke = new BasicStroke(3);
private static ArrayList<Point> points = new ArrayList<Point>();
JButton erase = new JButton();
JButton drawing = new JButton();
Point start = null;
Point end = null;
Line2D draw = new Line2D.Float();
JPanel panel = new JPanel();
private class Segment {
private final List<Point> points = new ArrayList<Point>();
private final Color color = initial;
private final Stroke stroke = SimplePaint.this.stroke;
}
private final List<Segment> segments = new ArrayList<>();
public SimplePaint() {
getContentPane().add(panel);
setSize(450, 450);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
design();
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
segments.add(0, new Segment());
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
segments.get(0).points.add(e.getPoint());
repaint();
}
});
addMouseMotionListener(new MouseMotionAdapter(){
#Override
public void mouseDragged(MouseEvent e){
points.add(e.getPoint());
repaint();
}
});
blue.addActionListener(this);
red.addActionListener(this);
yellow.addActionListener(this);
thin.addActionListener(this);
medium.addActionListener(this);
thick.addActionListener(this);
erase.addActionListener(this);
drawing.addActionListener(this);
}
public void design() {
panel.setBackground(Color.BLACK);
blue.setBackground(Color.BLUE);
blue.setPreferredSize(new Dimension(50, 25));
panel.add(blue);
red.setBackground(Color.RED);
red.setPreferredSize(new Dimension(50, 25));
panel.add(red);
yellow.setBackground(Color.yellow);
yellow.setPreferredSize(new Dimension(50, 25));
panel.add(yellow);
thin.setText("Thin");
panel.add(thin);
medium.setText("Medium");
panel.add(medium);
thick.setText("Thick");
panel.add(thick);
erase.setText("Erase");
panel.add(erase);
drawing.setText("Draw");
panel.add(drawing);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == blue){
initial = Color.BLUE;
}else if(e.getSource() == red){
initial = Color.RED;
}else if(e.getSource() == yellow){
initial = Color.YELLOW;
}else if(e.getSource() == thin){
stroke = new BasicStroke(1);
}else if(e.getSource() == medium){
stroke = new BasicStroke(5);
}else if(e.getSource() == thick){
stroke = new BasicStroke(10);
}else if(e.getSource() == erase){
initial = Color.WHITE;
stroke = new BasicStroke(15);
}
//repaint();
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
int x1, y1, x2, y2;
for (Segment segment : segments) {
g2.setColor(segment.color);
g2.setStroke(segment.stroke);
for (int p = 0; p < segment.points.size() - 1; p++) {
x1 = segment.points.get(p).x;
y1 = segment.points.get(p).y;
x2 = segment.points.get(p + 1).x;
y2 = segment.points.get(p + 1).y;
g2.drawLine(x1, y1, x2, y2);
}
}
g2.dispose();
}
public static void main(String []args){
SimplePaint s = new SimplePaint();
s.setVisible(true);
}
}
To fix your issue, you need to add to the end of the List and not the beginning:
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
segments.add(new Segment());
}
});
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
segments.get(segments.size() - 1).points.add(e.getPoint());
repaint();
}
});
Additionally, the second mouseDragged() implementation appears redundant, if you remove it, it still functions as expected.
// Can be removed
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
points.add(e.getPoint());
repaint();
}
});
Also, you should really use a JComponent or JPanel to paint your sketch, #Override paintComponent() as opposed to paint() with this approach. This will help (or should completely) remove the flickering you see. Coupled with a javax.swing.Timer to repaint() as opposed to dragging which could update extremely (and unnecessarily) quickly.
Finally, you should ensure your GUI is running on the event dispatch thread using SwingUtilities.invokeLater(Runnable doRun), since Swing objects are not thread safe.
e.g.
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
SimplePaint s = new SimplePaint();
s.setVisible(true);
}
});
}
I have program where I draw rectangles, however when I change the color of my graphics object(the mouse), it changes all of it too. Do I have to make another arraylist or is it possible to add on to existing one.
public class Rectangles extends JPanel {
private JRadioButton red, black;
private Color c;
private ArrayList<Point> points;
public Rectangles() {
setLayout(new FlowLayout());
setBackground(Color.white);
JPanel pane = new JPanel();
pane.setBackground(Color.gray);
points = new ArrayList<Point>();
addMouseListener(new MovementListener());
red = new JRadioButton("Red");
black = new JRadioButton("Black");
red.addActionListener(new ChangeColorListener());
black.addActionListener(new ChangeColorListener());
ButtonGroup group = new ButtonGroup();
group.add(red);
group.add(black);
red.setBackground(Color.red);
black.setBackground(Color.black);
add(pane);
pane.add(red);
pane.add(black);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(c);
for (int i = 0; i < points.size(); i++) {
Point p = points.get(i);
g.drawRect(p.x, p.y, 15, 15);
}
}
private class MovementListener extends MouseInputAdapter {
public void mouseClicked(MouseEvent ex) {
addMouseMotionListener(new MovementListener());
}
public void mouseMoved(MouseEvent ex) {
Point point = ex.getPoint();
points.add(point);
repaint();
}
}
private class ChangeColorListener implements ActionListener {
public void actionPerformed(ActionEvent ex) {
if (ex.getSource() == red) {
c = Color.red;
} else if (ex.getSource() == black) {
c = Color.black;
}
}
}
You will probably need to add another properties to these objects in the future. I recommend to create another class for that.
class MyPoint {
// if the values would be unchangeable make them final
private Point point;
private Color color;
public MyPoint(Point point, Color color) {
this.point = point;
this.color = color;
}
// getters
}
Also a small advice, in constructor you should only set the parameters. In your case I would create a method named "init()" and there create all there panels etc.
So this program that I wrote is supposed to draw a circle everytime click on the panel. For some reason I initially have a semicircle in the top right hand corner upon startup, and I can't get it to draw a circle. Can anyone see what's wrong with it? The circle should be 20 px in diameter, drawn with the clicked point at its center.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class QuizActionsInitial extends JFrame {
public JButton redButton = new JButton("red");
public JButton clearButton = new JButton("clear");
boolean isRed = false;
int x1,y1;
boolean clear = false;
CirclePanel myPanel;
public QuizActionsInitial() {
myPanel = new CirclePanel();
add(myPanel, BorderLayout.SOUTH);
JPanel southPanel = new JPanel(new FlowLayout());
clearButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
clear = true;
}
});
myPanel.addMouseListener(new CircleListener());
southPanel.add(redButton);
southPanel.add(clearButton);
add(southPanel, BorderLayout.NORTH);
pack();
setVisible(true);
} // end constructor
public class CirclePanel extends JPanel {
public CirclePanel() {
setPreferredSize(new Dimension(400,300));
setBorder(BorderFactory.createLineBorder(Color.BLUE, 2));
}
public void paintComponent(Graphics gc){
super.paintComponent(gc);
gc.fillOval(x1-10,y1-10,20,20);
}
} // end class CirclePanel
// end class CirclePanel
public class CircleListener extends MouseAdapter{
public void mouseClicked(MouseEvent e){
if (clear = false){
x1 = e.getX();
y1 = e.getY();
}
repaint();
clear = false;
}
}
public static void main(String args[]) {
new QuizActionsInitial();
} // end main
} // end class QuizActionsInitial
int x1,y1; initialise the values to 0, so you it will always draw an initial circle at -10x-10
Trying using a java.awt.Point class instead, and when it's null, don't paint anything...
//int x1,y1;
private Point point;
//...
public void paintComponent(Graphics gc){
super.paintComponent(gc);
if (point != null) {
gc.fillOval(point.x-10,point.y-10,20,20);
}
}
//...
public void mouseClicked(MouseEvent e){
if (!clear){
point = evt.getPoint();
}
clear = false;
repaint();
}
Oh, and if (clear = false){ is an assignment (making clear equal to false, so that the if statement will ALWAYS fail)
I have a problem with Paint- Repaint-Mechanism in Swing java.:
i want to create GraphicEditor, which can create a rectangle and shape with the Mouse.
The application should look like this
My Code Look like this :
public class MiniGrafikEditor extends JFrame implements ActionListener {
private Vector rectList;
private Rectangle currentRect;
private Color color = Color.green;
private static int v = 0 ;
JPanel bp;
public static void main(String[] args) {
MiniGrafikEditor wnd = new MiniGrafikEditor();
}
public MiniGrafikEditor() {
super("Rechtecke zeichnen");
rectList = new Vector();
currentRect = new Rectangle(0, 0, 0, 0);
setLayout(new BorderLayout());
addWindowListener(new MyWindowListener());
addMouseListener(new MyMouseListener());
addMouseMotionListener(new MyMouseMotionListener());
bp = new JPanel();
bp.setBackground(Color.gray);
add("North", bp);
JRadioButton b = null;
bp.add(b = new JRadioButton("Rechteck"));
b.addActionListener(this);
bp.add(b = new JRadioButton("kreis"));
b.addActionListener(this);
bp.add(b = new JRadioButton("Standard"));
b.addActionListener(this);
setLocation(200, 200);
setSize(400, 300);
setVisible(true);
}
public void actionPerformed(ActionEvent e) {
String label = ((JRadioButton) e.getSource()).getLabel();
bp.repaint();
if (label.equals("Rechteck")) {
v=1;
bp.repaint();
}
if (label.equals("Blue")) {
color = Color.blue;
bp.repaint();
}
Graphics g = getGraphics();
drawRects(g);
}
public void drawRects(Graphics g) {
Rectangle r;
Enumeration e;
g.clearRect(0, 0, getSize().width, getSize().height);
g.setColor(color);
for (e = rectList.elements(); e.hasMoreElements();) {
r = (Rectangle) e.nextElement();
g.drawRect(r.x, r.y, r.width, r.height);
}
if (currentRect != null && (currentRect.x > 0 || currentRect.y > 0)) {
g.drawRect(currentRect.x, currentRect.y, currentRect.width,
currentRect.height);
}
bp.repaint();
}
class MyMouseListener extends MouseAdapter {
public void mousePressed(MouseEvent event) {
bp.repaint();
if(v==1){
currentRect = new Rectangle(event.getX(), event.getY(), 0, 0);
}
}
public void mouseReleased(MouseEvent event) {
if(v==1){
if (currentRect.width > 0 || currentRect.height > 0) {
rectList.addElement(currentRect);
currentRect = null;
}
Graphics g = getGraphics();
drawRects(g);
}
bp.repaint();
}
}
class MyMouseMotionListener extends MouseMotionAdapter {
public void mouseDragged(MouseEvent event) {
if(v==1){
int x = event.getX();
int y = event.getY();
if (x > currentRect.x && y > currentRect.y) {
currentRect.width = x - currentRect.x;
currentRect.height = y - currentRect.y;
}
Graphics g = getGraphics();
drawRects(g);
}
}
}
class MyWindowListener extends WindowAdapter {
public void windowClosing(WindowEvent event) {
setVisible(false);
dispose();
System.exit(0);
}
}
}
when i run the application its look like this:
When i try to draw a rectangle , i can see when the Jpanel repaint it self.
how can i repaint the Jpanel and i cant see it, when it repaint it self.
thx a lot for your Help.
You have to write an extension of JPanel that overrides paint(Graphics g) or even better paintComponent(Graphics g). Under the overridden version of the method you will have to call your drawRects method.
See Custom Painting Approaches for examples of how to do custom painting using:
A List of objects to paint
a BufferedImage to paint the objects.
The examples will paint rectangles of different colors. So you will need to add code to paint different shapes. But the idea is to understand the basic painting concepts first.
For my assignment, I had to write a program that will either print some text, an oval, or a rectangle depending on which button is pressed at the top of the screen, however; when I press a button nothing happens, how would I fix this? This is my first GUI and I would appreciate any help! I'll end up needing the program to: start out with a rectangle, make whichever shape happens to be on screen stay in the center of the drawing area when the window gets resized, and my ovals and rectangles have to have half the width and height of the display area. I'm taking this one step at a time so I'll try to figure those out once I can actually get a shape on the screen, thanks :-).
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class firstGUI extends JFrame
implements ActionListener
{
private boolean showText = false;
private boolean showRect = false;
private boolean showOval = false;
private JButton text;
private JButton oval;
private JButton rectangle;
private JPanel buttonPanel;
public firstGUI()
{
super("First GUI");
setSize(512, 512);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(1,3));
text = new JButton("Text");
text.addActionListener(this);
buttonPanel.add(text);
oval = new JButton("Oval");
oval.addActionListener(this);
buttonPanel.add(oval);
rectangle = new JButton("Rectangle");
rectangle.addActionListener(this);
buttonPanel.add(rectangle);
//JComponent drawArea = new JComponent();
drawStuff d = new drawStuff();
Container contentPane = this.getContentPane();
contentPane.add(buttonPanel, BorderLayout.NORTH);
contentPane.add(d);
}
public void actionPerformed(ActionEvent event)
{
Object source = event.getSource();
if (source == text)
{
showText = true;
}
else if (source == oval)
{
showOval = true;
}
else if (source == rectangle)
{
showRect = true;
}
}
public void draw(Graphics g)
{
if(showText)
{
g.drawString("Hello", 0, 0);
}
else if (showOval)
{
g.drawOval(0, 0, 100, 100);
}
else if (showRect)
{
g.drawRect(0, 0, 100, 100);
}
}
public static void main(String [] args)
{
firstGUI myTest = new firstGUI();
myTest.setVisible(true);
}
}
class drawStuff extends JPanel
{
public void paint(Graphics g)
{
super.paint(g);
}
}
Try this. I added some repaint()s and helped you out with centering the objects being painted. I also changed the draw to paintComponent. This is what you should use when drawing on JComponents
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class firstGUI extends JFrame
implements ActionListener {
private boolean showText = false;
private boolean showRect = true;
private boolean showOval = false;
private JButton text;
private JButton oval;
private JButton rectangle;
private JPanel buttonPanel;
private DrawStuff drawPanel = new DrawStuff();
public firstGUI() {
super("First GUI");
setSize(512, 512);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(1, 3));
text = new JButton("Text");
text.addActionListener(this);
buttonPanel.add(text);
oval = new JButton("Oval");
oval.addActionListener(this);
buttonPanel.add(oval);
rectangle = new JButton("Rectangle");
rectangle.addActionListener(this);
buttonPanel.add(rectangle);
Container contentPane = this.getContentPane();
contentPane.add(buttonPanel, BorderLayout.NORTH);
add(drawPanel);
}
#Override
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if (source == text) {
showText = true;
repaint();
} else if (source == oval) {
showOval = true;
repaint();
} else if (source == rectangle) {
showRect = true;
repaint();
}
}
public static void main(String[] args) {
firstGUI myTest = new firstGUI();
myTest.setVisible(true);
}
class DrawStuff extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (showText) {
g.drawString("Hello", getHeight() / 2, getWidth() / 2);
showText = false;
} else if (showOval) {
g.drawOval(getWidth() / 4, getHeight() / 4, getWidth() / 2, getHeight() / 2);
showOval = false;
} else if (showRect) {
g.drawRect(getWidth() / 4, getHeight() / 4, getWidth() / 2, getHeight() / 2);
showRect = false;
}
}
}
}
You have all the building blocks, but after the button is pressed, the draw() method isn't called. Once you set your state (which item to draw) you need to re-draw()
Take a look at Performing Custom Painting.
Don't override paint but instead use paintComponent.
Take your draw method and move it to your drawStuff class. Call drawStuff from your paintComponent method
Set up some kind of flag (in drawStuff) that determines what should be painted
When you handle the button event, change the state flag on the panel and repaint the panel....
This will require your frame to have a reference to drawStuff
You may also want to take a look at and use Code Conventions for the Java Programming Language