Będzie to raczej szkic edytora graficznego. Będzie pozwalał
na dodawanie linii do rysunku.
Utwórz nowy projekt typu Desktop Application. Nazwij go Mouse.
Utwórz nową klasę dziedziczącą po JPanel. Nazwij ją MousePanel. Dodaj metodę public void paint(Graphics g){}. Dodaj instrukcję import. Przekompiluj klasę. Umieść komponent w oknie widoku. W miarę możliwości powinien wypełniać całe okno.
Utworzymy fragment hierarchii klas: klasę Line dziedziczącą po klasie Shape. Obie klasy będą klasami zagnieżdżonymi w MousePanel. Obiekty hierarchii Shape będą umiały się narysować korzystając z zdefiniowanych dla nich atrybutów.
// wewnątrz MousePanel
static class
Shape{
Color
color=Color.BLACK;
void
paint(Graphics g){
}
}
static class
Line extends Shape{
int x1,y1,x2,y2;
Line(int
_x1, int _y1,int _x2, int _y2){
x1=_x1;y1=_y1;x2=_x2;y2=_y2;
}
@Override
void paint(Graphics g){
g.setColor(color);
g.drawLine(x1, y1, x2, y2);
}
}
Wektory będą przechowywane w kontenerze Vector<Shape>.
1. Dodajemy atrybut klasy MousePanel:
Vector<Shape> shapes=new
Vector<Shape>();
2. Modyfikujemy
metodę paint() klasy MousePanel
tak, aby wyświetlić zawartość kontenera.
@Override
public void
paint(Graphics g){
for(int
i=0;i<shapes.size();i++){
shapes.get(i).paint(g);
}
}
3. Chcielibyśmy przetestować. W konstruktorze MousePanel dodamy klika linii…
public MousePanel() {
initComponents();
shapes.add(new Line(100,50,200,75));
shapes.add(new Line(50,75,150,175));
}
Po uruchomieniu wyświetli się okno z dwiema liniami.
W docelowej aplikacji, aby dodać linię powinniśmy wybrać opcję Dodaj linię i następnie zdefiniować jej położenie za pomocą myszy. Przyjmiemy najprostsze rozwiązanie. Program będzie reagował na kliknięcia:
· Pierwsze kliknięcie będzie punktem początkowym linii.
· Drugie kliknięcie będzie punktem końcowym.
Aby komponent reagował na zdarzenia typu kliknięcie przycisku myszy, powinien implementować interfejs MouseListener.
1.
Zmień deklarację klasy:
public class
MousePanel extends javax.swing.JPanel
implements MouseListener{
…
}
2. Klikając na symbol “żarówki” zaimportuj interfejs i dodaj automatycznie implementację metod mouseClicked(), mousePressed(), itd… Następnie usuń linie
//throw new UnsupportedOperationException("Not
supported yet.");
3. Zarejestruj komponent jako odbiorcę zdarzeń dodając w konstruktorze MousePanel linię:
addMouseListener(this);
4. Dodawanie linii jest procesem dwuetapowym, dlatego powinniśmy gdzieś przechować współrzędne pierwszego kliknięcia. Najwygodniej przyjąć następującą strategię.
a. Zadeklarujemy atrybut typu Line o wartości początkowej null.
Line newLine;
b. Przy pierwszym kliknięciu utworzymy obiekt typu Line i przypiszemy jego referencję zmiennej newLine. Przy drugim kliknięciu uaktualnimy współrzędne końcowe, dodamy obiekt do kontenera shapes, z powrotem ustawimy newLine na null i przerysujemy okno za pomocą repaint().
public void mouseClicked(MouseEvent e) {
//throw new
UnsupportedOperationException("Not supported yet.");
System.out.println(e.getX()+"
"+e.getY());
if(newLine == null){ // (a)
newLine = new Line(e.getX(),e.getY(),e.getX(),e.getY());
}
else { //
(b)
newLine.x2=e.getX();
newLine.y2=e.getY();
shapes.add(newLine);
newLine=null;
repaint();
}
}
Przetestujemy. Linie powinny być prawidłowo dodawane…
Strategia wizualizacji wektorów w trakcie dodawania opiera się na rozwiązaniu typu gumka (ang. rubberband). Kiedy przesuwamy mysz rysujemy kształty obiektu. Wykorzystujemy w tym celu operację XOR na pikselach. Pierwsze wyświetlenie w trybie XOR rysuje obiekt. Kolejna operacja graficzna z tymi samymi parametrami przywraca oryginalny kolor pikseli.
Rysowanie powinno odbywać się w reakcji na zdarzenie generowane podczas ruchu myszy.
Podobnie, jak w poprzednim przypadku zdefiniowany jest stosowny interfejs MouseMotionListener, który komponent powinien zaimplementować. Alternatywnie można automatycznie wygenerować odpowiednią metodę…
1. W trybie Design kliknij prawym klawisze na komponent MousePanel i wybierz: Events®MouseMotion®mouseMoved
Wygenerowana zostanie automatycznie metoda o nazwie typu formMouseMoved(). Mogliśmy to samo zrobić w poprzednim przypadku!
2. Wpiszemy tam kod, który rysuje obiekt newLine w trybie XOR, uaktualnia współrzędne i rysuje obiekt w nowym miejscu… Oczywiście, nie rysujemy linii, jeśli newLine ma wartość null. Rysowanie nie zachodzi w reakcji na zdarzenie paint(), dlatego musimy pobrać kontekst graficzny i na końcu go zwolnić.
private void
formMouseMoved(java.awt.event.MouseEvent evt) {
// TODO add
your handling code here:
if(newLine == null) return;
Graphics g = getGraphics();
g.setXORMode(Color.GRAY);
newLine.paint(g);
newLine.x2=evt.getX();
newLine.y2=evt.getY();
newLine.paint(g);
g.setPaintMode();
g.dispose();
}
Uwaga – należy we własnościach komponentu MousePanel usunąć przezroczystość (ang. opaque)