Free Drawing inside JPanel - java

I am new to Java.
I want to create a program, in which i need to draw freely on JPanel by dragging the mouse. I go through the basics of paint function and able to achieve this.
public class DrawLine extends JPanel {
public void paint(Graphics g)
{
g.drawLine(0, 0, 50, 50);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run()
{
JFrame frame=new JFrame("Top Level Demo");
frame.setSize(300, 250);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel myPanel=new JPanel();
myPanel.setLayout(null);
frame.add(myPanel);
frame.add(new DrawLine());
frame.setVisible(true);
}});
}}
But this generates an out put like this where the straight line is determined by coordinates.
Please some one help me to implement free drawing inside JPanel.

Override paintComponent() rather than paint() method of JPanel.
Create list of Point to be used in the paintComponent().
Iterate the list in a loop and For each pair of points from the list call
g.drawLine(currentPoint.x,currentPoint.y, nextPoint.x,nextPoint.y);
Add drag listening to store drag points in the list.

Try to use MouseListener and paintComponent method.
Try next simple example for drawing your line.
public class Test extends JPanel{
public static int xS = 0;
public static int yS = 0;
public static int xF = 0;
public static int yF = 0;
public static void main(String[] args){
JFrame frame = new JFrame("Movement of 2d Shapes");
frame.setSize(400,400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Test t = new Test();
t.setOpaque(true);
t.addMouseListener(getMouseListener(t));
frame.getContentPane().add(t);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static MouseListener getMouseListener(final Test t) {
return new MouseAdapter() {
#Override
public void mousePressed(MouseEvent arg0) {
xS = arg0.getPoint().x;
yS = arg0.getPoint().y;
}
#Override
public void mouseReleased(MouseEvent arg0) {
xF = arg0.getPoint().x;
yF = arg0.getPoint().y;
t.repaint();
}
};
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawLine(xS,yS, xF, yF);
}
}

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DrawLine extends JFrame implements MouseMotionListener {
int x1,y1,x,y;
private boolean first = true;
public DrawLine() {
super("Top Level Demo");
setSize(300, 250);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setBackground(Color.white);
addMouseMotionListener(this);
}
#Override
public void mouseDragged(MouseEvent e) {
x =x1; y = y1;
x1 = e.getX();
y1 = e.getY();
if(first){
x = x1;
y = y1;
first = false;
}
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
}
public void paint(Graphics graphics){
graphics.drawLine(x, y, x1, y1);
}
public static void main(String[] args) {
new DrawLine();
}
}

Related

java gui paintComponent refresh

I am learning java gui interface and wrote a program that has a button. Each time the button is clicked, a random sized rectangle will be added to the screen. But instead of adding it to the screen, the program keeps erasing the old one, which I want to keep on the screen. Here is my code. I tried to do paint() and it did not work. Thanks in advance.
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class SimpleGui implements ActionListener {
JFrame frame = new JFrame();
public static void main(String[] args){
SimpleGui gui = new SimpleGui();
gui.go();
}
public void go(){
JButton button = new JButton("Add a rectangle");
MyDrawPanel panel = new MyDrawPanel();
button.addActionListener(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(BorderLayout.SOUTH, button);
frame.getContentPane().add(BorderLayout.CENTER, panel);
frame.setSize(300, 300);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent event){
frame.repaint();
}
class MyDrawPanel extends JPanel{
public void paintComponent(Graphics g){
g.setColor(Color.blue);
int height = (int) (Math.random()*120 + 10);
int width = (int) (Math.random()*120 + 10);
int x = (int) (Math.random()*40 + 10);
int y = (int) (Math.random()*40 + 10);
g.fillRect(x, y, height, width);
}
}
}
Your paintComponent method is written to draw only one rectangle, so its behavior should come as no shock to you. If you want it to draw multiple, you have one of two options:
Create an ArrayList<Rectangle>, and in the actionPerformed method, add a new random Rectangle to this List and then call repaint(). In the paintComponent method, iterate through this List with a for-loop, painting each Rectangle.
Or you could draw the new random rectangle onto a BufferedImage that is displayed by the paintComponent method.
The first method is the easier of the two, the 2nd is better if you're worried about program responsiveness, say in an animation program.
For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.*;
#SuppressWarnings("serial")
public class TwoDrawRectMethods extends JPanel {
// Array to hold our two drawing JPanels
private AddRandomRect[] addRandomRects = {
new DrawList("Using List"),
new DrawBufferedImage("Using BufferedImage")};
// constructor
public TwoDrawRectMethods() {
// add drawing rectangles onto GUI
for (AddRandomRect addRandomRect : addRandomRects) {
add(addRandomRect);
}
// button to tell rectangles to add a new Rectangle
add(new JButton(new DrawAction("Add New Rectangle")));
}
// The button's Action -- an ActionListener on "steroids"
private class DrawAction extends AbstractAction {
public DrawAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
// tell both drawing JPanels to add a new rectangle
for (AddRandomRect addRandomRect : addRandomRects) {
addRandomRect.addRectangle();
}
}
}
private static void createAndShowGui() {
TwoDrawRectMethods mainPanel = new TwoDrawRectMethods();
JFrame frame = new JFrame("TwoDrawRectMethods");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
#SuppressWarnings("serial")
class DrawList extends AddRandomRect {
private static final Color RECT_COLOR = Color.RED;
private List<Rectangle> rectList = new ArrayList<>();
public DrawList(String title) {
super(title);
}
#Override
public void addRectangle() {
rectList.add(createRandomRect());
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(RECT_COLOR);
for (Rectangle rectangle : rectList) {
g2.draw(rectangle);
}
}
}
#SuppressWarnings("serial")
class DrawBufferedImage extends AddRandomRect {
private static final Color RECT_COLOR = Color.BLUE;
private BufferedImage img = null;
public DrawBufferedImage(String title) {
super(title);
}
#Override
public void addRectangle() {
if (img == null) {
img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
}
Rectangle rect = createRandomRect();
Graphics2D g2 = img.createGraphics();
g2.setColor(RECT_COLOR);
g2.draw(rect);
g2.dispose();
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, null);
}
}
}
#SuppressWarnings("serial")
abstract class AddRandomRect extends JPanel {
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W;
private Random random = new Random();
public AddRandomRect(String title) {
setBorder(BorderFactory.createTitledBorder(title));
}
abstract void addRectangle();
protected Rectangle createRandomRect() {
int x1 = random.nextInt(PREF_W);
int x2 = random.nextInt(PREF_W);
int y1 = random.nextInt(PREF_H);
int y2 = random.nextInt(PREF_H);
int x = Math.min(x1, x2);
int y = Math.min(y1, y2);
int width = Math.abs(x1 - x2);
int height = Math.abs(y1 - y2);
return new Rectangle(x, y, width, height);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
}

I cannot draw objects and have them move on the screen

I can draw static things to the screen, but I want to make them move with user key input. I don't know what to do, I've been searching and searching and haven't come up with an answer yet. Please help!
package com.Game.game;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Game extends JFrame
{
final static int width = 500;
final static int height = 500;
public int x = 250;
public int y = 250;
public int changeX = 10;
public int changeY = 10;
public static void main(String[] args)
{
new Game();
}
public Game()
{
KeyListener listener = new KeyListening();
addKeyListener(listener);
setFocusable(true);
DrawingStuff drawingstuff = new DrawingStuff();
add(drawingstuff);
setSize(width, height);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public class DrawingStuff extends JPanel
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawString("Hey there!", 300, 300);
g.setColor(Color.RED);
g.fillRect(x, y, 50, 50);
}
}
public class KeyListening implements KeyListener
{
DrawingStuff drawingstuff = new DrawingStuff();
#Override
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_UP)
{
y = y + changeY;
System.out.println("Hey");
drawingstuff.repaint();
}
}
#Override
public void keyReleased(KeyEvent e)
{
}
#Override
public void keyTyped(KeyEvent e)
{
}
}
public void update()
{
}
}
EDIT: Fixed it. I took away the key listener stuff in the constructor method, added a command to focus on "drawingstuff" in the constructor method, and, most importantly, added this bit of code to the end of the constructor method:
while(true)
{
drawingstuff.repaint();
}
The problem is that your KeyListening object has a reference to a different DrawingStuff object than the one you added to your UI inside the Game constructor.
public class KeyListening implements KeyListener
{
DrawingStuff drawingstuff = new DrawingStuff();
...
You should pass a DrawingStuff reference to the KeyListening instance so that it can tell the right object to repaint itself.

Change the background color on a custom Button?

I want my button to change color on the mod == 0 of i % 3. The paintComponent(...) is called when the form is re-sized and index is passed in so I would think that this should change the color of my button ever time I start moving the form around the screen.
I have two components on the screen but both will not show up this might be a factor.
Code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class testform {
public static void main (String[] p) {
testBall3 j1 = new testBall3();
myButton b1 = new myButton("test");
JPanel testPane = new JPanel();
testPane.setBackground(Color.green);
testPane.setLayout(new BorderLayout());
j1.setPreferredSize(new Dimension(10,10));
//testPane.add(b1);
testPane.add(j1);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(testPane);
frame.pack();
frame.setSize(300, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
//j1.setColorBall(Color.BLACK);
//j1.repaint();
}
}
class myButton extends JButton {
private static final long serialVersionUID = 1L;
public myButton(String s) {
super(s);
}
public void setPrefferedSize(Dimension d) {
//this.setBounds(x, y, width, height)
setPreferredSize(d);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
index += i;
System.out.println(i);
if (index % 3 == 0) {
setBackground(Color.RED);
}
else {
setBackground(Color.BLACK);
}
}
}
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;
class testBall3 extends JComponent
{
private static final long serialVersionUID = 1L;
private Color colorBall = Color.red;
private int x1, y1;
int index = 0;
public void setColorBall(Color c)
{
this.colorBall = c;
}
public testBall3()
{
super();
System.out.println("MyBall (0)");
}
public testBall3(int x, int y, int diameter)
{
super();
this.setLocation(x, y);
this.setSize(diameter, diameter);
System.out.println("MyBall (1)");
x1 = x;
y1 = y;
}
public void paintBorder(Graphics g)
{
super.paintBorder(g);
g.setColor(Color.YELLOW);
g.fillOval(100, 100, 50, 50);
System.out.println("PaintBorder");
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(colorBall);
g.fillOval(x1, y1, 10, 10);
System.out.println("paintComponent");
}
public void paint(Graphics g)
{
super.paint(g);
paintComponent(g);
paintBorder(g);
paintChildren(g);
System.out.println("Paint");
}
}
But paintComponent doesn't take a second parameter, how are you passing it? I would think that instead of trying to pass i, you would want make i an attribute of class myButton instead and initialize it to 0 upon instantiation. That is, if you want each button to have its own counter. That sounds like the better plan.
You've got a lot of strange stuff going on...
You've got a component where you override all four major painting methods for no good reason.
In this component, your paint method override calls the super method, and calls the other 3 methods, which in essence will make those 3 methods be called twice.
You've got program logic (advancement of i) inside of your myButton's paintComponent method -- something that should never be done. You do not have full control over when or even if this method is called.
You are calling setBackground(...) from within paintComponent, something which shouldn't be done.
Your class names do not begin with an upper case letter, going against coding conventions, and potentially confusing anyone who tries to read your code.
If you want to change the state of a component on resize, use a ComponentListener.
e.g.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class Foo2 extends JPanel {
protected static final Color MAGIC_BACKGROUND = Color.red;
protected static final int MAGIC_NUMBER = 3;
private static final int TIMER_DELAY = 20;
private int index = 0;
private JButton myButton = new JButton("My Button");
protected int DELTA_SIZE = 2;
public Foo2() {
add(myButton);
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
index++;
if (index % MAGIC_NUMBER == 0) {
myButton.setBackground(MAGIC_BACKGROUND);
} else {
myButton.setBackground(null);
}
}
});
new Timer(TIMER_DELAY, new ActionListener() {
private Toolkit toolkit = Toolkit.getDefaultToolkit();
private int screenWidth = toolkit.getScreenSize().width;
private int screenHeight = toolkit.getScreenSize().height;
#Override
public void actionPerformed(ActionEvent e) {
if (getWidth() >= screenWidth || getHeight() >= screenHeight) {
((Timer)e.getSource()).stop();
} else {
int width = getWidth() + DELTA_SIZE;
int height = getHeight() + DELTA_SIZE;
setPreferredSize(new Dimension(width, height));
Window win = SwingUtilities.getWindowAncestor(Foo2.this);
win.pack();
win.setLocationRelativeTo(null);
}
}
}).start();
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Foo2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new Foo2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Window's content disappears when minimized

I have a simple class that draws a line when mouse dragging or a dot when mouse pressing(releasing).
When I minimize the application and then restore it, the content of the window disappears except the last dot (pixel). I understand that the method super.paint(g) repaints the background every time the window changes, but the result seems to be the same whether I use it or not. The difference between the two of them is that when I don't use it there's more than a pixel painted on the window, but not all my painting. How can I fix this?
Here is the class.
package painting;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;
class CustomCanvas extends Canvas{
Point oldLocation= new Point(10, 10);
Point location= new Point(10, 10);
Dimension dimension = new Dimension(2, 2);
CustomCanvas(Dimension dimension){
this.dimension = dimension;
this.init();
addListeners();
}
private void init(){
oldLocation= new Point(0, 0);
location= new Point(0, 0);
}
public void paintLine(){
if ((location.x!=oldLocation.x) || (location.y!=oldLocation.y)) {
repaint(location.x,location.y,1,1);
}
}
private void addListeners(){
addMouseListener(new MouseAdapter(){
#Override
public void mousePressed(MouseEvent me){
oldLocation = location;
location = new Point(me.getX(), me.getY());
paintLine();
}
#Override
public void mouseReleased(MouseEvent me){
oldLocation = location;
location = new Point(me.getX(), me.getY());
paintLine();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent me){
oldLocation = location;
location = new Point(me.getX(), me.getY());
paintLine();
}
});
}
#Override
public void paint(Graphics g){
super.paint(g);
g.setColor(Color.red);
g.drawLine(location.x, location.y, oldLocation.x, oldLocation.y);
}
#Override
public Dimension getMinimumSize() {
return dimension;
}
#Override
public Dimension getPreferredSize() {
return dimension;
}
}
class CustomFrame extends JPanel {
JPanel displayPanel = new JPanel(new BorderLayout());
CustomCanvas canvas = new CustomCanvas(new Dimension(200, 200));
public CustomFrame(String titlu) {
canvas.setBackground(Color.white);
displayPanel.add(canvas, BorderLayout.CENTER);
this.add(displayPanel);
}
}
public class CustomCanvasFrame {
public static void main(String args[]) {
CustomFrame panel = new CustomFrame("Test Paint");
JFrame f = new JFrame();
f.add(panel);
f.pack();
SwingConsole.run(f, 700, 700);
}
}
You are not storing the state of the points you are drawing. When the panel is repainted, it only has information for the last point it drew.
Response to comment:
You would need to have a collection of Points, for instance ArrayList<Point> location = new ArrayList<Point>();
Then, in your listeners: location.add(new Point(me.getX(), me.getY()));
Finally, in paintLine():
for (Point location : locations) {
repaint(location.x,location.y,1,1);
}
The collection locations is usually referred to as a Display List. Most graphics programs use them.
Response to comment:
Yes, I expect so. I just tossed off an idea based on your code to give you a starting point. It is almost certainly a bad idea to do exactly as I have described.
Doesn't that mean I will draw all the points(instead of one) everytime I press or drag the mouse?
Yes, but #Dave's approach is perfectly satisfactory for thousands of nodes, as may be seen in GraphPanel. Beyond that, consider the flyweight pattern, as used by JTable renderers and illustrated here.
Addendum: Focusing on your AWTPainting questions, the variation below may illustrate the difference between System- and App-triggered Painting. As the mouse is dragged, repaint() invokes update(), which calls paint(); this is app-triggered. As you resize the window, only paint() is called (no red numbers are drawn); this is system-triggered. Note that there is a flicker when the mouse is released after resizing.
Flickering typically occurs when the entire component's background is cleared and redrawn:
4. If the component did not override update(), the default implementation of update() clears the component's background (if it's not a lightweight component) and simply calls paint().
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Panel;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;
public class AWTPainting {
public static void main(String args[]) {
CustomPanel panel = new CustomPanel();
Frame f = new Frame();
f.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.add(panel);
f.pack();
f.setVisible(true);
}
}
class CustomPanel extends Panel {
public CustomPanel() {
this.add(new CustomCanvas(new Dimension(320, 240)));
}
}
class CustomCanvas extends Canvas {
private MouseAdapter handler = new MouseHandler();
private List<Point> locations = new ArrayList<Point>();
private Point sentinel = new Point();
private Dimension dimension;
CustomCanvas(Dimension dimension) {
this.dimension = dimension;
this.setBackground(Color.white);
this.addMouseListener(handler);
this.addMouseMotionListener(handler);
this.locations.add(sentinel);
}
#Override
public void paint(Graphics g) {
g.setColor(Color.blue);
Point p1 = locations.get(0);
for (Point p2 : locations.subList(1, locations.size())) {
g.drawLine(p1.x, p1.y, p2.x, p2.y);
p1 = p2;
}
}
#Override
public void update(Graphics g) {
paint(g);
g.clearRect(0, getHeight() - 24, 50, 20); // to background
g.setColor(Color.red);
g.drawString(String.valueOf(locations.size()), 8, getHeight() - 8);
}
private class MouseHandler extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
if (locations.get(0) == sentinel) { // reference identity
locations.set(0, new Point(e.getX(), e.getY()));
}
}
#Override
public void mouseDragged(MouseEvent e) {
locations.add(new Point(e.getX(), e.getY()));
repaint();
}
}
#Override
public Dimension getPreferredSize() {
return dimension;
}
}
#Andrew, #Dave, #trashgod Hi,
I did some research on this and, finally, this is what I've got. Please correct me if I'm wrong. You cannot override paint() so you call repaint() everytime you need to do app-triggered painting.
Repaint() calls update() which its default behavior is to call paint().
update() is used for incremental painting; that explains the flickering screen when paint() was doing all the work, which practically means it was painting the whole image at every step.
However, my question is if I add "locationsAdded = 0" in the update method that means everytime I drag the mouse I paint the whole image(like in paint), so why doesn't it blink like before?
I've also read something about painting in swing and I didn't understand why update() is never invoked for swing. Can you explain me why?
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
class CustomCanvas extends Canvas{
ArrayList<Point> locations;
int locationsAdded;
Point oldLocation;
Point location;
Dimension dimension;
CustomCanvas(Dimension dimension){
locations = new ArrayList<>();
this.dimension = dimension;
this.init();
addListeners();
}
private void init(){
oldLocation= new Point(0, 0);
location= new Point(0, 0);
}
public void paintLine(Graphics g, int x){
Point p1 = (Point)locations.get(x);
Point p2 = (Point)locations.get(x+1);
g.drawLine(p1.x, p1.y, p2.x, p2.y);
locationsAdded++;
}
#Override
public void paint(Graphics g){
locationsAdded = 0;
g.setColor(Color.red);
for(int i = locationsAdded; i < locations.size()-1; i++){
paintLine(g, i);
}
}
public void update(Graphics g) {
//locationsAdded = 0;
for (int i = locationsAdded; i < locations.size()-1; i++) {
paintLine(g, i);
}
}
private void addListeners(){
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent me){
oldLocation = location;
location = new Point(me.getX(), me.getY());
locations.add(location);
repaint();
}
});
}
#Override
public Dimension getMinimumSize() {
return dimension;
}
#Override
public Dimension getPreferredSize() {
return dimension;
}
}
class CustomFrame extends Panel {
Panel displayPanel = new Panel(new BorderLayout());
CustomCanvas canvas = new CustomCanvas(new Dimension(700, 700));
public CustomFrame(String titlu) {
canvas.setBackground(Color.white);
displayPanel.add(canvas, BorderLayout.CENTER);
this.add(displayPanel);
}
}
public class AWTPainting {
public static void main(String args[]) {
CustomFrame panel = new CustomFrame("Test Paint");
Frame f = new Frame();
f.add(panel);
f.pack();
f.setSize(700,700);
f.show();
}
}
set your layout to Null layout

How to add new Graphic element to JPanel and use its link to change its position in loop?

I need only one ring to be created on MyPanel (extends JPanel) initialization. Then I need to change (in a loop iterate() ) position of ring on MyPanel. How and what to add to this code?
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;
public class mull {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JPanel p = createAndShowGUI();
iterate(p);
// "The method iterate(MyPanel) in the type mull is not applicable for the arguments (JPanel)"
}
});
}
private static JPanel createAndShowGUI() {
System.out.println("Created GUI on EDT? "+
SwingUtilities.isEventDispatchThread());
JFrame f = new JFrame("Swing Paint Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// how to grab link to this panel - in order to use it in iteration loop ?
MyPanel p = new MyPanel();
f.add(p);
// f.add(new MyPanel());
f.pack();
f.setVisible(true);
return p;
}
private static void iterate(JPanel p){
// the loop should change square position on each iteration
// how to implement ?
for (int i = 0; i < 999; i++){
((MyPanel) p).moveSquare(100 + i*10, 200 + i*10); // here is problem:
//"Cannot make a static reference to the non-static method moveSquare(int, int) from the type MyPanel"
}
}
}
class MyPanel extends JPanel {
private int squareX = 50;
private int squareY = 50;
private int squareW = 200;
private int squareH = 200;
public MyPanel() {
setBorder(BorderFactory.createLineBorder(Color.black));
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
moveSquare(e.getX(),e.getY());
}
});
addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e) {
moveSquare(e.getX(),e.getY());
}
});
}
// originally this method was private - in orger to access it within mull, it vas changed to public
public void moveSquare(int x, int y) {
int OFFSET = 1;
if ((squareX!=x) || (squareY!=y)) {
repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
squareX=x;
squareY=y;
repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
}
}
public Dimension getPreferredSize() {
return new Dimension(900,700);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("This is my custom Panel!",10,20);
g.setColor(Color.RED);
g.fillRect(squareX,squareY,squareW,squareH);
g.setColor(Color.BLACK);
g.drawRect(squareX,squareY,squareW,squareH);
}
}

Categories