-1

I have an informatic project with JAVA langage for class and it's rated to graduate from high school.

Btw my program consists in drawing geometrical forms in the JPanel with clic control but I don't know how to put, in my main program, fonctions which draw figures as I want like drawSquare(x,y,length). For the moment the program show this window (it's a JFrame with my JPanel inside):

https://i.stack.imgur.com/ayZv2.png

I have a method readClick() which give to a Point point the coordinates point.x and point.y in the frame but I don't know how, in my main, I can do to call a graphical drawing. "My problem is that I want to put in my main program something like

Point clic; 
clic= Fenetre.readClick() ; // I have this method which wait me to clic on the frame  
x = clic.x ;    //and give to point the coordonates 
y= clic.y;    // point.x && point.y
clic = Fenetre.readClick();
a = clic.x ;
b = clic.y ;
"Function which draws rectangle for example"(x,y,a,b);
//It's this fonction I want to create and
// I want it to draw the rectangle in the JPanel 

But I don't know how to make the function which adds a drawing in the JPanel "

My main program :

public class Geogebra  {
   @SuppressWarnings("unused")
     public static void main(String args[]){
    Fenetre fen = new Fenetre();
     }}

My window class :

import java.awt.Color;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.concurrent.SynchronousQueue;
import javax.swing.JFrame;

@SuppressWarnings({ "unused", "serial" })
public class Fenetre extends JFrame {

static Panneau component = null;
private final static SynchronousQueue<MouseEvent> clicks = new SynchronousQueue<MouseEvent>();
public Fenetre(){
    JFrame frame = new JFrame();
      component = new Panneau();    
    frame.setTitle("ISNOGEBRA");
    frame.setSize(900, 700); // Taille initiale de la fenetre : 900 * 700
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
    frame.setContentPane(component);
    frame.setVisible(true);   
    component.addMouseListener( new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            clicks.offer(e);
        }
    });


}
public static MouseEvent readMouse() {
    try {
    return clicks.take();
    }
    catch (InterruptedException e) {
    throw new AssertionError();
    }
    }
 public static Point readClick() {
        return readMouse().getPoint();
        }

}

My JPanel class (the two class Mathwrapper and Menu just draw the interface, I'll show them if needed but it's really long) :

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.concurrent.ConcurrentLinkedQueue;
import javax.swing.JPanel;

@SuppressWarnings({ "serial", "unused" })
public class Panneau extends JPanel implements MouseListener {
Menu menu;
MathWrapper mw;

public Panneau(){
    super();
    this.setBackground(Color.WHITE);
    menu = new Menu(20, 20);
    mw = MathWrapper.getInstance(0, 80);
    this.setOpaque(true);
    this.addMouseListener(this);        
}


@Override 
public void paintComponent(Graphics g){
    menu.draw(g);
    mw.draw(g);
    }

public void mouseClicked(MouseEvent e) {
    //That shows a blue square behind the icon in the menu I click on 
    //and draws a black one on the one which was selected 

    if((e.getX() > 20  && e.getX() < 60) && (e.getY()) > 20 && e.getY() < 60){
        menu.btns[menu.activeTool].toggleClicked();
        menu.btns[0].toggleClicked();
        menu.activeTool = 0;
    }else if((e.getX() > 80  && e.getX() < 120) && (e.getY()) > 20 && e.getY() < 60){
        menu.btns[menu.activeTool].toggleClicked();
        menu.btns[1].toggleClicked();
        menu.activeTool = 1;
    }else if((e.getX() > 140  && e.getX() < 180) && (e.getY()) > 20 && e.getY() < 60){
        menu.btns[menu.activeTool].toggleClicked();
        menu.btns[2].toggleClicked();
        menu.activeTool = 2;
    }else if((e.getX() > 200  && e.getX() < 240) && (e.getY()) > 20 && e.getY() < 60){
        menu.btns[menu.activeTool].toggleClicked();
        menu.btns[3].toggleClicked();
        menu.activeTool = 3;
    }else if((e.getX() > 260  && e.getX() < 300) && (e.getY()) > 20 && e.getY() < 60){
        menu.btns[menu.activeTool].toggleClicked();
        menu.btns[4].toggleClicked();
        menu.activeTool = 4;
    }
    mw.setActiveTool(menu.activeTool);
    this.repaint();
}

public void mouseEntered(MouseEvent e) {

}

public void mouseExited(MouseEvent e) {


}

public void mousePressed(MouseEvent e) {

}

public void mouseReleased(MouseEvent e) {

}

}

Please help me I've read plents of documents about JPanel and drawing but I still don't understand ..

Rayan94
  • 3
  • 2
  • salut :) I'm not sure what your problem is. Do you need help to write a function which draws geometric shapes? Or do you need help to make your panneau display the shapes you drew? – Dan O May 22 '14 at 17:52
  • My problem is that I want to put in my main program something like Point clic; clic= Fenetre.readClick() ; x = clic.x ;y= clic.y; clic = Fenetre.readClick(); a = clic.x ; b = clic.y ; "Function which draws rectangle for example"(x,y,a,b). But I don't know how to make the function that adds a drawing in the JPanel – Rayan94 May 22 '14 at 18:00
  • A complete example is cited [here](http://stackoverflow.com/a/11944233/230513). – trashgod May 22 '14 at 18:32
  • @trashgod I'm sorry but I don't understand what's the solution of my problem with this example of GraphPanel – Rayan94 May 22 '14 at 18:44
  • Really need help. I'm here to learn and I can't understand without someone explaining me. – Rayan94 May 22 '14 at 19:35
  • Sometimes a working example offers some insight. – trashgod May 22 '14 at 19:40
  • That's sure but this example is not exactly what I want to do :/ – Rayan94 May 22 '14 at 19:56

2 Answers2

1

If I understand your question, you basically want some function from which you can

  • wait for user interaction and get information about it
  • draw something to your window

(I'm ignoring right now that you want to do it from the main method, since I'm pretty sure you'll be happy to do it from another method as well)

Basically you are facing two obstacles in that project:

  • Drawing in most windowing systems is event driven, i. e. if the user puts the window to front, it has to know how to draw its current state
  • User interaction is also event driven, i. e. you will get callbacks when the user clicks.

The first obstacle is easy to solve: Create a BufferedImage somewhere that both your UI code and the function can access, and draw inside it. (BufferedImage has a createGraphics method you can use to draw inside the image's buffer). Then the paintComponent method just draws the image whenever somebody puts the window to foreground.

The second obstacle is a bit harder. Basically you'll need threading and synchronization for it. It used to be a lot of tweaking with wait and notify and synchronized calls up to Java 1.4, but since Java 1.5 the synchronization (for this special case) can be handled by BlockingQueue class. So your UI code waits (with MouseListener) for a mouse click and adds the coordinates (as a java.awt.Point) to BlockingQueue, and your UI code will just have to wait for the next point whenever it needs one. You will still have a bit of experience using multithreaded applications (so you should know how to start a Thread and that a Thread cannot interact directly with the UI), so depending on your experience of Java it may be a steep learning curve - but certainly doable.

EDIT: I see you are already using some kind of synchronization for the mouse events, so probably the only parts you still need is starting a thread and drawing to a BufferedImage instead of the real window itself.

EDIT2: Here is a very simplified example that shows you how you can draw to a BufferedImage from a second thread. It will ask for coordinates and colors from the console (standard input) and paint them to the image, which will show in the JPanel. It is your task to combine this example with what you already have to move the mouse position across etc.

import java.awt.*;

import javax.swing.*;

import java.awt.image.BufferedImage;
import java.util.Scanner;

public class BufferedImagePainting extends JFrame {

    public static void main(String[] args) {
        BufferedImage img = new BufferedImage(800, 600, BufferedImage.TYPE_3BYTE_BGR);
        JPanel drawPanel = new DrawPanel(img);
        new InteractionThread(img, drawPanel).start();
        new BufferedImagePainting(drawPanel);
    }

    public BufferedImagePainting(final JPanel drawPanel) {
        super();
        setLayout(new GridLayout(1, 1));
        add(drawPanel);
        pack();
        setVisible(true);
    }

    private static class DrawPanel extends JPanel {
        private BufferedImage img;

        public DrawPanel(BufferedImage img) {
            this.img = img;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(img, 0, 0, this);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(img.getWidth(), img.getHeight());
        }
    }

    private static class InteractionThread extends Thread {

        private BufferedImage img;
        private JPanel drawPanel;

        public InteractionThread(BufferedImage img, JPanel drawPanel) {
            this.img = img;
            this.drawPanel = drawPanel;
        }

        @Override
        public void run() {
            @SuppressWarnings("resource")
            Scanner s = new Scanner(System.in);
            while (true) {
                System.out.println("Enter a draw color and a fill color, separated by spaces");
                System.out.println("Enter colors as 6-digit hex number, i. e. 000000 = black, ffffff = white");
                Color drawColor = new Color(Integer.parseInt(s.next(), 16));
                Color fillColor = new Color(Integer.parseInt(s.next(), 16));
                System.out.println("Enter coordinates in form x y width height, separated by spaces");
                int x = s.nextInt();
                int y = s.nextInt();
                int w = s.nextInt();
                int h = s.nextInt();
                Graphics g = img.createGraphics();
                g.setColor(fillColor);
                g.fillRect(x, y, w, h);
                g.setColor(drawColor);
                g.drawRect(x, y, w, h);
                g.dispose();
                drawPanel.repaint();
            }
        }
    }
}
mihi
  • 6,507
  • 1
  • 38
  • 48
  • It's exactly what I want to do. I have the method readClick which wait for a clic and add to the point the coordonates of the clic and I just have to create the BufferedImage if I understand what you said(sorry I'm french). – Rayan94 May 23 '14 at 16:57
  • I've searched how to create a BufferedImage , create graphics on it, etc but still don't know how to organize it – Rayan94 May 23 '14 at 19:16
0

You must set visibility of your JFrame. Try this in your main class.

public class Geogebra  {
   @SuppressWarnings("unused")
     public static void main(String args[]){
    Fenetre fen = new Fenetre();
    fen.setVisible(true);
     }}
Emad
  • 769
  • 9
  • 21