Linuksowo.pl - Linux forum

Transkrypt

Linuksowo.pl - Linux forum
Subject: [ROZW.] "odmalowywanie okna" swing, awt
Posted by [PMP] on Fri, 21 Dec 2007 15:00:35 GMT
View Forum Message <> Reply to Message
Wiem ze sprawa byla juz poruszana ale po przeczytaniu wczesniejszych watkow i przgladaniu
googla nie znalazlem odpowiedzi na ten temat. A mianowicie chcialbym aby po zmienieniu
rozmiaru okna mysza lub po przejachaniu jakims oknem ponad aplikacja nie znikala zawartosc
mojego okna. Najlepiej zrozumie sprawe gdy zobacze to na przykladzie. Prosze bardzo o
przekszalcenie ponizszego przykladu tak aby dzialal juz "poprawnie":
import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
public class Paint extends JFrame
{
private Paint()
{
super("PROG1");
add(new PaintPanel(),BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) ;
setSize(800, 600) ;
setVisible(true) ;
}
public static void main(String[] args)
{
new Paint() ;
}
public class PaintPanel extends JPanel implements MouseMotionListener, MouseListener
{
public int lastX,lastY;
public PaintPanel()
{
super();
setBackground(Color.white);
Page 1 of 6 ---- Generated from
Linuksowe by FUDforum 2.8.1
Linuksowo.pl - Linux forum - Polskie Forum
addMouseListener(this) ;
addMouseMotionListener(this) ;
}
public void mouseDragged(MouseEvent e) {
usePen(e);
}
public void mousePressed(MouseEvent e){
lastX=e.getX();
lastY=e.getY();
}
public void mouseReleased(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
public void mouseClicked(MouseEvent arg0){}
public void mouseEntered(MouseEvent arg0) {}
public void mouseExited(MouseEvent arg0) {}
public void usePen(MouseEvent e){
Graphics g =getGraphics();
g.setColor(Color.BLACK);
g.drawLine(lastX, lastY, e.getX(), e.getY()) ;
lastX=e.getX();
lastY=e.getY();
}
}
}
serdecznie dziekuje za wszelka pomoc
Administrator: Poprawione kodowanie
Subject: Odp: "odmalowywanie okna" swing, awt
Posted by Pashimito on Sat, 22 Dec 2007 16:55:02 GMT
View Forum Message <> Reply to Message
Hejka,
Zwróć uwagę, że nigdzie w Twoim kodzie nie nakazujesz, aby narysowane obiekty
zostały zapamiętane. Za każdym razem, gdy okno po którym rysujesz zmienia swoje
położenie, jest przykrywane przez okno innej aplikacji, jest maksymalizowane lub
minimalizowane, Java musi je odrysować na nowo. Robi to poprzez metodę paint(), która w
przypadku komponentów Swinga wywołuje metodę paintComponent(). Zapamiętać
narysowane obiekty można na wiele sposobów, na przykład przechowywać je w kolekcji lub
buforować je z wykorzystaniem obiektu typu Image i to rozwiązanie zastosowałem do
Twojego kodu. W tym celu wystarczy dodać przeciążoną metodę paintComponent() w
Page 2 of 6 ---- Generated from
Linuksowe by FUDforum 2.8.1
Linuksowo.pl - Linux forum - Polskie Forum
której należy skorzystać z metody drawImage() obiektu typu Image aby odrysować
wszelkie dodane wcześniej kształty, tworząc je standardowo przez użycie obiektu typu
Graphics2D.
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Paint extends JFrame
{
private Paint()
{
super("PROG1");
add(new PaintPanel(),BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) ;
setSize(800, 600) ;
setVisible(true) ;
}
public static void main(String[] args)
{
new Paint() ;
}
public class PaintPanel extends JPanel implements MouseMotionListener, MouseListener
{
Image image;
Graphics2D g2d;
Page 3 of 6 ---- Generated from
Linuksowe by FUDforum 2.8.1
Linuksowo.pl - Linux forum - Polskie Forum
public int lastX,lastY;
public PaintPanel()
{
super();
setBackground(Color.white);
addMouseListener(this) ;
addMouseMotionListener(this) ;
}
public void mouseDragged(MouseEvent e) {
usePen(e);
repaint();
}
public void mousePressed(MouseEvent e){
lastX=e.getX();
lastY=e.getY();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image == null)
{
image = createImage(getWidth(), getHeight());
g2d = (Graphics2D)image.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.white);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.setColor(Color.black);
}
Rectangle r = g.getClipBounds();
g.drawImage(image, r.x, r.y, r.width+r.x, r.height+r.y,
r.x, r.y, r.width+r.x, r.height+r.y, null);
}
public void mouseReleased(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
public void mouseClicked(MouseEvent arg0){}
public void mouseEntered(MouseEvent arg0) {}
Page 4 of 6 ---- Generated from
Linuksowe by FUDforum 2.8.1
Linuksowo.pl - Linux forum - Polskie Forum
public void mouseExited(MouseEvent arg0) {}
public void usePen(MouseEvent e){
g2d.setColor(Color.BLACK);
g2d.drawLine(lastX, lastY, e.getX(), e.getY()) ;
lastX=e.getX();
lastY=e.getY();
}
}
}
Dodatkowo, zamiast przechowywać współrzędne punktu w dwóch osobnych zmiennych
można skorzystać z obiektu Point, wtedy w metodzie odpowiadającej za wciśnięcie
przycisku myszy możnaby zamiast przypisywania tym dwóm zmiennym wartości poprzez
metody e.getX() i e.getY() przypisać obiektowi typu Point wpółrzędne korzystając z
metody e.getPoint(). Natomiast przy rysowaniu skorzystać z właściwości x oraz y tego
obiektu.
Pozdro
Administrator: Poprawione kodowanie
Subject: Odp: "odmalowywanie okna" swing, awt
Posted by [PMP] on Sat, 22 Dec 2007 20:49:42 GMT
View Forum Message <> Reply to Message
dziekuje bardzo
wiedzialem ze jest potrzeba odmalowania okna ale nie udawalo mi sie tego dokonac:)
ps. a jakbym musial zmienic ten kod aby podczas zmiany rozmiaru mysza mogl rysowac po
nowym obszarze. Dokladniej gdy zwieksze okno mogl malowac po nowym obszarze, a gdy
zmniejsze tylko po tym co zostalo a reszta niech zostanie usunieta.
dziekuje za pomoc pogodnych swiat
Administrator: Poprawione kodowanie
Subject: Odp: "odmalowywanie okna" swing, awt
Posted by Pashimito on Mon, 24 Dec 2007 18:01:36 GMT
View Forum Message <> Reply to Message
Wykorzystanie obiektu typu Image do przechowywania narysowanych obiektów graficznych jest
dobre gdy jego rozmiar nie ulega zmianie. Jest on tworzony tylko raz, a jego rozmiar jest ustalany
Page 5 of 6 ---- Generated from
Linuksowe by FUDforum 2.8.1
Linuksowo.pl - Linux forum - Polskie Forum
poprzez wykorzystanie metody createImage(<szerokość>, <wysokość>)). W wielu apsach
graficznych właśnie tak to jest, że trzeba najpierw podać rozmiar grafiki. A więc w Twoim
przypadku każda zmiana rozmiaru panelu pociągałaby konieczność stworzenia nowego
obiektu, co jest nie fajne.
Jeśli chcesz móc dowolnie zmieniać rozmiar obszaru na którym można rysować to
lepszym rozwiązaniem będzie jednak utworzenie sobie specjalnej kolekcji, do której
będą trafiać rysowane obiekty. Jest to rozwiązanie wymagające napisania większej
ilości kodu za to umożliwia łatwiejszą implementację cofania i ponawiania zmian
(Undo/Redo). Może to być rozwiązanie oparte na przykład o LinkedHashMap gdzie
kluczem będzie typ obiektu. Wszystko zależy od informacji jakie chcemy w niej
przechowywać.
Na pewno trzeba będzie przechowywać typ obiektu (linia ciągła, prostokąt, okrąg),
punkt rozpoczęcia, punkt zakończenia itp, kolor, grubość kreski. Domyślam się, że
będziesz chciał dać możliwość użytkownikom wyboru kształtów do rysowania,
grubości linii, koloru itp. Przyjmijmy, że każdemu kształtowi będzie odpowiadać inny
przycisk, grubość linii będzie ustalana przez JSpinner a kolor przez JComboBox. Wówczas
wystarczy przy dodawaniu nowego obiektu do kolekcji sprawdzać który przycisk jest wybrany,
pobrać wartości z JSpinnera i z rozwijanej listy.
Docelowo pewnie oprócz metody usePen() będziesz mieć i inne metody na przykład
rysujące okręgi, wypisujące tekst itd. W każdej z nich należałoby umieścić kod
dodający do kolekcji wszystkie informacje potrzebne do wyrysowania danego kształtu.
Następnie w metodzie paintComponent() wystarczy dla każdego elementu z kolekcji
sprawdzić jaki to typ i wywołać odpowiadającą mu metodę.
Więcej o kolekcjach w Javie można się dowiedzieć czytając ten skrypt dr Bartosza
Waltera:
http://wazniak.mimuw.edu.pl/images/3/32/Zpo-2-wyk.pdf
Pozdro
Administrator: Poprawione kodowanie
Page 6 of 6 ---- Generated from
Linuksowe by FUDforum 2.8.1
Linuksowo.pl - Linux forum - Polskie Forum

Podobne dokumenty