java obsluga zdarzen

0

Witam, napisałem prosty program który zlicza kliknięcia przycisku i wypisuje w komponencie label ilość tych kliknięć. Niestety mam problem z obsługą zdarzeń. proszę o opinie kodu i pomoc z obslugą zdarzeń ;):

import javax.swing.*;


/**
 *
 * @author marcin
 * program bedzie zliczal klikniecia przycisku
 */

class Okno{
    private JPanel jPanel = new JPanel();
    private JFrame jFrame = new JFrame();
    private JButton jButton = new JButton();
    private JLabel jLabel = new JLabel();
    private GridLayout gridLayout = new GridLayout(2, 1);
    private ActionListener actionListener;
    private ActionEvent actionEvent;

    public Okno() {
    }
   
    void createWindow(){
        int w = 200;
        int h = 100;
        jPanel.setLayout(gridLayout);
       
        jButton.setText("kliknij");
        jButton.addActionListener(actionListener);
       
        jLabel.setText("0");
       
        jFrame.setTitle("zliczacz klikniec !!");
       
        jFrame.setLocation(600, 300);
        jFrame.setSize(w, h);
        jFrame.add(jPanel);
       
        jPanel.add(jButton);
        jPanel.add(jLabel);
       
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.setVisible(true);
    }
   
    void obslugaZdarzen(){
        int i = 0;
        Object object = actionEvent.getSource();
        if(object == jButton){
            i = i + 1;
            jLabel.setText(String.valueOf(i));
        }
    }
}

public class Java_swing_licznik {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                Okno window = new Okno();
                window.createWindow();
                window.obslugaZdarzen();
            }
        });
    }
} 
0

Nie ma co rozciągać zbędnie kodu. ;) Gotowiec do przeanalizowania:

// Licznik.java

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

class Util {
    public static void run(final JFrame f, final int width, final int height) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setSize(width, height);
                f.setVisible(true);
            }
        });
    }
}

public class Licznik extends JFrame {
    public Licznik() {
        super("Zliczacz klikniec !!");
        setLayout(new GridLayout(2,1));

        final JLabel label = new JLabel("0");
        JButton b = new JButton("Kliknij");

        add(label);
        add(b);

        b.addActionListener(new ActionListener() {
            private int count = 0;
            public void actionPerformed(ActionEvent e) {
                label.setText(++count + ""); // Rzutowanie na String.
            }
        });
    }

    public static void main(String[] args) {
        Util.run(new Licznik(), 300, 100);
    }
}
0

dziękuje, ale chce żeby ktoś wytłumaczył mi to na moim przykładzie

0

Nie da się, Twój przykład jest całkowicie błędny.

0

co jest źle??

0

Mechanizm zdarzeń działa tak:

  1. tworzysz komponent
  2. dodajesz do niego słuchacza zdarzeń (add...Listener();)
  3. słuchacz zdarzeń albo jest klasą anonimową albo klasą, która implementuje określony interfejs
  4. w momencie zajścia danego zdarzenia (np. kliknięcie przycisku) wywoływana jest metoda actionPerformed() wszystkich słuchaczy podłączonych do danego komponentu

Teraz sam sobie odpowiedz, co u Ciebie jest zle...

0

po zamianie i działa tak jak chciałem ale przydała by się porada co do zmian kosmetycznych.

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package java_swing_licznik;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;



/**
 *
 * @author marcin
 * program bedzie zliczal klikniecia przycisku
 */

class Okno implements ActionListener{
    private JPanel jPanel = new JPanel();
    private JFrame jFrame = new JFrame();
    private JButton jButton = new JButton();
    private JLabel jLabel = new JLabel();
    private GridLayout gridLayout = new GridLayout(2, 1);
    private int i = 0;

    public Okno() {
    }
    
    void createWindow(){
        int w = 200;
        int h = 100;
        jPanel.setLayout(gridLayout);
        
        jButton.setText("kliknij");
        
        
        jLabel.setText("0");
        
        jFrame.setTitle("zliczacz klikniec !!");
        
        jFrame.setLocation(600, 300);
        jFrame.setSize(w, h);
        jFrame.add(jPanel);
        
        jPanel.add(jButton);
        jPanel.add(jLabel);
        
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.setVisible(true);
        jButton.addActionListener(this);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        i = i + 1;
        jLabel.setText(String.valueOf(i));
    }
    
}

public class Java_swing_licznik {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                Okno window = new Okno();
                window.createWindow();
                //window.obslugaZdarzen();
            }
        });
    }
}
 
0
  1. Po to masz w Javie inkrementację (++), żeby z niej korzystać. Dzięki temu nie popełnisz takich błędów jak i = 1+1 zamiast i = i + 1. Jeżeli zamiast "i" będziesz mieć skomplikowane wyrażenie (np. komórkę tablicy) to inkrementacja jest jeszcze przydatniejsza i bezpieczniejsza. Nich zgadnę - uczyłeś się wcześniej Pascala lub Basica?

  2. Zamiast

jLabel.setText("0");

używaj tego samego wyrażenia jakie użyłeś w actionPerformed. Po pierwsze dlatego, że unikniesz możliwej pomyłki, a w przypadku skomplikowanej obsługi będziesz mógł fragment taki jak u Ciebie jLabel.setText(String.valueOf(i));

 wrzucić do prywatnej procedury odpalanej z wielu miejsc. Po drugie dlatego, że "0" jest tu "magiczną wartością". Niczego nikomu nie mówi.

3. Niektórzy uważają, że struktura klas swingowych powinna odpowiadać strukturze rodzicielskiej okienek i komponentów. Czasem upraszcza to kod. U Ciebie okno, panel oraz komponenty są na tym samym poziomie dostępu, więc jak będziesz miał ich więcej, to zwyczajnie się pogubisz co jest czym, a na dodatek będziesz musiał wymyślić taki system nazewnictwa, żeby nie konfliktowały ze sobą. Przy takim podejściu kod okienka ma łatwy dostęp nawet do komponentów paneli na którymś poziomie dostępności. Gdyby okno było klasą, to tak jakbyś wszystkie elementy ustawił z atrybutem public. Prowadzi to do mnóstwa błędów. Bezpieczną zasadą jest, że kod okna i każdego innego elementu ma bezpośredni dostęp tylko do swoich bezpośrednich komponentów i niczego więcej.
Dlatego zwykle jest tak, że klasa dziedziczy po oknie, jej komponentami są klasy dziedziczące po panelu, których komponenty są elementami, które będą w nich umieszczone. W ten sposób okno nie wtrynia się do tego co robią panele, a panele nie mogą nic grzebać w oknie.
Oczywiście czasem są potrzebne wyjątki - ale powinny być one wyjątkami, a nie zasadą. Wtedy zazwyczaj przekazuje się innej klasie referencję do obiektu, który ma dostęp do danych, które chce się zmodyfikować w innym miejscu. Na przykład jeżeli panel ma kontrolkę, która zmienia ramkę okna, to powinien uzyskać referencję do tego okna i za pośrednictwem metod tego okna zmienić tę ramkę.
JFrame powinno być komponentem klasy (lub nawet elementem jakiegoś kontenera) jeżeli klasa takimi oknami żongluje - na przykład często je zmienia, otwiera, zamyka itp.
0
  1. jeżeli chodzi o użycie i = i +1 zamiast i++ to celowo to użyłem
    dziękuje za informację muszę teraz to sobie przeanalizować ;), przerabiam teraz ten program aby klasa okno dziedziczyła z JFrame, oraz żeby klasa okno była w drugim pliku. i pogrupować komponenty w tej klasie
0

poprawiłem trochę ten program, klasy są teraz w osobnych plikach i komponenty trochę uporządkowałem, dodałem komponent JButton i za jego pomocą po kliknięciu można wyjść z programu, no i czekam na uwagi ;), o to kod:

/*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package java_swing_licznik_v2;

    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;

    /**
     *
     * @author marcin
     */
    public class KlasaOkno extends JFrame implements ActionListener{
       
        private final int wysokosc = 100;
        private final int szerokosc = 200;
        private final int pozycja_okna_x = 400;
        private final int pozycja_okna_y = 200;
        private JPanel jPanel;
        private JButton jButtonLicz;
        private JButton jButtonWyjscie;
        private JLabel jLabel;
        private int i = 0;

        public KlasaOkno(){   
            jPanel = new JPanel();
            jLabel = new JLabel();
            jButtonLicz = new JButton();
            jButtonWyjscie = new JButton();
           
            setTitle("zliczacz klikniec !!");
            setLocation(pozycja_okna_x, pozycja_okna_y);
            setSize(szerokosc, wysokosc);
            setVisible(true);
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            add(jPanel);
           
            jPanel.setLayout(new GridLayout(3, 1));
            jPanel.add(jLabel);
            jPanel.add(jButtonLicz);
            jPanel.add(jButtonWyjscie);
           
            jLabel.setText("0");
           
            jButtonLicz.setText("kliknij");
            jButtonLicz.addActionListener(this);
           
            jButtonWyjscie.setText("wyjscie");
            jButtonWyjscie.addActionListener(this);
        }

       
        @Override
        public void actionPerformed(ActionEvent e) {
            Object zrodlo = e.getSource();
            if(zrodlo == jButtonLicz){
                ++i;
                jLabel.setText(String.valueOf(i));
            } else if(zrodlo == jButtonWyjscie){
                System.exit(0);
            }
        }
       
    }

     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package java_swing_licznik_v2;

    import javax.swing.SwingUtilities;

    /**
     *
     * @author marcin
     */
    public class Java_swing_licznik_v2 {

        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            // TODO code application logic here
            SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {
                    KlasaOkno klasaOkno = new KlasaOkno();
                }
            });
        }
    }
 
0

ok dzięki za pomoc, postaram się jeszcze to zmienić, możesz napisać jak na tym prostym programie mógłbym użyć wzorca MVC??

0

Najprościej abyś przeczytał to co napisali lepsi fachowcy:
http://www.oracle.com/technetwork/articles/javase/index-142890.html
Jeżeli masz problem z angielskim, to google-translator/chrome powinno wystarczyć.

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