adding to arraylist with different graphics object - java

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.

Related

Whole Colors change when I change Colors in my Java Paint Program

I created a program in Java using JPanel and Graphics. This is simple Paint Panel program in which things draw when we drag mouse and when we want to make line with different color simply just press the button in a panel but the problem is that when I press a button in panel and drag the mouse whole components present in a panel turns into that color (Button' Color).
Code:
public class PaintAssign extends JPanel {
private ArrayList<Point> points= new ArrayList<>();
private ArrayList<Point> points2= new ArrayList<>();
public final JButton[] panelButton=new JButton[5];
public String[] colors={"RED","BLUE","GREEN","YELLOW","CYAN"};
int x=0;
public PaintAssign()
{ addMouseMotionListener(
new MouseMotionAdapter(){
#Override
public void mouseDragged(MouseEvent e)
{
points.add(e.getPoint());
repaint();
}
});
addMouseListener(
new MouseAdapter(){
});
for (int i = 0; i < 5; i++) {
Rectangle r = new Rectangle(22, 22);
panelButton[i] = new JButton();
panelButton[i].setText(colors[i]);
panelButton[i].setOpaque(true);
panelButton[i].setBounds(r);
this.add(panelButton[i]);
this.setVisible(true);
}
mouseAction handle=new mouseAction();
panelButton[0].addActionListener(handle);
panelButton[1].addActionListener(handle);
panelButton[2].addActionListener(handle);
panelButton[3].addActionListener(handle);
panelButton[4].addActionListener(handle);
}
private class mouseAction implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==panelButton[0])
{
x=1;
}
else if(e.getSource()==panelButton[1])
{
x=2;
}
else if(e.getSource()==panelButton[2])
{
x=3;
}
else if(e.getSource()==panelButton[3])
{
x=4;
}
else if(e.getSource()==panelButton[4])
{
x=5;
}
}
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if(x==0)
{
g.setColor(Color.BLACK);
}
else if(x==1)
{
g.setColor(Color.RED);
}
else if(x==2)
{
g.setColor(Color.BLUE);
}
else if(x==3)
{
g.setColor(Color.GREEN);
}
else if(x==4)
{
g.setColor(Color.YELLOW);
}else if(x==5)
{
g.setColor(Color.CYAN);
}
for(Point i:points)
{
g.fillOval(i.x,i.y,15,15);
}
}
The paintComponent method is called everytime the panel redraw itself and that happens quite often. Then when you set the color, all the points will be redrawn with the new color.
To avoid this behavior you must save not only the coordinates of your points but also their color.
public class PaintAssign extends JPanel {
private ArrayList<Point> points= new ArrayList<>();
private ArrayList<Color> colors = new ArrayList<>();
//....
public PaintAssign(){
addMouseMotionListener(new MouseMotionAdapter(){
#Override
public void mouseDragged(MouseEvent e) {
points.add(e.getPoint());
if(x==0) {
colors.add(Color.BLACK);
} else if(x==1) {
colors.add(Color.RED);
} else if(x==2) {
colors.add(Color.BLUE);
} else if(x==3) {
colors.add(Color.GREEN);
} else if(x==4) {
colors.add(Color.YELLOW);
}else if(x==5) {
colors.add(Color.CYAN);
}
repaint();
}
});
// ...
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < points.size(); i++) {
g.setColor(colors.get(i));
g.fillOval(points.get(i).x, points.get(i).y, 15, 15);
}
}
}
Consider creating a new class Point containing the coordinates and the color of the point.
You didn' provide the repaint() method, but my guess is, since you record all your points to the same list, all points are redrawn in the same color. What you need are separate lists for every component you draw, managed in a way that you can access that list when the component is selected.
I'm not sure if I understood your problem correctly though, maybe you could provide more details.

Trouble With Color Changing In My Java Swing Paint Application

Should I still be practicing Java Swing?
I'm trying to add functionality to my Java Swing Paint Application by adding a choice to change brush colors. However, when I'm finished choosing a different color in the color chooser, all of the old marks change into that chosen color along with my new line marks. I wanted the old marks to stay the same color as before.
(Pictures below)
Using black ink. Drawing something.
Deciding to change the color to green
Both the old AND new lines change to green.
This is not the entire application(tell me if you need the rest), but I believe the problem has something to do with incorrect table manipulation. The "shapeFill" table which matches colors to the lines("shapes" table) is not working correctly.
public class TestPane extends JComponent{
private List<List<Point>> points;
private ArrayList<Shape> shapes = new ArrayList<Shape>();
public TestPane() {
points = new ArrayList<>(100);
MouseAdapter ma = new MouseAdapter() {
private List<Point> currentPath;
#Override
public void mousePressed(MouseEvent e) {
currentPath = new ArrayList<>(100);
currentPath.add(e.getPoint());
points.add(currentPath);
}
#Override
public void mouseDragged(MouseEvent e) {
Point dragPoint = e.getPoint();
currentPath.add(dragPoint);
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
currentPath = null;
}
};
addMouseListener(ma);
addMouseMotionListener(ma);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Iterator<Color> fillCounter = shapeFill.iterator();
for(Shape s : shapes) { // I believe problem is somewhere around here?
g2d.setPaint(fillCounter.next());
g2d.setStroke(new java.awt.BasicStroke(10));
}
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (List<Point> path : points) {
Point from = null;
for (Point p : path) {
if (from != null) {
Shape line = new Line2D.Float(from.x, from.y, p.x, p.y);
g2d.draw(line);
shapes.add(line);
shapeFill.add(lineColor);
}
from = p;
}
}
g2d.dispose();
}
}
public JButton createButton(String title) {
JButton button = new JButton(title);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == colorChooser) {
Color chooser = JColorChooser.showDialog(null, "Select color", lineColor);
lineColor = chooser;
shapeFill.add(chooser);
repaint();
}else if(e.getSource() == shapeFillArrayList) {
System.out.print("\n");
for(Color index : shapeFill) {
System.out.println(index);
}
}
}
});
return button;
}

Drawing multiple shapes by combobox<Shape>

I am having an issue when repainting and keeping all drawn objects on the screen. Basically from my knowledge of Java (Isn't much) is that every time I repaint I am basically calling the draw method of the same object hence therefore just repainting the same object instead of a new object. On mouseRelease I am adding the shape to a list. Every element reference I assume refers to the same shape in memory and therefore calling the same draw method. How would you solve this but still keep the comboBox object oriented? I would prefer not to use strings and a switch case or else if logic.
The draw method which is same for oval and rectangle except the last line.
#Override
public void draw(Graphics context)
{
Point startingPoint = super.getStartingPoint();
Point endingPoint = super.getEndingPoint();
int minX = Math.min(endingPoint.x, startingPoint.x);
int minY = Math.min(endingPoint.y, startingPoint.y);
int maxX = Math.max(endingPoint.x, startingPoint.x);
int maxY = Math.max(endingPoint.y, startingPoint.y);
context.drawOval(minX, minY, maxX - minX, maxY - minY);
}
The JPanel which has the components and the drawing.
public class ShapeMakerPanel
extends JPanel
{
private JPanel controls;
private JPanel currentColor;
private JComboBox<Shape> shapeChoice;
private JCheckBox filled;
private JButton undo;
private JButton clear;
private List<Shape> list;
public ShapeMakerPanel()
{
//Initialize Objects
controls = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
currentColor = new JPanel();
shapeChoice = new JComboBox<Shape>();
undo = new JButton("Undo");
clear = new JButton("Clear");
filled = new JCheckBox("Filled");
list = new ArrayList<Shape>();
//Set object names
controls.setName("controls");
currentColor.setName("currentColor");
undo.setName("undo");
clear.setName("clear");
shapeChoice.setName("shapeChoice");
//Set JPanel current color to black and size it...will add jcolorchooser
currentColor.setBackground(Color.BLACK);
currentColor.setPreferredSize(new Dimension(25, 25));
/*
* Add items to comboBox, subclasses of type shape
*/
shapeChoice.addItem(new Rectangle());
shapeChoice.addItem(new Oval());
//Add components to the controls panel
controls.add(shapeChoice);
controls.add(currentColor);
controls.add(filled);
controls.add(undo);
controls.add(clear);
//Add listeners, settings and components to main panel for frame
addMouseListener(new ShapePanelMouseListener());
addMouseMotionListener(new ShapePanelMouseListener());
setBackground(Color.WHITE);
add(controls);
}
public List<Shape> getShapes()
{
return list;
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g.create();
if (!list.isEmpty())
{
for (Shape s : list) {
g2d.setColor(currentColor.getBackground());
s.draw(g2d);
}
}
g2d.dispose();
}
private class ShapePanelMouseListener
extends MouseAdapter
{
private Shape shape;
private ShapePanelMouseListener()
{
shape = (Shape)shapeChoice.getSelectedItem();
}
#Override
public void mousePressed(MouseEvent e)
{
shape = (Shape)shapeChoice.getSelectedItem();
shape.setStartingPoint(e.getPoint());
}
#Override
public void mouseDragged(MouseEvent e)
{
shape = (Shape)shapeChoice.getSelectedItem();
shape.setEndingPoint(e.getPoint());
repaint();
}
#Override
public void mouseReleased(MouseEvent e)
{
list.add(shape);
System.out.println(list.size());
}
}

Passing Data between Java Classes

I'm having trouble retrieving the variable from my Colour class after i send the index from the GUI after selecting a colour from the drop down list. I can send the index fine and retrieve it from the HashMap, i know this because i use System.out.println to check. Basically my questions are, where have i gone wrong? and What do i need to remember to make sure i don't have this trouble again? Edit: forgot to mention, the button sending the index is in a seperate JPanel which is used for the UI components(buttons and combo boxes).
//edit
class UIPanel extends JPanel{
public MainPanel gpanel;
public Integer data;
public Color colval;
public Colour col;
public UIPanel(MainPanel panel) {
col = new Colour();
gpanel = panel;
Box btnBox = Box.createHorizontalBox();
btnBox.add(setBtn = new JButton());
btnBox.add(Box.createHorizontalGlue());
JButton setBtn = new JButton("Set");
final DefaultComboBoxModel colour = new DefaultComboBoxModel();
colour.addElement("Red");
final JComboBox colours = new JComboBox(colour);
JScrollPane colourScroll = new JScrollPane(colours);
btnBox.setSize(300, 100);
btnBox.add(Box.createHorizontalGlue());
add(btnBox, BorderLayout.NORTH);
//end of edit
Button to send Index from GUI class to Colour class
setBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
data= colours.getSelectedIndex();
col.setCol(data);
}
});
Colour Class where hashmap with the list of colours in.
public class Colour{
public Color colVal;
HashMap<Integer, Color> map = new HashMap<Integer, Color>();
public Colour() {
map.put(0, Color.RED);
map.put(1, Color.BLUE);
map.put(2, Color.YELLOW);
map.put(3, Color.GREEN);
}
public Color setCol(Integer data) {
//Color colours;
colVal = map.get(data);
System.out.println("colour" + colVal);
return colVal;
}
public Color getColVal() {
return colVal;
}
And the paint area on the GUI class where the colour will be sent to from the colour class
class MainPanel extends JPanel{
//private Colour col;
int px, py;
//radius
public Color colvals;
public Colour col;
public MainPanel() {
col = new Colour();
this.addMouseMotionListener(new MouseMotionAdapter() {
// store drag coordinates and repaint
public void mouseDragged( MouseEvent event )
{
px = event.getX();
py = event.getY();
repaint();
}
}); // end call to addMouseMotionListener
}
public void paint( Graphics g ) {
g.setColor(col.colVal);//This is where the colour value will be placed
System.out.println(col.colVal);
g.fillOval( px, py, 15, 15 );
}
}
I'm Probably missing something stupid out but I cant seem to figure it out.
P.S: How complicated will it be to make a Vignere Cipher Application?
JComboBox can be used to directly use any Objects as items with only one little thing to consider: It will use the toString for the label to display. (see JComboBox javadoc - Providing a Custom Renderer).
But instead of using a custom renderer I always preferred to write a very simple helper class once - let's call it ComboBoxItem - that is reusable for any kind of data.
public class ComboBoxItem<T>
{
private T value;
private String label;
public ComboBoxItem(T value, String label)
{
this.value = value;
this.label = label;
}
public T getValue()
{
return this.value;
}
public String getLabel()
{
return this.label;
}
// important! since this is the workaround ;-)
public String toString()
{
return this.label; // or whatever you like
}
}
And then populate the JComboBox with ComboBoxItems instead of String values:
In your code instead of
final DefaultComboBoxModel colour = new DefaultComboBoxModel();
colour.addElement("Red");
colour.addElement("Blue");
colour.addElement("Yellow");
colour.addElement("Green");
colours = new JComboBox(colourValues);
... you will use
final DefaultComboBoxModel colour = new DefaultComboBoxModel();
colour.addElement(new ComboBoxItem<Color>(Color.RED, "Red"));
colour.addElement(new ComboBoxItem<Color>(Color.BLUE, "Blue"));
colour.addElement(new ComboBoxItem<Color>(Color.YELLOW, "Yellow"));
colour.addElement(new ComboBoxItem<Color>(Color.GREEN, "Green"));
colours = new JComboBox(colourValues);
This will make the select contain ComboBoxItems as values which you can simply access by doing the following:
// instead of getSelectedIndex()
ComboBoxItem<Color> item = (ComboBoxItem) colours.getSelectedItem();
Color c = item.getValue();
The same procedure can then be reused for any other kind of values - even complex ones.
Note: If you have a data object with an appropriate toString() representation anyway, you can of course simply use it as a value for the select.
Note2: If a string representation is not enough (e.g. you want to display the color along with the name), have a look at ListCellRenderer which is able to display the item in any desired way (by returning an arbitrary JComponent).
Your setCol(...) method inside of the Colour class should be getCol(...) since it's functioning as a getter:
public class Colour{
public Color colVal;
HashMap<Integer, Color> map = new HashMap<Integer, Color>();
public Colour() {
map.put(0, Color.RED);
map.put(1, Color.BLUE);
map.put(2, Color.YELLOW);
map.put(3, Color.GREEN);
}
// **** change name ****
public Color getCol(Integer data) {
//Color colours;
colVal = map.get(data);
System.out.println("colour" + colVal);
return colVal;
}
// **** not sure you need this method
public Color getColVal() {
return colVal;
}
and in your ActionListener, you retrieve the color but never do anything with it. It should be:
public void actionPerformed(ActionEvent e) {
data = colours.getSelectedIndex();
Color color = col.getCol(data); // note name change
// use Color variable, color, somehow here
mainPanel.setColVals(color); // something like this perhaps
mainPanel.repaint(); // to tell the JVM to repaint the JPanel
}
Also note that in your JPanel class override you should override the paintComponent method, not the paint method, and don't forget to call the super's method.
i.e.,
public void setColVals(Color colVals) {
this.colVals = colVals;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(colVal);
// System.out.println(colVal);
g.fillOval( px, py, 15, 15 );
}
Edit a better answer:
Get rid of Colour entirely.
Use an enum to match your Color to a String and create a JComboBox model out of that enum.
Using an enum will prevent you're having to use magic numbers with the risk that the wrong number has been used, a number that doesn't match a color.
Also, by using an enum, it is trivial to change your code and add more colors. Just add a new item to the enum, and the rest of the program will adapt to the change.
Add a PropertyChangeListener from the MainPanel to the UIPanel and listen for changes to its "bound" Color property.
Use RenderingHints with a Graphics2D object to smooth out the jaggies from your circle drawing.
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
public class ColorListenerPanel extends JPanel {
public ColorListenerPanel() {
UIPanel uiPanel = new UIPanel();
MainPanel mainPanel = new MainPanel(uiPanel);
setLayout(new BorderLayout());
add(mainPanel, BorderLayout.CENTER);
add(uiPanel, BorderLayout.PAGE_START);
}
private static void createAndShowGui() {
ColorListenerPanel mainPanel = new ColorListenerPanel();
JFrame frame = new JFrame("ColorListenerPanel");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class MainPanel extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 650;
private static final int OVAL_WIDTH = 16;
private int px, py;
private Color color = MyColors.values()[0].getColor();
public MainPanel(UIPanel uiPanel) {
this.addMouseMotionListener(new MouseMotionAdapter() {
// store drag coordinates and repaint
public void mouseDragged(MouseEvent event) {
px = event.getX();
py = event.getY();
repaint();
}
});
uiPanel.addPropertyChangeListener(UIPanel.COLOR, new UiListener());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(color);
g.fillOval(px - OVAL_WIDTH / 2, py - OVAL_WIDTH / 2, OVAL_WIDTH, OVAL_WIDTH);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class UiListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent pcEvt) {
// not really needed since our listener is added using
// this property name
if (!UIPanel.COLOR.equals(pcEvt.getPropertyName())) {
return;
}
color = (Color) pcEvt.getNewValue();
repaint();
}
}
}
enum MyColors {
RED("Red", Color.RED),
BLUE("Blue", Color.BLUE),
YELLOW("Yellow", Color.YELLOW),
GREEN("Green", Color.GREEN);
private String name;
private Color color;
private MyColors(String name, Color color) {
this.name = name;
this.color = color;
}
public String getName() {
return name;
}
public Color getColor() {
return color;
}
#Override
public String toString() {
return name;
}
}
class UIPanel extends JPanel {
public static final String COLOR = "color";
private MainPanel gpanel;
private Integer data;
private Color color;
private DefaultComboBoxModel<MyColors> comboModel = new DefaultComboBoxModel<>();
private JComboBox<MyColors> colorsCombo = new JComboBox<>(comboModel);
SetColorAction setColorAction = new SetColorAction("Set", KeyEvent.VK_S);
public UIPanel() {
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
add(colorsCombo);
add(Box.createHorizontalStrut(5));
add(new JButton(setColorAction));
colorsCombo.addActionListener(setColorAction);
add(Box.createHorizontalGlue());
for (MyColors myColor : MyColors.values()) {
comboModel.addElement(myColor);
}
}
public void setColor(Color color) {
Color oldValue = this.color;
Color newValue = color;
this.color = color;
firePropertyChange(COLOR, oldValue, newValue);
}
private class SetColorAction extends AbstractAction {
public SetColorAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent evt) {
MyColors selection = (MyColors) colorsCombo.getSelectedItem();
if (selection != null) {
setColor(selection.getColor());
}
}
}
}
In this Function
public void paint( Graphics g ) {
g.setColor(col.colVal);//This is where the colour value will be placed
System.out.println(col.colVal);
g.fillOval( px, py, 15, 15 );
}
You are using g.setColor(col.colVal); col.colVal will give you the default value assigned to it probably null ,You should use col.getColVal() as this is the getter method you have created for the colVal attribute.
And also in the setter declaration public Color setCol(Integer data) the return type you are using is Color but when you are using this function in your GUI class without a Color variable which can accept a Value returned by your setter .
I don't understand the need of returning values from a Setter method.

How to use Canvas to draw multiple rectangles based on user input?

So basically I'm writing a program where the user clicks and drags the mouse to a size he/she wants, and lets go, filling in a rectangle based on the choice from the JComboBox.
What I have implemented is MouseListener and MouseMotionListener to track the location of the mouse, and draw a rectangle based on where the user first clicked, to where it was let go.
When the user clicks and drags (but does not let go), there is a drawRect() but not a fillRect() (as in, the rectangle does not fill - only when the user releases the mouse does the rectangle fill with the color).
This class creates a Rect object that has another part in the constructor, which is the color that is selected (which is determined in the ColorListener class below).
This is where I included my instance variables, and everything is instantiated in the constructor below:
private ArrayList<Rect> rectList;
private Color currentColor;
private Canvas canvas;
private JPanel controlPanel;
private JButton undo, erase;
private JComboBox comboBox;
private int xStart, yStart, xEnd, yEnd;
private Graphics page;
private Point pt = null;
private PointListener pointListener;
private ColorListener colorListener;
public WholePanel()
{
// here we use black to draw a rectangle
currentColor = Color.black;
pointListener = new PointListener();
addMouseListener(pointListener);
addMouseMotionListener(pointListener);
String[] listOfColors = {"black", "red", "blue", "green", "orange"};
comboBox = new JComboBox(listOfColors);
comboBox.setSelectedIndex(0);
rectList = new ArrayList<Rect>();
controlPanel = new JPanel(new GridLayout(1,3));
undo = new JButton("Undo");
erase = new JButton("Erase");
controlPanel.add(comboBox);
controlPanel.add(undo);
controlPanel.add(erase);
undo.addActionListener(new ButtonListener());
erase.addActionListener(new ButtonListener());
canvas = new Canvas();
JSplitPane sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, controlPanel, canvas);
setLayout(new BorderLayout());
add(sp);
}
The Rect class can create a Rect object used later.
public class Rect
{
private int x1, y1, width1, height1;
private Color color1;
public Rect(int x, int y, int width, int height, Color color)
{
x1 = x;
y1 = y;
width1 = width;
height1 = height;
color1 = color;
}
public void draw(Graphics page)
{
page.setColor(color1);
page.drawRect(x1,y1,width1,height1);
}
}
The Canvas class creates the space that allows for drawing of an object.
private class Canvas extends JPanel
{
public void paintComponent(Graphics page)
{
super.paintComponent(page);
setBackground(Color.white);
if (pt != null)
{
Rect rect = new Rect(xStart, yStart, xEnd-xStart, yEnd-yStart, currentColor);
rect.draw(page);
}
}
}
The PointListener class finds all the points that are there, as in where the user clicks, to where the user drags, and also to where the user releases.
private class PointListener implements MouseListener, MouseMotionListener
{
public void mousePressed(MouseEvent event)
{
pt = event.getPoint();
xStart = pt.x;
yStart = pt.y;
}
public void mouseReleased(MouseEvent event)
{
pt = event.getPoint();
if (pt != null)
{
xEnd = pt.x;
yEnd = pt.y;
page.fillRect(xStart, yStart, xEnd-xStart, yEnd-yStart);
}
}
public void mouseClicked(MouseEvent event) {}
public void mouseEntered(MouseEvent event) {}
public void mouseExited(MouseEvent event) {}
public void mouseDragged(MouseEvent event)
{
pt = event.getPoint();
if (pt != null)
{
xEnd = pt.x;
yEnd = pt.y;
Rect rect = new Rect(xStart, yStart, xEnd-xStart, yEnd-yStart, currentColor);
rect.draw(page);
}
repaint();
}
public void mouseMoved(MouseEvent event) {}
}
ColorListener finds the type of object that is selected in the JComboBox determined in the main() method, and sets the currentColor to it (it is put back as the color in the Rect constructor above).
private class ColorListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
if (event.getSource().equals("black"))
{
currentColor = Color.black;
comboBox.setSelectedIndex(0);
}
else if (event.getSource().equals("red"))
{
currentColor = Color.red;
comboBox.setSelectedIndex(1);
}
else if (event.getSource().equals("blue"))
{
currentColor = Color.blue;
comboBox.setSelectedIndex(2);
}
else if (event.getSource().equals("green"))
{
currentColor = Color.green;
comboBox.setSelectedIndex(3);
}
else if (event.getSource().equals("orange"))
{
currentColor = Color.orange;
comboBox.setSelectedIndex(4);
}
}
}
So what I am having trouble with is being able to draw it. I don't see any flaws in logic in the program so far above, and nothing is being able to be drawn onto the Canvas (don't worry about the JButtons Undo and Erase, as they are easy to work with with an ArrayList and remove() and clear() and things like that).
Your program should have no Graphics field that is a class field (your page class field). I'm surprised your not seeing a NullPointException with the way you're attempting to use it above in say your Mouse Listener class:
public void mouseReleased(MouseEvent event)
{
pt = event.getPoint();
if (pt != null)
{
xEnd = pt.x;
yEnd = pt.y;
// !!!! don't do this !!!!
page.fillRect(xStart, yStart, xEnd-xStart, yEnd-yStart);
}
}
Instead the Graphics object should only be obtained from the JVM, should only exist within the paintComponent method and should only be used within the same paintComponent method (exceptions being any methods called from with paintComponent that are passed this object and of course a Graphics object obtained from a BufferedImage). The MouseListener/MouseMotionListener should fill in your x-start, y-start, x-end, and y-end variables during mouseDragged, and then on mouseRelease these variables should be used to create a new Rect object that is placed in the rectList, and then repaint called.
Then paintComponent should iterate through rectList, filling each Rect object it finds there.

Categories

Resources