JFrame zdefiniowanej w pakiecie javax swing. Jframe



Pobieranie 124.08 Kb.
Data03.05.2016
Rozmiar124.08 Kb.
Okienko

Zdefiniujemy własną klasę dla obiektu - okienka naszej aplikacji.

Wyprowadzimy tę klasę jako rozszerzenie - klasę potomną -  z klasy bazowej JFrame zdefiniowanej w pakiecie javax.swing.JFrame.
Nasza klasa będzie wówczas od razu wyposażona w standardowe elementy okienka, w tym: ramkę, pasek tytułowy, menu systemowe i przyciski sterujące min-max-zamknij. Wykorzystując metody odziedziczone po klasie JFrame można nadać okienku żądany tytuł, rozmiar, położenie.

import javax.swing.*;

public class Apok {


    
    public static void main(String[] args) {
        Okno ok = new Okno();
        ok.setVisible(true);
    }
}

class Okno extends JFrame {


    Okno() {                     
// konstruktor klasy Okno
        setSize(200,150);
        setLocation(100,100);    
// lokalizacja względem początku ekranu;
        setTitle("Java jest OK");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
// 3 - zamknięcie okna zamyka VMJava
    }
}



Całe wnętrze okienka jest domyślnie obiektem klasy Container. Aby zmienić  właściwości wnętrza okienka (na przykład kolor tła) lub umieścić w okienku jakieś komponenty (na przykład przyciski, pola tekstowe) - trzeba odwołać się do tego kontenera. Dostęp do niego zapewnia metoda getContentPane() klasy JFrame.

Przykład: aby zmienić kolor wnętrza okienka należałoby dodać do powyższego kodu import pakietów definiujących klasy: Color i Contenair:

import java.awt.Color;


import java.awt.Container;

a w klasie Okno zadeklarować kontener o nazwie np wnetrze i w konstruktorze klasy Okno ustawić kolor tła:

Container wnetrze = this.getContentPane();
wnetrze.setBackground(Color.yellow);

 

Wewnętrzny kontener klasy JFrame ma ograniczone możliwości (m.in. nie umożliwia obramowania). Dlatego programiści najczęściej definiują wewnątrz okienka JFrame dodatkowy kontener - panel klasy JPanel i dopiero wewnątrz niego umieszczają potrzebne komponenty.



class Okno extends JFrame {
    
    JPanel
p = new JPanel();       
    
    Okno() {
      setSize(400,300);
      setLocation(100,100);
      setTitle("Java jest OK");
      setDefaultCloseOperation(EXIT_ON_CLOSE);
 
     
p.setBackground(Color.yellow);   // ustawia kolor tła
     
add(p);                          // dodaje panel p do wewnętrznego kontenera klasy Okno
    }
}

 

Komponenty wewnątrz okienka

W okienku można umieścić komponenty - obiekty różnych klas. Wykorzystamy wybrane klasy z biblioteki swing zdefiniowane w pakiecie javax.swing.JComponent:


  • JTextField - pole tekstowe do wyświetlania danych i do wprowadzania danych z klawiatury

  • JLabel - etykietka do wyświetlania tekstu

  • JButton - przycisk

Rozmieszczeniem komponentów w kontenerze/panelu zarzadza jego metoda setLayout(). Przyjmuje ona jako parametr nowy obiekt LayoutManager - zarządca rozmieszczenia. Zarządca może być różnej klasy. Najczęściej używane klasy LayoutManager-ów :

  • FlowLayout() - komponenty rozmieszczane są kolejno w wierszu

  • GridLayout(n,m) -  komponenty rozmieszczane są w siatce o wierszach i m  kolumnach

  • BoxLayout - pozwala na składanie okienka z niezależnych "pudełek" zawierajacych komponenty

  • null - każdy  komponenty musi być wyposażony we własne parametry decydujące o jego położeniu i rozmiarach

Komponenty dodajemy do kontenera/panelu jego metodą add(komponent)

W przykładach poniżej stosowane sa dwie etykietki, jedno pole tekstowe i jeden przycisk służący do pobierania danych.



Uwaga! Przycisk w tych programach na razie nie reaguje jeszcze na kliknięcie. Dopiero w następnym punkcie wyposażymy program w obsługę zdarzenia.

Przykład: zarządca klasy FlowLayout

import javax.swing.*;

import java.awt.FlowLayout// klasa wymaga importu

public class Apok {...}   // jak w programie powyżej

class Okno extends JFrame {
    JPanel p;                    
// składniki okna
    JLabel pytanie;
    JTextField dana;
    JLabel powitanie;
    JButton wez;     
   
    Okno() {                    
// konstruktor okna 
    setSize(400,100);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
   
    p = new JPanel();
    p.
setLayout(new FlowLayout(8));  // odstęp 8px między kolejnymi komponentami

    pytanie = new JLabel("Jak Ci na imię ?");


    powitanie = new JLabel("Witaj");
    dana = new JTextField(10);
    wez = new JButton("weź dane");
   
    p.add(pytanie);
    p.add(dana);
    p.add(wez);
    p.add(powitanie);

    add(p);


    }
}


Przykład: zarządca klasy GridLayout

import javax.swing.*;
import java.awt.
GridLayout// klasa wymaga importu

public class Apok {...}   // jak w programie powyżej

class Okno extends JFrame {

    JPanel p;                             // składniki okna;
    JLabel pytanie;
    JTextField dana;
    JLabel powitanie;
    JButton wez;     

    Okno() {                             // konstruktor okna


    setSize(200,150);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    
    p = new JPanel();
    p.
setLayout(new GridLayout(4,1));  // 4 wiersze 1 kolumna

    pytanie = new JLabel("Jak Ci na imię ?");


    powitanie = new JLabel("Witaj");
    dana = new JTextField(10);
    wez = new JButton("weź dane");
   
    p.add(pytanie);
    p.add(dana);
    p.add(wez);
    p.add(powitanie);

    add(p);


    }
}

 Obsługa kliknięcia przycisku

Aby przycisk zareagował na zdarzenie, trzeba dołączyć do niego "nasłuchiwacz  zdarzeń" - ActionListener.

Jest to abstrakcyjna klasa, która ma zadeklarowaną metodę obsługi zdarzeń actionPerformed(), ale bez jej implementacji (to znaczy: z pustym ciałem metody). Programista sam musi wypełnić ciało metody actionPerformed poleceniami, które mają być wykonane w razie wystąpienia zdarzenia skierowanego do wybranego komponentu.

W naszym przykładzie program po kliknięciu przycisku ma odczytać tekst umieszczony w komponencie dana  i dołączyć ten tekst do pozdrowienia wyświetlanego w komponencie powitanie.

Do odczytania tekstu  i umieszczenia nowego tekstu wykorzystamy metody klasy TextField:



  • getText() - pobiera zawartość pola tekstowego

  • setText(String) - umieszcza w polu tekstowym wartość typu String

Do kodu programu trzeba zaimportować pakiet java.awt.event.* w którym zdefiniowane są narzędzia do obsługi zdarzeń.

Cały program prezentuje się następująco:



import javax.swing.*;
import java.awt.GridLayout;
import
java.awt.event.*;

public class Apok1 {


   
    public static void main(String[] args) {
    Okno ok = new Okno();
    ok.setVisible(true);
    }
}

class Okno extends JFrame {

    JPanel p = new JPanel();
    JLabel pytanie;
    JTextField dana;
    JLabel powitanie;
    JButton wez;    

    Okno() {    // konstruktor


    setSize(200,150);

    setDefaultCloseOperation(3);
 
    p = new JPanel();
    p.setLayout(new GridLayout(4,1));

    pytanie = new JLabel("Jak Ci na imię ?");


    dana = new JTextField(10);
    powitanie = new JLabel("Witaj");
    wez = new JButton("weź dane");    

    wez.addActionListener(new ActionListener() {


        public void
actionPerformed(ActionEvent zdarzenie) {
            powitanie.
setText("Witaj "+dana.getText());
            }
        }   
     );


     
    p.add(pytanie);
    p.add(dana);
    p.add(wez);
    p.add(powitanie);
    add(p);
    }

}



Wiele przycisków i jeden ActionListener

Interfejs graficzny programu może zawierać wiele przycisków o różnej funkcjonalności.  W takiej sytuacji programista używa  interfejsu ActionListener, obsługującego wszystkie przyciski jedną i tą samą metodą actionPerformed(). Metoda actionPerformed() "sama" wykryje który przycisk jest źródłem zdarzenia - zrobi to przy pomocy metody getSource() wbudowanej w zdarzenie. Metoda getSource() zwraca nazwę obiektu wywołującego zdarzenie.

Program poniżej utrwala i rozwija polecenia służące do budowania okienka.

Okienko zawiera dwa panele o różnych kolorach tła,  obramowane.

Etykietka JLabel w drugim panelu, zawierająca treść powitania, ma rozmiar ustawiony na stałe (domyślnie obiekt typu JLabel dopasowywałby swoją wielkość do treści którą ma wyświetlać) oraz czcionkę wybraną przez programistę.

Przycisk Weź dane  ma za zadanie odczytać dane wpisane przez użytkownika do pól tekstowych i wyświetlić uprzejme powitanie w dolnym panelu. Treść powitania zależy od podanego wieku: osoby poniżej 18 lat wita słowem "dziecino",dla osób starszych treść powitania jest inna.

Wyjątek Exception ex  obsłuży sytuację, gdy użytkownik nieprawidłowo poda wiek (gdy poda  łańcuch znaków który nie da się przetłumaczyć na wartość liczbową, na przykład poda litery)

Przycisk Czyść dane ma za zadanie usunąć zawartość pól tekstowych służących do wpisywania danych.

import javax.swing.*;            // do klasy bazowej JFrame
import java.awt.GridLayout;      // do rozmieszczenia komponentów
import java.awt.FlowLayout;
import java.awt.event.*;         // do obsługi zdarzeń
import javax.swing.border.*;     // do obramowania panelu
import java.awt.Dimension;       // do ustalenia preferowanych wymiarów etykiety
import java.awt.Font;            // do wyboru czcionki
import java.awt.Color;

class Zdarzenia {


    public static void main(String[] args) {
            Okno ok = new Okno();
            ok.setVisible(true);
        }
    }

class Okno extends JFrame implements ActionListener {


    JPanel p1,p2;                        // składniki okna : 2 panele
    JLabel lImie, lWiek, powitanie;      // 3 etykietki
    JTextField tImie, tWiek;             // 2 pola tekstowe
    JButton bWez, bCzysc;                // 2 przyciski
    
    Okno() {                             // konstruktor okna
        setSize(260,200);
        setTitle("2 przyciski demo");
        setLocation(100,100);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        
        this.setLayout(new FlowLayout(20));  // wewn.kontener, 20px odstepu od krawędzi
        
        p1 = new JPanel(new GridLayout(3,2));  // pierwszy panel - dla danych
        p1.setBorder(BorderFactory.createTitledBorder("Dane"));
        p1.setBackground(Color.yellow);
             
        lImie = new JLabel("Jak Ci na imię ?");
        lWiek = new JLabel("Ile masz lat ?");
        tImie = new JTextField(10);
        tWiek = new JTextField(10);
              
        bWez = new JButton("weź dane");        // tworzy przyciski
        bCzysc = new JButton("czyść dane");
            
        bWez.addActionListener(this);          // przyłącza ActionListener do przycisków
        bCzysc.addActionListener(this);
               
        p1.add(lImie);        // dodaje komponenty do panelu p1
        p1.add(tImie);
        p1.add(lWiek);
        p1.add(tWiek);
        p1.add(bWez);
        p1.add(bCzysc);
        add(p1);        // na końcu dodaje panel p1 do wewnętrznego kontenera klasy Okno
             
        p2 = new JPanel(new GridLayout(1,1));        // drugi panel - p2 - dla powitania
        p2.setBorder(BorderFactory.createTitledBorder("Powitanie"));
        p2.setBackground(Color.pink);
             
        powitanie = new JLabel("");
        powitanie.setPreferredSize(new Dimension(230,20));
        powitanie.setFont(new Font("Monotype Corsiva",1,16));
        p2.add(powitanie);
        add(p2);                // dodaje panel p1 do wewnętrznego kontenera klasy Okno
    }                                                       // koniec konstruktora okna

    public void actionPerformed(ActionEvent e) {


      
      if (e.getSource()== bWez) {        // obsługa kliknięcia przycisku: Weź dane
         try{
          int wiek = Integer.parseInt(tWiek.getText());
          if (wiek<18) powitanie.setText("Witaj "+tImie.getText()+" dziecino");
                  else powitanie.setText("Witaj "+tImie.getText()+" chodzmy na piwo");
          } catch (Exception ex) { powitanie.setText("bledne dane"); }
      }
        
      if (e.getSource()== bCzysc) {     // obsługa kliknięcia przycisku: Czyść dane
         tImie.setText("");             // czyści pole tekstowe
         tWiek.setText("");
         powitanie.setText("");
      }
    }                                    // koniec obsługi zdarzeń
}

 

 Ćwiczenie



Napisz program okienkowy który pobiera w polu tekstowym odległość w kilometrach. W odpowiedzi na kliknięcie przycisku Oblicz  program powinien przeliczyć podaną odległość na:

  • metry

  • stopy (1 stopa = 30,48 cm)

  • jardy  (1 jard = 0,9144 metra)

  • mile morskie (1 mila morska = 1,85166 km)

wyświetlając wyniki w czterech kolejnych etykietkach poniżej przycisku.

 Przycisk i okienka dialogowe JOptionPane

Klasa JOptionPane z pakietu javax.swing.JOptionPane  umożliwia łatwe wyświetlanie okienek dialogowych różnych typów przy pomocy metod:


  • showMessageDialog - komunikat informacyjny z przyciskiem potwierdzenia

  • showConfirmDialog - komunikat  z wyborem przycisków yes/no/cancel

  • showOptionDialog - rozszerzenie dwóch powyższych typów

  • showInputDialog - zachęta do wprowadzenia odpowiedzi

Wywołania metod:

void showMessageDialog(null,"akuku")          // wersja najprostsza

void showMessageDialog(Component parent, Object treść, String tytuł, int typKomunikatu)
   
int showConfirmDialog(null,"akuku")           //  wersja najprostsza

int showConfirmDialog( Component parent, Object treść, String tytuł, int typOpcji)

int showOptionDialog(Component parent, Object treść, String tytuł,
      int typOpcji, int typKomunikatu, Icon icon, Object[] options, Object initialValue)


String showInputDialog( String pytanie)     //  wersja najprostsza  

String showInputDialog( Component parent, String pytanie, String wartośćDomyslna, int typKomunikatu)

 

Parametry pobierane przez metody showXxxDialog:

typKomunikatu:

     ERROR_MESSAGE


   INFORMATION_MESSAGE
   WARNING_MESSAGE
   QUESTION_MESSAGE
   PLAIN_MESSAGE

typOpcji:

      YES_OPTION


   NO_OPTION
   CANCEL_OPTION
   OK_OPTION
   CLOSED_OPTION
oraz ich kombinacje: YES_NO_OPTION, YES_NO_CANCEL_OPTION   

parent - komponent nadrzędny (rodzic). Jeśli rodzic jest podany, to okienko dialogowe  zostanie wyświetlone w obszarze rodzica (przykryje go częściowo). Jesli rodzic nie jest podany (lub podano: null), to okienko dialogowe zostanie wyświetlone w środku ekranu.

Przykładowy program

Okienko główne  zawiera wyłącznie przycisk, który należy kliknąć aby uruchomić metodę actionPerformed() interfejsu ActionListener.

import javax.swing.*;
import java.awt.event.*;

public class Mess implements ActionListener {


 
  JFrame ok;
 
  public static void main(String[] args){
    Mess db = new Mess();
  }

  public Mess() {


    ok = new JFrame("Dialogowe okienko komunikatu");
    JButton button = new JButton("Kliknij mnie");
    button.addActionListener(this);
    ok.add(button);
    ok.setSize(300, 200);
    ok.setVisible(true);
    ok.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }

    public void actionPerformed(ActionEvent e){


   
    // komunikat ze standardową treścią napisów na przciskach
    JOptionPane.showConfirmDialog(ok,"Czy mnie lubisz?",
           "tytuł - pytanie", JOptionPane.YES_NO_CANCEL_OPTION);

    // komunikat z własną treścią napisów na przyciskach, zwraca wartość typu int:


    // 0 - jeśli wybrano pierwszy przycisk, 1 - jeśli drugi itd

    Object[] options = { "DALEJ", "ANULUJ" };
    int x= JOptionPane.showOptionDialog(null,
             "Czy chcesz kontunuować?", "tytuł okienka",
              JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
              null, options, options[0]);
   
    if (x==0) {
     
     // pobranie danej z okienka dialogowego
     String imie = JOptionPane.showInputDialog(null,"Podaj imię",
              "tytuł - pobieranie danej",JOptionPane.QUESTION_MESSAGE);
     
     // zwykły komunikat
     JOptionPane.showMessageDialog(ok,"Witaj "+imie,"tytuł komunikatu",
               JOptionPane.INFORMATION_MESSAGE);
               }
  }
}

Więcej o obsłudze zdarzeń. Jak to działa ?

Zdarzenie jest obiektem, który opisuje zmianę stanu swojego źródła wywołaną na przykład:

  • kliknięciem przycisku

  • przesunięciem myszy

  • naciśnięciem klawisza

  • wyborem elementu z listy


Źródłem zdarzenia najczęściej jest mysz, klawiatura lub element interfejsu graficznego użytkownika (przycisk, lista wyboru itp).

W Javie zdarzenia są delegowane:



  1. źródło generuje zdarzenie

  2. zdarzenie jest wysyłane do słuchacza

  3. słuchacz wywołuje metodę która obsługuje zdarzenie


Słuchacz jest obiektem, który nasłuchuje - czeka na wystąpienie zdarzenia, po otrzymaniu informacji o zdarzeniu obsługuje je i natychmiast powraca do stanu nasłuchu.

Słuchacz musi implementować interfejs dla określonego rodzaju zdarzeń, to znaczy implementować metody które uruchomi w razie wystąpienia zdarzenia.



Interfejs - to zbiór nazw metod, bez ich definicji. Można go dodać do klasy aby rozszerzyć jej możliwości. Interfejsy stosowane są w sytuacji, gdy takie same czynności muszą być dostępne w grupie wielu niezależnych klas.

Jeśli obiekt  będzie miał reagować na zdarzenia, to klasa która go definiuje musi implementować słuchacza odpowiednich zdarzeń. Informację o implementacji wybranego interfejsu trzeba umieścić w nagłówku definicji klasy:

   class NazwaKlasy implements NazwaInterfejsu {

        ciało klasy

  }

Klasa musi implementować WSZYSTKIE metody wybranego interfejsu, nawet jeśli niektórych z nich nie wykorzystuje. Ciała metod nie wykorzystanych pozostają puste.

Słuchacza trzeba przyłączyć do źródła aby mógł otrzymywać zawiadomienia o zdarzeniach generowanych przez to źródło. Przyłączenia dokonuje się metodą źródła o nazwie podobnej do: addTYPSŁUCHACZAListener, na przykład:


  • addActionListener

  • addMouseListener

  • addKeyListener

Metody przyłączające słuchacza pobierają parametr - nazwę klasy implementującej interfejs nasłuchu, this - oznacza bieżącą klasę, ale można zdefiniować osobną klasę.

Słuchacza można odłączyc od źródła metodą removeTYPSŁUCHACZAListener.

Różne źródła mogą być przyłączone do tego samego słuchacza. Słuchacz rozpoznaje źródło na podstawie informacji przekazywanej mu przez zdarzenie.

Wszystkie zdarzenia posiadają metodę getSource() typu Object. Zwraca ona nazwę obiektu – źródła, które wywołało zdarzenia.

Narzędzia do obsługi zdarzeń są zawarte w pakiecie java.awt.event. Trzeba importować ten pakiet.

 

Najczęściej wykorzystywane interfejsy



Interfejs ActionListener posiada tylko jedną metodę. Obsługuje ona zdarzenia generowane przez dowolną akcję.

void actionPerformed(ActionEvent e) {  }

Słuchacza należy przyłączyć do źródła metodą addActionListener().


Interfejs MouseListener do obsługi zdarzeń związanych z myszą posiada metody:

void mouseClicked(MouseEvent me) {  } - kliknięcie myszą na obiekcie


void mouseEntered(MouseEvent me) {  } - wejście myszy w obszar obiektu
void mouseExited(MouseEvent me) {  } - wyjście myszy z obszaru obiektu
void mousePressed(MouseEvent me) {  } - naciśnięcie przycisku myszy
void mouseReleased(MouseEvent me) {  } - zwolnienie naciśniętego przycisku myszy

Słuchacza należy przyłączyć do źródła metodą addMouseListener().



Interfejs MouseMotionListener do obsługi zdarzeń związanych z ruchem myszy posiada metody:

void mouseDragged(MouseEvent me) {  } - mysz przeciągana (poruszana z naciśniętym klawiszem)


void mouseMoved(MouseEvent me) {  } - mysz poruszana (bez naciśniętego klawisza)

Słuchacza należy przyłączyć do źródła metodą addMouseMotionListener().

Klasa zdarzenia MouseEvent ma następujące najważniejsze elementy:


  • Component src - źródło zdarzenia

  • int type - typ zdarzenia (MOUSE_CLICKED - kliknięcie, MOUSE_DRAGGED - przeciąganie, MOUSE_ENTERED – wejście do elementu, MOUSE_EXITED – wyjście z elementu,  MOUSE_MOVED - przesuwanie, MOUSE_PRESSED – naciskanie, MOUSE_RELEASED - zwalnianie)

  • int x,y - współrzędne myszy

  • metody: int getX() oraz int getY() pozwalają pobrać współrzędne myszy w chwili zdarzenia


Interfejs KeyListener służy do obsługi klawiatury i posiada metody:

void keyPressed(KeyEvent ke)  {  }    // klawisz jest naciśnięty


void keyReleased(KeyEvent ke)  {  }   // klawisz jest zwolniony
void keyTyped(KeyEvent ke)  {  }      // znak jest wygenerowany

Słuchacza należy przyłączyć do źródła metodą addKeyListener().

Klasa zdarzenia KeyEvent ma następujące elementy:


  • Component src  - źródło zdarzenia

  • int type - typ zdarzenia (KEY_PRESSED – klawisz naciśnięty, KEY_RELEASED – klawisz zwolniony, KEY_TYPED – znak wygenerowany)

  • int code - kod naciśniętego klawisza

  • char ch - znak naciśniętego klawizsa

  • char getKeyChar() - pobranie znaku naciśniętego klawisza

  • int getKeyCode() - pobranie kodu naciśniętego klawisza

  • int getKeyLocation() - określa lokalizacje klawisza (pozwala odróznić np. lewy Shift od prawego Shifta, klawisze cyfr na klawiaturze podstawowej od tych samych cyfr na klawiaturze numerycznej)

  • String getKeyText(code) - opis tekstowy klawisza o podanym kodzie, np: Home, Shift, Space

Klawisze specjalne mają określony kod wirtualny: VK_ENTER, VK_ESCAPE, VK_CANCEL, VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT, VK_SHIFT, VK_ALT.

Interfejs TextListener posiada tylko jedną metodę. Jest na wywoływana w sytuacji, gdy zmianie ulegnie zawartość tekstu w źródle (polu tekstowym).

void textValueChanged(TextEvent e) {  }

Słuchacza należy przyłączyć do źródła metodą addTextListener().

Adapter

Implementacja interfejsu nasłuchu wymaga umieszczenia w klasie implementującej wszystkich metod interfejsu, nawet tych które nie są potrzebne w bieżącym programie. Można się od tego "wykręcić" stosując Adapter. Klasa Adapter ułatwia programowanie obsługi zdarzeń. Dostarcza puste implementacje wszystkich metod w danym interfejsie zdarzeń. Wystarczy dziedziczyć po klasie odpowiedniego adaptera, implementując tylko te zdarzenia które nas interesują. Przykłady będą dalej :)

Źródło: http://www.math.hosted.pl/math_2/programowanie_obiektowe/wyklad12.pdf

Obsługa naciskania klawiszy – KeyListener

Przypomnijmy: obsługa klawiatury wymaga zastosowania interfejsu KeyListener.

Interfejs KeyListener posiada metody, które wszystkie musimy zaimplementować, choć wykorzystamy tylko KeyPressed:


  • void keyPressed(KeyEvent ke)  {  }    // klawisz jest naciśnięty

  • void keyReleased(KeyEvent ke)  {  }   // klawisz jest zwolniony

  • void keyTyped(KeyEvent ke)  {  }      // znak jest wygenerowany

Słuchacza należy przyłączyć do źródła metodą addKeyListener().

Wykorzystamy następujące metody klasy zdarzenia KeyEvent:



  • char getKeyChar() - pobranie znaku naciśniętego klawisza

  • int getKeyCode() - pobranie kodu naciśniętego klawisza

  • String getKeyText(code) - opis tekstowy klawisza o podanym kodzie, np: Home, Shift, Space.


Przykładowy program reaguje na naciśnięcie klawisza.

W etykietce o nazwie  labKod  podaje kod klawisza (nie kod znaku!!!), a w etykietce labText - opis klawisza: znak odpowiadający klawiszowi (litera, cyfra) lub jego tekstowy opis (Shift, Enter itp).

W okienku nie zastosowano żadnego menadżera rozkładu: setLayout(null). Każda z etykietek ma indywidualnie określone położenie w okienku przy pomocy metody setBound(). Metoda ta pobiera parametry - współrzędne dwóch przeciwległych wierzchołków obiektu: lewego górnego i prawego dolnego. Jeśli zawartość obiektu, tu: etykietki, nie mieści się w podanych rozmiarach, to etykietka domyślnie rozszerza się w prawo tyle ile potrzebuje.

W odpowiedzi na naciskanie klawiszy strzałek etykietka z opisem porusza się w kierunku wskazanym przez strzałkę (realizacja - przez zmianę parametrów metody setBound), a w razie wyjścia etykietki poza krawędź okienka - powraca ona z przeciwnej strony okienka.

Klawisze strzałek mają odpowiadające im kody:

37 - w lewo


38 - do góry
39 - w prawo
40 - na dół

Oto kod programu:

import javax.swing.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

class Klaw {


  static public void main (String[] args) {
     Okno ok = new Okno();
     ok.setVisible(true);
     }
}

class Okno extends JFrame implements KeyListener {


   JLabel labKod, labText;
   int x=80, y=50;                   // współrzędne początkowe etykietki z kodem
   int width=300, height=150;        // rozmiary okienka
  
   Okno () {
      setTitle("Kod naciśniętego klawisza");
      setSize(width,height);
      setDefaultCloseOperation(3);
      setLayout(null);
     
      labKod = new JLabel("  ");    // etykietka do wyświetlania kodu klawisza
      labKod.setBounds(x,20,x,20);
      add(labKod);
     
      labText = new JLabel("  ");    // etykietka do wyświetlania opisu klawisza
      labText.setBounds(x,y,x,y);
      add(labText);

      addKeyListener(this);


   }
 
  public void keyPressed(KeyEvent e) {
      int kod = e.getKeyCode();              // weź kod klawisza
      labKod.setText(" "+kod);
     
      String klawisz = e.getKeyText(kod);    // weź opis klawisza
      labText.setText(klawisz);
     
      if (kod == 37)  { x=x-10; if (x<0) x=width; labText.setBounds(x,y,x,y);} // w lewo
      if (kod == 39) { x=x+10; if (x>width) x=0; labText.setBounds(x,y,x,y);}  // w prawo
      if (kod == 38)  { y=y-10; if (y<0) y=height; labText.setBounds(x,y,x,y);} // w górę
      if (kod == 40)  { y=y+10; if (y>height) y=0; labText.setBounds(x,y,x,y);} // w dół
   }

   public void keyReleased(KeyEvent e) { }   // metoda nie wykorzystana w tym programie


   public void keyTyped(KeyEvent e) { }      // metoda nie wykorzystana w tym programie
 
}

PODSTAWY GRAFIKI. Klasy: Canvas i Graphics

Rysunek powinien powstawać w komponencie klasy Canvas. Jest to prostokątny czysty obszar, po którym aplikacja może bazgrać, pisać, wklejać gotowe rysunki i wykonywać na nich różne operacje graficzne. Klasa Canvas jest zdefiniowana w pakiecie java.awt.Canvas.

Można także utworzyć własny komponent rysunkowy bazujący na klasie JComponent.

W zasadzie możnaby bazgrać po każdym obiekcie wizualnym (JPanel, JLabel itp), ale nie powinno się tego robić, tak jak nie powinno się bazgrać po ścianach, samochodach itp, bo to i bałagan i skutki bywają nieprzewidywalne ;)

Do tworzenia rysunków służy klasa Graphics z pakietu java.awt.Graphics.

Klasa Graphics pełni dwie role:



  • Tworzy kontekst graficzny: kanwę rysunku zwiazaną z wybranym obiektem. Przypisuje mu atrybuty: wymiary, kolor tła, kolor pierwszoplanowy, czcionkę.

  • Dostarcza metod do rysowania prostych figur geometrycznych, tworzenia napisów, ładowania obrazu z pliku graficznego.

Aby program mógł coś rysować, trzeba udostępnić mu kontekst graficzny (obiekt klasy Graphics). Następnie można odwoływać się do metod tego obiektu, aby rysować odcinki, łuki, wieloboki, elipsy.

Obiekt klasy Canvas (każdy inny obiekt wizualny też) ma wbudowaną metodę paint(Graphisc g), która jest odpowiedzialna za rysowanie obrazka. Tę metodę należy nadpisać, tzn zdefiniować samodzielnie jej ciało. Tu należy umieszczać polecenia rysowania czegokolwiek.

Metoda paint(Graphics g) jest wykonywana każdorazowo:



  • na starcie programu

  • gdy okno programu zostało zminimalizowane, a następnie przywrócone do normalnych rozmiarów

  • gdy okno programu zostało przykryte innym oknem, a następnie wyciągniete na wierzch

  • gdy wywołano metodę repaint()


Układ współrzędnych kontekstu graficznego ma początek (0,0) w lewym górnym narożniku kontekstu graficznego, oś X rośnie w prawo, oś Y rośnie w dół.

Metody rysujące proste figury geometryczne (XXX - zastąpisz nazwą figury geometrycznej)



drawXXX() - rysuje linię lub kontur figury zamkniętej linią o szerokości 1px
fillXXX() - rysuje figury zamknięte wypełnione kolorem pierwszoplanowym

Kolor pierwszoplanowy (linii, wypełnienia) należy ustawić metodą setColor(Color) przed poleceniem rysowania.

Oto niektóre metody klasy Graphics:


  • drawLine(x1,y1,x2,y2) - odcinek łączący punkty o podanych współrzędnych typu int

  • drawRect(x,y,szerokość,wysokość) - prostokąt o lewym górnym narożniku (x,y)

  • drawRoundRect(x,y,szerokość,wysokość, szerokość_łuku, wysokość_Łuku) - prostokąt o zaokrąglonych wierzchołkach

  • drawOval(x,y,szerokość,wysokość) - elipsa wpisana w prostokąt o lewym górnym narożniku (x,y)

  • drawPolygon(x[],y[],n) - wielobok o n wierzchołkach, których wspórzędne podano w tablicach x[] oraz y[] typu int

  • drawPolyLine(x[],y[],n) - linia łamana łącząca n punktów, których wspórzędne podano w tablicach x[] oraz y[] typu int

  • drawArc(x,y,szerokosc,wysokosc, kąt_początkowy,kąt_końcowy) - łuk wpisany w prostokąt

  • drawImage(obraz, wymiary)

  • drawString(tekst,x,y) - tekst umieszczony lewym dolnym wierzchołkiem w (x,y), wcześniej należy wybrać czcionkę metodą setFont(czcionka)

oraz niektóre metody rysujące zamknięte figury wypełnione (parametry jak powyżej):



  • fillRect(x,y,szerokość,wysokość)

  • fillOval(x,y,szerokość,wysokość)

  • fillPolygon(x[],y[],n)

  • fillArc(x,y,szerokosc,wysokosc, kąt_początkowy,kąt_końcowy)


Przykładowy program

import javax.swing.*;


import java.awt.Graphisc;

public class Grafika extends JFrame{


    
    public static void main(String[] args) {
      Grafika ok = new Grafika();
      ok.setTitle("Moja pierwsza j-grafika");
      ok.setSize(300,200);
      ok.setDefaultCloseOperation(EXIT_ON_CLOSE);

      ok.add(new Kanwa());    


      ok.setVisible(true);
    }
}

class Kanwa extends Canvas {

    public void paint(Graphics g) {
        
        g.setColor(Color.yellow);
        g.fillRoundRect(30,30,190,100,10,20);
        
        g.setColor(Color.green);
        g.fillOval(50,50,150,100);

        g.setColor(Color.blue);


        g.drawLine(10,10,280,150);

        Font f = new Font("TimesRoman",Font.BOLD,36);


        g.setFont(f);
        g.setColor(Color.red);
        g.drawString("Wow - Java!", 60 , 100);
    }
  }

 

Klasa Graphics2D


Klasa Graphics2D jest rozszerzeniem klasy Graphics, zdefiniowanym w pakiecie java.awt.Graphics2D. Dostarcza bardziej wyrafinowanych narzędzi graficznych.

Aby wykorzystać nowe możliwości na powierzchni rysunkowej wybranego komponetu, trzeba rzutować jego domyślny kontekst graficzny Graphics g na typ Graphics2D, tworząc nowy kontekst graficzny:

Graphics2D g2 = (Graphics2D)g;

Klasa Graphics2D umożliwia między innymi rysowanie konturów o żądanej szerokości, stylu zakończenia linii i miejsca połaczeń odcinków:

g2.setStroke(new BasicStroke(szerokość_linii, zakończenie_linii, łaczenia_linii));


                               float        int 0-2           int 0-2


Przykład:   g2.setStroke(new BasicStroke(5.0f)); 

// linia ciągła szerokość linii 5px

Kolor, teksturę i przezroczystość ustala się w klasie Graphics2D metodą setPaint()

import java.awt.*;


import javax.swing.*;

public class Bs extends JFrame {

  public static void main(String s[]) {
    Bs ok = new Bs();
    ok.setSize(240, 170);
    ok.setTitle("Graphics2D");
    ok.setDefaultCloseOperation(EXIT_ON_CLOSE);
    ok.add(new Kanwa());
    ok.setVisible(true);
  }
}
  class Kanwa extends Canvas {
 
    public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;           // kontekst graficzny o rozszerzonych możliwościach
    g2.setStroke(new BasicStroke(8.0f,0,2));  // szerokość linii 5px, połączenia zaokrąglone
      
    g2.setPaint(Color.blue);
    Rectangle r = new Rectangle(10,10,200,110);
    g2.draw(r);
      
    g2.setPaint(Color.red);
    Rectangle rr = new Rectangle(50,50,50,50);
    g2.draw(rr);
      
    g.setColor(Color.green);
    g.fillOval(120,30,100,45);
    g.setColor(Color.yellow);
    g.drawOval(120,30,100,45);
    }
  }

 

Przykład - Wykres kołowy

Program rysujący wykres kołowy dla liczb o losowo wybranych wartościach. Ilość liczb jest podawana jako argument przy uruchomieniu programu. Program jest przygotowany na przyjęcie maksymalnie 20 liczb (ale to ograniczenie można usunąć, stosując Vector zamiast tablicy liczb).

Przykład uruchomienia (po skompilowaniu) dla 8 liczb:   java Kolowy 8

import javax.swing.*;
import java.awt.*;
import java.util.Random;

public class Kolowy {


    public static void main(String [] args) {
      int n = Integer.parseInt(args[0]);  // n - argument przy uruch.programu
          Okno ok = new Okno(n);
      }
}

class Okno extends JFrame {


   Random r = new Random();
   int n;
   int [] x;
   int suma=0;
   Wykres k;
    
   Okno( int n) {
      setSize(300,300);
      setTitle("Wykres kołowy - dane losowe");
      setDefaultCloseOperation(EXIT_ON_CLOSE);

      x = new int[n];


      for (int i=0;i< n; i++)
     // tworzenie obiektu k klasy Wykres dla n liczb       
      k = new Wykres(n,x);   // o wartościach w tablicy x   
      add(k);          
      setVisible(true);
   }
}

class Wykres extends Canvas {


    int n=20;
    int [] x = new int[n];
    int suma=0;
    Random r = new Random();
    
    Wykres(int nd, int[] dane) {
    n=nd;
    for (int i=0; i< n; i++) {
        x[i]=dane[i];
        suma=suma+x[i];
        }
    setBackground(Color.orange);
    }
    
    public void paint(Graphics g) {
    int xp=10, yp=10;
    int szer = getWidth()-10;             // pobranie wymiarów okienka
    int wys = getHeight()-10;
    int katP = 0;                         // kąt początkowy dla wycinka
    for (int i=0; i< n; i++) {
        double kK = (double)x[i]/suma*360;   // kąt końcowy wycinka
        int katK = (int)kK;
        if (i == n-1) katK=360-katP;
        Color k = new Color(r.nextInt(256),r.nextInt(256),r.nextInt(256)); // losowy kolor wycinka
        g.setColor(k);
        g.fillArc(xp,yp,szer,wys,katP,katK);    // rysowanie wycinka
        katP = katP+katK;
      }
      g.setColor(Color.white);
      StringBuilder s = new StringBuilder("Liczby: ");
      for (int i=0; i< n; i++) s.append(x[i] +", ");
      g.drawString(s.toString(),10,70);
    }
}

Grafika i zdarzenia związane z myszą

Klasa komponentu, po którym ma rysować mysz, musi implementować interfejs MouseMotionListener,  zaś do utworzonego komponentu - obiektu tej klasy trzeba przyłączyć słuchacza ruchu myszy: addMouseMotionListener(this).

Interfejs MouseMotionListener posiada dwie metody:

mouseDragged(MouseEvent me) - przesuwanie myszy (bez naciśnięcia jej klawisza)
mouseMoved(MouseEvent me) - przeciąganie myszy (przesuwanie z naciśniętym klawiszem)

Trzeba implementować OBIE te metody, nawet jeśli w programie potrzebna jest tylko jedna z nich (niewykorzystana metoda ma ciało puste).

Przykładowy program wykorzystuje metodę mouseMoved. Przy poruszaniu myszą program wyświetla bieżące współrzędne myszy  i testuje położenie: wewnątrz / na zewnątrz czerwonego prostokąta. Program działa przy przesuwaniu myszy bez naciśnięcia klawisza. Przy przesuwaniu naciśniętej myszy zachodziłoby zdarzenie: przeciąganie myszy i należałoby obsłużyć drugą z metod interfejsu MouseMotionListener - metodę mouseDragged.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.Container;

class Okno extends JFrame {


    Kanwa k;
    
    public static void main(String[] args) {
      Okno ok = new Okno();
    }
    
    Okno () {
     setTitle("Ruszaj myszą");
     setSize(300,250);
     setDefaultCloseOperation(EXIT_ON_CLOSE);

     Container con = this.getContentPane();


     con.setBackground(Color.yellow);
     


   k = new Kanwa();
     add(k);


  

    setVisible(true);    }
}

class Kanwa extends Canvas implements MouseMotionListener  {


    boolean wewnatrz = false;
    int X=0,Y=0;
    int xw=40,szer=200,yw=60,wys=100;
// położenie i wymiary czerwonego prostokąta

    Kanwa () {


        
addMouseMotionListener(this);
    }
    
    public void paint(Graphics g) {
        g.setColor(Color.red);
        g.fillRect(xw,yw,szer,wys);
        g.setColor(Color.blue);
        if (wewnatrz) g.drawString("Mysz w srodku "+X+" "+Y,60,120);
             else g.drawString("Mysz na zewnatrz "+X+" "+Y,60,40);
    }
   
   public void
mouseDragged(MouseEvent me) {  }
   
    public void
mouseMoved(MouseEvent me) {
        X = me.getX();
        Y = me.getY();
        if ( X>xw && Xyw && Y< yw+wys) wewnatrz=true;  else wewnatrz=false;
        repaint();
    }
}


Rysowanie prostych figur geometrycznych

Program demonstruje:



  • Zastosowanie grupy przycisków opcji (radio-buttonów) do wyboru kształtu figury (elipsa, prostokąt, trójkąt). Główna klasa programu implementuje interfejs ActionListener. Jego metoda actionPerformed sprawdza który przycisk opcji wygenerował zdarzenie ActionEvent - stąd wiadomo jakie kształy rysować.

  • Implementację interfejsu MouseListener do testowania naciśnięcia i zwolnienia przycisku myszy, oraz odczytu współrzędnych myszy w chwili zdarzenia. Interfejs MouseListener jest implementowany przez klasę obiektu, po którym chcesz rysować, czyli przez kanwę. Zaś do samego obiektu przyłacza się słuchacza: addMouseListener(this).

Wykorzystano następujące metody interfejsu MouseListener:



mousePressed(MouseEvent e) - naciśnięcie myszy
mouseReleased(MouseEvent e) - zwolnienie myszy

zaś pozostałe metody tego interfejsu: mouseClicked(), mouseEntered() i mouseExited() mają ciała puste.

Klasa Kanwa jest w programie rozszerzeniem klasy JPanel. W zasadzie powinno się rysować na komponentach klasy Canvas, nie na panelach. Dlaczego?

Jedna z różnic w działaniu tych obiektów jest widoczna w chwili zastosowania metody repaint():

Metoda repaint() zastosowana dla obiektu klasy Canvas czyści całą powierzchnię i rysuje nową figurę na czystej powierzchni (usuwając poprzednio narysowane figury).

Metoda repaint() zastosowana wprost do obiektu klasy JPanel NIE CZYŚCI obrazu poprzednio narysowanych figur, one są jakby narysowane w innej warstwie. Dopiero odświeżenie wewnętrznego kontenera tego panelu (lub w ogóle głównego okna aplikacji!) powoduje usunięcie poprzednio narysowanych figur.


import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;

public class Simple extends JFrame implements ActionListener {



// współrz. lewego górnego wierzchołka i wymiary prostokąta/elipsy
    int x, y, w, h;
// współrzędne wierzchołków trójkąta    
    int[] xt = new int[3];
    int[] yt = new int[3];
 
    String ksztalt = "Prostokat";
    Random r = new Random();

    public static void main(String[] args) {


        Simple frame = new Simple();
        frame.setVisible(true);
    }
    
    public Simple() {
        setTitle("Ciągnij naciśniętą mysz i puść");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(400,300);
        setLayout(new BorderLayout());
        
        // grupa przycisków opcji
        ButtonGroup opcje = new ButtonGroup();
        
        JRadioButton elipsa = new JRadioButton("Elipsa");
        JRadioButton prosto = new JRadioButton("Prostokat");
        JRadioButton trojkat = new JRadioButton("Trojkat");
        
        opcje.add(elipsa);
        opcje.add(prosto);
        opcje.add(trojkat);
        
        elipsa.addActionListener(this);
        prosto.addActionListener(this);
        prosto.setSelected(true);
        trojkat.addActionListener(this);
        
        // panel przycisków opcji
        JPanel opcjePanel = new JPanel();
        opcjePanel.setLayout(new FlowLayout());
        opcjePanel.add(elipsa);
        opcjePanel.add(prosto);
        opcjePanel.add(trojkat);
        add(opcjePanel, BorderLayout.NORTH);
    
       // panel do rysowania
        Kanwa p = new Kanwa();
        add(p,BorderLayout.CENTER);
    }
    
    public void actionPerformed(ActionEvent ae) {  // wybór opcji kształtu
        ksztalt = ae.getActionCommand().toString();
    }

   class Kanwa extends JPanel  implements MouseListener// można też tak: extends Canvas ale...???


   
    Container con;    // wewnętrzny kontener Kanwy

    Kanwa() {


        con = getContentPane();
        con.setBackground(new Color(220,255,100));
        addMouseListener(this);
    }
   
    public void paint(Graphics g) {
         // losowy wybór koloru wypełnienia figury
         g.setColor(new Color(r.nextInt(256),r.nextInt(256),r.nextInt(256)));
       
         if (ksztalt=="Prostokat") g.fillRect(x,y,w,h);
         if (ksztalt=="Elipsa") g.fillOval(x,y,w,h);
         if (ksztalt=="Trojkat") {
                 Polygon tr = new Polygon(xt,yt,3);
                 g.fillPolygon(tr);
                }
    }

    public void mouseClicked(MouseEvent me) { }


    public void mouseEntered(MouseEvent me) { }
    public void mouseExited(MouseEvent me) { }

    public void mousePressed(MouseEvent me) {


        x = me.getX();   // współrzędne myszy w chwili naciśnięciu klawisza
        y = me.getY();
    }

    public void mouseReleased(MouseEvent me) {


    
        int x2 = me.getX();     // współrzędne myszy w chwili zwolnieniu klawisza
        int y2 = me.getY();
        
        if (ksztalt=="Prostokat" || ksztalt=="Elipsa") {
            w = Math.abs(x2-x);   // szerokość figury
            x = Math.min(x,x2);   //  współrzędna x lewego górnego wierzchołka
            h = Math.abs(y2-y);   // wysokość figury
            y = Math.min(y,y2);   //  współrzędna y lewego górnego wierzchołka
        }
        if (ksztalt=="Trojkat") {
            xt[0]=x; xt[1]=x2; xt[2]= x;
            yt[0]=y; yt[1]=y2; yt[2]= y2;
            }
        repaint();  
        //   con.repaint();       tak jeśli chciałbyś odświeżać tło dla każdej rysowanej figury
   }
  }  // koniec klasy Kanwa
}    // koniec klasy Simple

Rysowanie linii w ślad za myszą

Początek linii ma miejsce w miejscu położenia wskaźnika myszy w chwili gdy naciśnięto klawisz myszy. Współrzędnie pobierane są przy pomocy metody mousePressed() interfejsu MouseListener.

System operacyjny sprawdza położenie myszy w pewnych odstępach czasu. Poruszana mysz zdąży w tym czasie, między jednym a drugim odczytem,  pokonać niewielki odcinek na ekranie.

Przy przeciąganiu myszy (poruszaniu z naciśniętym klawiszem) program wykorzystuje metodę mouseDragged() interfejsu MouseMotion Listener.  Pobierane są bieżące współrzędne myszy.

Polecenie repaint() powoduje wywołanie metody paint(), która rysuje odcinek łączący punkty: od poprzedniego do bieżącego położenia myszy. Powstaje linia łamana, złożona z odcinków o niewielkiej długości.

Piewrsza wersja programu wykorzystuje obiekt klasy JPanel jako kanwę rysunku - wówczas nie ma problemu z usuwaniem wcześniej narysowanych fragmentów linii, kolejne odcinki są dodawane do końca bieżącej linii.

import javax.swing.*;


import java.awt.*;
import java.awt.event.*;
import javax.diva.canvas.JCanvas;

public class Malarz {


   static public void main(String[] args) {
      Okno ok = new Okno();
      ok.setVisible(true);
   }
}

class Okno extends JFrame {


   Kanwa k;
   
   Okno() {
      setSize(400,300);
      setTitle("Rysuj naciśniętą myszą");
      setDefaultCloseOperation(EXIT_ON_CLOSE);
      k = new Kanwa();
      add(k);
   }
 }
 
class Kanwa extends JPanel implements MouseMotionListener, MouseListener {

    int x0,y0,x1,y1;


    
    Kanwa() {
       x0=0;
       y0=0;
       addMouseMotionListener(this);
       addMouseListener(this);
     }
    
    public void paint(Graphics g) {
          g.drawLine(x0,y0,x1,y1); x0=x1; y0=y1;  
        }
     
    // metody interfejsu MouseMotionListener
    public void mouseDragged(MouseEvent me) {
      x1=me.getX();
      y1=me.getY();
      repaint();
    }
   
    public void mouseMoved(MouseEvent me) {  }

    // metody interfejsu MouseListener


    public void mousePressed(MouseEvent me) {  
      x0=me.getX();
      y0=me.getY();
    }

    public void mouseClicked(MouseEvent me) { }


    public void mouseEntered(MouseEvent me) {  }
    public void mouseExited(MouseEvent me) {  }
    public void mouseReleased(MouseEvent me) {}     

 }



Druga wersja programu wykorzystuje obiekt klasy Canvas jako kanwę rysunku. Tym razem program tworzy w pamięci kolekcję rysowanych odcinków. Każdy następny odcinek jest dodawany do tej kolekcji. Polecenie repaint() czyści kanwę i rysuje od nowa całą kolekcję obiektów - odcinków.

W programie zastosowano klasę ArrayList z pakietu java.util.ArrayList.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;

public class Malarz1 {


   public static void main(String[] args) {
    Okno ok = new Okno();
    ok.setVisible(true);
   }
}

class Okno extends JFrame {


   Kanwa k;
   Okno() {
      setSize(400,300);
      setDefaultCloseOperation(3);
      k=new Kanwa();
      add(k);
   }
}

class Kanwa extends Canvas implements MouseMotionListener, MouseListener {


    
    // tworzenie kolekcji obiektów klasy  Odcinek
    ArrayList lamana = new ArrayList();
    
    int x0,y0;   // współrzędne początku każdego kolejnego odcinka
    
    Kanwa() {
       setBackground(Color.orange);
       addMouseListener(this);
       addMouseMotionListener(this);
    }

    public void paint(Graphics g) {


    // dla każdego obiektu z kolekcji lamana wykonaj polecenie: narysuj go
    for (Odcinek s : lamana)  g.drawLine(s.x1,s.y1,s.x2,s.y2);
    }

    
    // metody interfejsu MouseMotionListener


    public void mouseDragged(MouseEvent me) {
        int x1=me.getX();  // pobierz współrzędne kończ odcinka
        int y1=me.getY();

        // utwórz obiekty klasy Odcinek i dodaj go do kolekcji lamana


        Odcinek s = new Odcinek(x0,y0,x1,y1);  
        lamana.add(s);
        repaint();

        // przyjmij koniec bieżącego odcinka jako początek dla następnego odcinka


        x0=x1;
        y0=y1;
     }
   
     public void mouseMoved(MouseEvent me) {  }
   

     // metody interfejsu MouseListener


     public void mousePressed(MouseEvent me) {  
       x0=me.getX();
       y0=me.getY();
      }
     public void mouseReleased(MouseEvent me) {  }
     public void mouseClicked(MouseEvent me) { }
     public void mouseEntered(MouseEvent me) {  }
     public void mouseExited(MouseEvent me) {  }
}

class Odcinek{


   public int x1,y1,x2,y2;
   Odcinek (int a,int b,int c,int d){
      x1=a; y1=b; x2=c; y2=d;
   }
}

 

Ćwiczenie



Napisz program który rysuje kółka w miejscu kliknięcia myszą, a następnie:

  • łączy odcinkami środki kolejnych kółek

  • oblicza i wyświetla długość w pikselach ostatnio narysowanego odcinka


©absta.pl 2016
wyślij wiadomość

    Strona główna