SWING AWT - mouseClicked() i paintComponent()

0

Witam, mam małe pytanie:

  • mam pewną klasę Wektor (obiekt panel), która dziedziczy z JPanel i implementuje MouseListener
  • chciałbym aby po kliknięciu na panelu wyświetlały się jakieś linie (drawLine(...))
  • próbuję w mouseClicked() dodać np. g2D.drawLine(x1,y1,x2,y2);
  • nie wiem czy w paintComponent() wystarczy super.paintComponent(g) bo po kliknięciu tylko linie "mrugnie"
  • wg mnie trzeba jakoś te narysowane linie przekazać z mouseClicked() do paintComponent() tylko właśnie problem jak?
    Dziękuję.
0

Te linie są z góry znane, czy tworzone są nowe w zależności od tego gdzie użytkownik kliknął?

0

linie są z góry znane, mają być w określonym miejscu, określonej długości, szerokości

0

Utwórz pole w klasie (tablica lub kolekcja) zawierające parametry tych linii, w metodzie mouseClicked() wywołaj repaint(), w paintComponent() daj super.paintComponent(), a potem w pętli rysuj linie z tablicy (kolekcji).

0

wielkie dzięki kolego, to bardzo dobre rozwiązanie, działa bardzo dobrze :)
super rozwiązanie jeżeli chcemy rysować wiele linii
Jeszcze tylko jedno pytanko, ja generalnie potrzebuję narysować dwie linie - dokładnie krzyżyk na środku

  • dlatego pytałem czy można ten obiekt jakoś bezpośrednio przekazać z mouseClicked() do paintComponent()

a kod po poprawce wygląda tak:

public class Wektor extends JPanel implements MouseListener {
	Graphics2D g2D;
	LinkedList<Linia> lista = new LinkedList<Linia>();
	Linia linia;
	public Wektor() {
		this.addMouseListener(this);
		this.setBounds(210,5,200,200);
		this.setBackground(Color.LIGHT_GRAY);
	}
	
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		g2D = (Graphics2D)g;
		g2D.setStroke(new BasicStroke(5));
		g2D.setColor(Color.BLACK);
		for(int i=0; i<lista.size(); i++) {
			linia = (Linia)lista.get(i);
			g2D.drawLine(linia.getX1(),linia.getY1(),linia.getX2(),linia.getY2());
		}
	}
	
	public void mouseClicked(MouseEvent zdarzenie) {
		lista.add(new Linia((this.getWidth()/2),0,(this.getWidth()/2),this.getHeight()));
		lista.add(new Linia(0,(this.getHeight()/2),this.getWidth(),(this.getHeight()/2)));
		this.repaint();
	}
	public void mouseEntered(MouseEvent arg0) {}
	public void mouseExited(MouseEvent arg0) {}
	public void mousePressed(MouseEvent arg0) {}
	public void mouseReleased(MouseEvent arg0) {}
}

public class Linia {
	int x1,y1,x2,y2;
	public Linia(int x1,int y1,int x2,int y2) {
		this.x1 = x1;
		this.y1 = y1;
		this.x2 = x2;
		this.y2 = y2;
	}
	public int getX1() { return x1; }
	public int getY1() { return y1; }
	public int getX2() { return x2; }
	public int getY2() { return y2; }
}
0

witam....

ja zrobiłem coś takiego (co zapewne przyda się autorowi postu) :

class Main extends JFrame {

    int x = 0, y = 10, w = 50, h = 100;
    JPanel p = new Pan(x, y, w, h);

    public Main() {
        setLayout(new GridLayout(0, 1));

        add(p);
        p.addMouseListener(new M());
    }

    class M extends MouseAdapter {

        public void mousePressed(MouseEvent e) {

            int width = p.getWidth();
            int height = p.getHeight();
            System.out.println(width);

            x = (int) (Math.random() * width);
            System.out.println(x);

            y = (int) (Math.random() * height);
            w = (int) (Math.random() * width);
            h = (int) (Math.random() * height);
            p.revalidate();
            p.repaint();
        }
    }

    class Pan extends JPanel {

        int px, py, pw, ph;

        public Pan(int x, int y, int w, int h) {
            this.px = x;
            this.py = y;
            this.pw = w;
            this.ph = h;
        }

        @Override
        public synchronized void addMouseListener(MouseListener l) {
            super.addMouseListener(l);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
       
     this.setBackground(Color.red);
            g.setColor(Color.black);
            System.out.println("hh: " + x);
            g.drawLine(px, py, pw, ph);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                JFrame fr = new Main();
                fr.setVisible(true);
                fr.setSize(500, 500);
                fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            }
        });


    } // end main
} // 


 

jednak nie reaguje na kliknięcie myszki :/ tzn nie przemalowuje panelu :/
Co jest tu nie tak ?

0

U mnie reaguje, ale trudno to zauważyć bo przemalowany panel jest identyczny z oryginalnym. Może byś tak zmienił wartości pól px, py, pw i ph.

0

Ten fragment

public void mouseClicked(MouseEvent zdarzenie) {
     lista.add(new Linia((this.getWidth()/2),0,(this.getWidth()/2),this.getHeight()));
     lista.add(new Linia(0,(this.getHeight()/2),this.getWidth(),(this.getHeight()/2)));
    this.repaint();
}

jest dość ryzykowny. Ile będzie elementów w kolekcji lista po 1000 kliknięć?
Możliwe usprawnienia:

  • dodatkowe pole logiczne pamiętające, że już dodaliśmy elementy do listy,
  • dodawanie tylko wtedy gdy rozmiar listy jest równy zero,
  • zamiast kolekcji typu LinkedList, kolekcja typu HashSet, do której nie da się dodać dwa razy tego samego.
0

hula :)

jeszcze jedna sprawa....
chciałem żeby w tym kodzie:


class Main extends JFrame {

    int x = 0, y = 10, w = 50, h = 100;
    JPanel p = new Pan(x, y, w, h);

    public Main() {
        setLayout(new GridLayout(0, 1));
        add(p);
    }
    class Pan extends JPanel implements MouseListener {

        int px, py, pw, ph;

        public Pan(int x, int y, int w, int h) {
            this.px = x;
            this.py = y;
            this.pw = w;
            this.ph = h;
            this.addMouseListener(this);
        }

        public void mousePressed(MouseEvent e) {

            int width = this.getWidth();
            int height = this.getHeight();
            px = (int) (Math.random() * width);
            py = (int) (Math.random() * height);
            pw = (int) (Math.random() * width);
            ph = (int) (Math.random() * height);
          //  this.repaint();
            this.repaint();
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.black);
            g.drawLine(px, py, pw, ph);
        }

        

        public void mouseClicked(MouseEvent e) {
        }

        public void mouseReleased(MouseEvent e) {
        }

        public void mouseEntered(MouseEvent e) {
        }

        public void mouseExited(MouseEvent e) {
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                JFrame fr = new Main();
                fr.setVisible(true);
                fr.setSize(500, 500);
                fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            }
        });


    } // end main
} // 

 

jak kliknę myszką to żeby mi robiło repaint ale żeby poprzednio narysowane kreski zostawały
Wszystkie próby spełzły na niczym :(
próbowałem w metodzie repaint wpisywać wartości x,y,w,h ale strasznie się wtedy wszystko gubi :/

0
bo napisał(a)

Ten fragment

public void mouseClicked(MouseEvent zdarzenie) {
     lista.add(new Linia((this.getWidth()/2),0,(this.getWidth()/2),this.getHeight()));
     lista.add(new Linia(0,(this.getHeight()/2),this.getWidth(),(this.getHeight()/2)));
    this.repaint();
}

jest dość ryzykowny. Ile będzie elementów w kolekcji lista po 1000 kliknięć?
Możliwe usprawnienia:

  • dodatkowe pole logiczne pamiętające, że już dodaliśmy elementy do listy,
  • dodawanie tylko wtedy gdy rozmiar listy jest równy zero,
  • zamiast kolekcji typu LinkedList, kolekcja typu HashSet, do której nie da się dodać dwa razy tego samego.

korzystam z dodawania tylko przy pustej liście

remigio napisał(a)

jak kliknę myszką to żeby mi robiło repaint ale żeby poprzednio narysowane kreski zostawały

możesz posłużyć się podobnie jak ja LinkedList(), dodajesz do kolejki obiekty klasy Linia, czyli: lista.add(new Linia(x1,y1,x2,y2)) potem w pętli w paintComponent() odrysowujesz, chcesz usunąć wszystkie: lista.clear() - bardzo wygodna metoda

0

:) świetnie zrobione to z tą linią :) dzienks : )

0

jeszcze jedna kwestia bo nie wiem o co chodzi
po uruchomieniu trzeba złapać ramkę i zminimalizować lub zmienić rozmiar wtedy panele się pojawiają - inaczej ramka wygląda jakby była pusta

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.LinkedList;

public class Cw1 {
	Rastr rastr;
	Wektor wektor;
	Menu menu;
	JTextField text;
	public static void main(String args[]) {
		Cw1 cw1 = new Cw1();
		cw1.start();
	}
	
	public void start() {
		JFrame ramka = new JFrame();
		ramka.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		ramka.setLocation(100,100);
		ramka.setSize(431,442);
//		ramka.setResizable(false);
		ramka.setTitle("Ćw. 1");
		ramka.setVisible(true);
		ramka.setLayout(null);
		
		rastr = new Rastr();
		wektor = new Wektor();
		menu = new Menu();
		ramka.getContentPane().add(rastr);
		ramka.getContentPane().add(wektor);
		ramka.getContentPane().add(menu);
		
		JLabel e = new JLabel("ćw. 1",JLabel.CENTER);
		e.setLocation(0,370);
		e.setSize(menu.getWidth(), 30);
		ramka.getContentPane().add(e);
	}
	
	public class Rastr extends JPanel implements MouseListener {
		File fileIn;
		File fileOut;
		Graphics2D gR;
		BufferedImage imageB;
		public Rastr() {
			this.addMouseListener(this);
			this.setBounds(5,5,200,200);
			this.setBackground(Color.LIGHT_GRAY);
		}
		
		public void wczytaj() {
			fileIn = new File(text.getText());
			try {
				imageB = ImageIO.read(fileIn);
			}
			catch (IOException e) {
				System.out.println("błąd IO in");
			}
			gR = imageB.createGraphics();
		}
		
		public void zapisz() {
			fileOut = new File(text.getText());
			try {
				ImageIO.write(imageB,"jpg",fileOut);
			}
			catch (IOException e) {
				System.out.println("błąd IO out");
			}
		}
		
		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			Graphics2D g2D = (Graphics2D)g;
			g2D.drawImage(imageB,null,0,0);
		}
		
		public void mouseClicked(MouseEvent zdarzenie) {
			gR.setColor(Color.BLACK);
			gR.drawLine(0,zdarzenie.getY(),this.getWidth(),zdarzenie.getY());
			gR.drawLine(zdarzenie.getX(),0,zdarzenie.getX(),this.getHeight());
			this.repaint();
		}
		public void mouseEntered(MouseEvent arg0) {}
		public void mouseExited(MouseEvent arg0) {}
		public void mousePressed(MouseEvent arg0) {}
		public void mouseReleased(MouseEvent arg0) {}
	}
	
	public class Wektor extends JPanel implements MouseListener {
		Graphics2D g2D;
		int licznik = 0;
		LinkedList<Linia> lista = new LinkedList<Linia>();
		Linia linia;
		public Wektor() {
			this.addMouseListener(this);
			this.setBounds(210,5,200,200);
			this.setBackground(Color.LIGHT_GRAY);
		}
		
		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			g2D = (Graphics2D)g;
			g2D.setStroke(new BasicStroke(5));
			g2D.setColor(Color.BLACK);
			for(int i=0; i<lista.size(); i++) {
				linia = (Linia)lista.get(i);
				g2D.drawLine(linia.getX1(),linia.getY1(),linia.getX2(),linia.getY2());
			}
			if(licznik%2 != 0) {
				g2D.setXORMode(Color.white);
				g2D.setPaint(Color.black);
				g2D.fillOval((this.getWidth()/4),(this.getHeight()/4),(this.getWidth()/2),(this.getHeight()/2));
			}
		}
		
		public void mouseClicked(MouseEvent arg0) {
			lista.add(new Linia((this.getWidth()/2),0,(this.getWidth()/2),this.getHeight()));
			lista.add(new Linia(0,(this.getHeight()/2),this.getWidth(),(this.getHeight()/2)));
			this.repaint();
		}
		public void mouseEntered(MouseEvent arg0) {}
		public void mouseExited(MouseEvent arg0) {}
		public void mousePressed(MouseEvent arg0) {}
		public void mouseReleased(MouseEvent arg0) {}
	}
	
	public class Linia {
		int x1,y1,x2,y2;
		public Linia(int x1,int y1,int x2,int y2) {
			this.x1 = x1;
			this.y1 = y1;
			this.x2 = x2;
			this.y2 = y2;
		}
		public int getX1() { return x1; }
		public int getY1() { return y1; }
		public int getX2() { return x2; }
		public int getY2() { return y2; }
	}
	
	public class Menu extends JPanel implements ActionListener {
		JButton wczytaj;
		JButton zapisz;
		JButton usunR;
		JButton rysuj;
		JButton kolo;
		JButton usunW;
		JLabel etykieta;
		public Menu() {
			this.setLayout(new GridLayout(4,2,5,5));
//			this.setBounds(5,220,405,160);
			this.setLocation(5,210);
			this.setSize(405,160);
			wczytaj = new JButton("Wczytaj");
			zapisz = new JButton("Zapisz");
			usunR = new JButton("Usuń");
			rysuj = new JButton("Rysuj");
			kolo = new JButton("Koło");
			usunW = new JButton("Usuń");
			text = new JTextField("foto.jpg");
			etykieta = new JLabel("ścieżka do pliku");

			zapisz.addActionListener(this);
			wczytaj.addActionListener(this);
			usunR.addActionListener(this);
			rysuj.addActionListener(this);
			kolo.addActionListener(this);
			usunW.addActionListener(this);

			this.add(wczytaj);
			this.add(rysuj);
			this.add(zapisz);
			this.add(kolo);
			this.add(usunR);
			this.add(usunW);
			this.add(text);
			this.add(etykieta);
		}
		public void actionPerformed(ActionEvent zdarzenie) {
			Object e = zdarzenie.getSource();
			if(e == wczytaj) {
				rastr.wczytaj();
				rastr.repaint();
			}
			if(e == zapisz) {
				rastr.zapisz();
			}
			if(e == usunR) {
				rastr.imageB = null;
				text.setText("");
				rastr.repaint();
			}
			if(e == rysuj) {
				if(wektor.lista.isEmpty()) {
					wektor.lista.add(new Linia((wektor.getWidth()/2),0,(wektor.getWidth()/2),wektor.getHeight()));
					wektor.lista.add(new Linia(0,(wektor.getHeight()/2),wektor.getWidth(),(wektor.getHeight()/2)));
					wektor.repaint();
				}
			}
			if(e == kolo) {
				wektor.licznik++;
				wektor.repaint();
			}
			if(e == usunW) {
				wektor.lista.clear();
				wektor.licznik = 0;
				wektor.repaint();
			}
		}
	}
}
0

Zdecydowanie za wcześnie masz setVisible(true); przenieś na koniec metody start().
Btw, kliknięcie w lewy górny panel powoduje błąd wykonania (NullPointerException).

0

Jeszcze raz wielkie dzięki kolego, działa, uruchamia się ładnie, wszystko widoczne :)
Jeżeli chodzi o lewy panel to najpierw muszę wczytać obrazek dopiero wtedy kliknięcie powoduje naniesienie linii (modyfikację obrazka), próbowałem catch obsłużyć jakimś oknem (dialog) ale i tak konsola krzyczy...

0

Może tak:

                public void mouseClicked(MouseEvent zdarzenie) {
                        if(gR==null) return;
                        gR.setColor(Color.BLACK);
                        gR.drawLine(0,zdarzenie.getY(),this.getWidth(),zdarzenie.getY());
                        gR.drawLine(zdarzenie.getX(),0,zdarzenie.getX(),this.getHeight());
                        this.repaint();

0

No tak :) proste a jakie pomocne, no to napisaliśmy program :)
wiem że moja implementacja ma jeszcze wiele uchybień (czytałem że należy startować to w wątkach) ale dobry początek że przynajmniej robi to co potrzebuję
pozdr.

0

kontynuując SWING'A I AWT
proszę o podpowiedź jak pobrać poprzez najlepiej jakiś BufferedImage obrazek do dwuwymiarowej macierzy?
Czy petla i getRGB() wystarczy aby wykonywać operację na obrazku (obrót, skalowanie, odcienie szarości, zmiana koloru itp) ?
I ostatnia rzecz to jak później wyświetlić tą tablicę jako obrazek?
dziękuję.

1 użytkowników online, w tym zalogowanych: 0, gości: 1