Problem z obsługą zdarzenia w Javie

0

Witam,
Piszę do was ponieważ podczas pisania programu napotkałem ścianę, a że jestem osobą która dopiero się uczy i to w dodatku sama nie mogę sobie poradzić z problemem. Otóż piszę program, który ma reprezentować kalendarz. Wymyśliłem sobie to tak, że miesiąc będzie wyświetlany w panelu składającym się z 42 przycisków, każdy to jeden dzień (domyślnie mają być klikalne, żeby wprowadzać przepracowane godziny). Stworzyłem więc tablicę przycisków JButton[] tablicaButtonow = new JButton[41] następnie w pętli dodałem buttony do tablicy:

        panelMiesiac = new JPanel();
        panelMiesiac.setLayout(new GridLayout(6,7));

        for (int i=0; i<42; i++){
            int nr = 0;
            JButton b = new JButton();
            JPanel p = new JPanel();
            p.add(b);
            tablicaButtonow[i] = b;
            panelMiesiac.add(p);
        }
        return panelMiesiac;
    }

Po tym napisałem metodę, która za pomocą klasy LocalDate "generuje" aktualny miesiąc (dodaje nr dnia w buttonie zmienia jego kolor w przypadku niedzieli itd) oraz uzupełnia pozostałe pola o nr dni z poprzedniego miesiąca oraz następnego. I ta metoda działa dobrze, umieszczam ją w konstruktorze i otrzymuję widok aktualnego miesiąca, tak jakbym sobie tego życzył.
Problem pojawił się gdy chciałem do przycisku poprzedni i następny miesiąc dodać ActionListener a w nim podobną metodę jak ta, która generuje aktualny miesiąc. Okazuje się, że po kliknięciu nic się nie dzieje. Sprawdziłem to małymi kroczkami, napisałem prostą metodę w której po kliknięciu w przycisk poprzedni miał się zmienić kolor jednego z przycisku coś na zasadzie tablicaButtonow[1].setBackground(Color.BLUE) i okazuje się, że o ile IDE podpowiada mi metody odpowiednie do JButton to już tych metod po kliknięciu nie uznaje kompletnie. Domyślam się, że może chodzić o to, iż w tablicy teoretycznie na każdym indeksie jest button o nazwie b ale czy w takim razie nie powinno być tak, że w konstruktorze też by to nie zadziałało?

Byłbym bardzo wdzięczny za wszystkie ewentualne podpowiedzi jak to rozwiązać, a może moje podejście było zbyt naiwne i za bardzo chciałem zautomatyzować działanie tego programu?
Dziękuję i pozdrawiam!

0

Tyvrel, dziekuję za zainteresowanie moim problemem. To jest metoda, której używam do generowania kalendarza na aktualny miesiąc (wymaga nieco lub dużo szlifu ale w konstruktorze działa dokładnie tak, jakbym sobie tego życzył). Chciałem użyć właściwie tej samej metody to wyświetlania poprzedniego i kolejnego miesiąca, tj. wrzucić ją w ActionListener i może przerobić tak, żeby przyjmowała odpowiednie argumenty, które "przestawią" kalendarz na odpowiedni miesiąc, niestety tak jak pisałem nie działa ona po kliknięciu w przycisk.

LocalDate dataAktalna = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()); // zmienna przechowująca aktualną datę, zmieniona by był w niej zawsze 1 dzień

private void generatorKalendarza(){
        int iloscDni = dataAktalna.lengthOfMonth(); /// pobranie ilości dni danego miesiąca
        int indexPierwszegoDnia = (dataAktalna.getDayOfWeek().getValue() - 1); // pobranie wartości (numeru) pierwszego dnia miesiąca (odejmuję 1 ponieważ getValue() rozpoczyna się od 1 a tablica od 0
        int nrDnia = 1; // zmienna która służy do numerowania buttonów danego dnia
        int miesiac = (dataAktalna.getMonth().getValue() - 1); // zmienna która, przechowuje nr poprzedniego miesiąca, stąd - 1
        int rok = dataAktalna.getYear(); // pobranie aktualnego roku

            if (miesiac == 0){ // zabezpieczenie - gdy miesiąc = 0 ustawiam miesiąc na grudzień, a rok dekrementuję
                miesiac = 12;
                rok --;
            }

        LocalDate dataMiesiacPoprzedni = LocalDate.of(rok, miesiac, 1); // deklarowanie kolejnej zmiennej dla miesiąca poprzedniego
        int nrDnia2 = dataMiesiacPoprzedni.lengthOfMonth() - (indexPierwszegoDnia - 1);  // pobieranie ilości dni poprzedniego miesiąca (służy podobie do zmiennej nrDnia ale odpowiada za miesiąc poprzedni podczas wyświetlania
        etykieta.setText(""+iloscDni2);

        for (int i = 0; i < indexPierwszegoDnia; i++){ // pętla uzupełniająca dni w buttonach miesiącem poprzednim 
            tablicaButtonow[i].setText(""+nrDnia2);
            tablicaButtonow[i].setVisible(true);
            tablicaButtonow[i].setEnabled(false);
            tablicaButtonow[i].setBackground(kolorButtonN);
            nrDnia2++;
        }


        for (int i = indexPierwszegoDnia; i < iloscDni + indexPierwszegoDnia; i++){ // pętla uzupełniająca dni w buttonach w miesiącu aktualnym
            tablicaButtonow[i].setText(""+nrDnia);
            tablicaButtonow[i].setVisible(true);

            if (i == 6 || i == 13 || i == 20 || i == 27 || i == 34 || i == 41){

                tablicaButtonow[i].setBackground(niedziela);
            }
            else if (i == 5 || i == 12 || i == 19 || i == 26 || i == 33 || i == 40){
                tablicaButtonow[i].setBackground(sobota);
            }
            else{
                tablicaButtonow[i].setBackground(kolorButton);
            }
            miesiacRok.setText(""+tlumacz(dataAktalna.getMonth().getValue())+" "+rok); // metoda "tłumacz" służy do tłumaczenia dni miesiąca z angielskiego na polski
            nrDnia++;
        }

        nrDnia = 1; // ustawienie nrDnia na 1 ponieważ kolejny miesiąc zawsze zaczyna się od 1 

        for (int i = (iloscDni + indexPierwszegoDnia); i < 41; i++){ // pętla uzupełniająca pozostałe, puste buttony nr dnia następnego miesiąca
            tablicaButtonow[i].setText(""+ nrDnia);
            tablicaButtonow[i].setVisible(true);
            tablicaButtonow[i].setEnabled(false);
            tablicaButtonow[i].setBackground(kolorButtonN);
            nrDnia++;
        }
    }

Jak widać sama metoda chociaż parę linijek posiada to cudów nie robi po prostu dodaje tekst zmienia kolor buttonów o indeksie równym zmiennej "i" z pętli.
Mam nadzieję, że nie buchniesz śmiechem patrząc na te wypociny :)

Dodałem załącznik ze zdjęciem jak to wygląda jak działa (mam nadzieję, że gdzieś to widać)

0

Nie wiem czy dobrze rozumiem Twój problem, bo trochę chaotycznie to opisujesz. Ale spróbuj w parametrach tej metody przekazywać datę, czyli nie:

private void generatorKalendarza(){
        int iloscDni = dataAktalna.lengthOfMonth(); /// pobranie ilości dni danego miesiąca
        int indexPierwszegoDnia = (dataAktalna.getDayOfWeek().getValue() - 1); // pobranie wartości (numeru) pierwszego dnia miesiąca (odejmuję 1 ponieważ getValue() rozpoczyna się od 1 a tablica od 0
        int nrDnia = 1; // zmienna która służy do numerowania buttonów danego dnia

itd..

tylko:

private void generatorKalendarza(TypDaty data){
        int iloscDni = data.lengthOfMonth(); /// pobranie ilości dni danego miesiąca
        int indexPierwszegoDnia = (data.getDayOfWeek().getValue() - 1); // pobranie wartości (numeru) pierwszego dnia miesiąca (odejmuję 1 ponieważ getValue() rozpoczyna się od 1 a tablica od 0
        int nrDnia = 1; // zmienna która służy do numerowania buttonów danego dnia

itd..

I w tym Twoim konstruktorze, wywoływać generatorKalendarza(LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()))
a w listenerze cos w stylu generatorKalendarza(LocalDate.now().minusMonth(1).with(TemporalAdjusters.firstDayOfMonth()));

Ale to trochę wróżenie z fusów, bo jak wspomniałem wyżej trochę chaotycznie to opisujesz i mało kodu pokazałeś, więc ciężko znaleźć ten błąd.

0

GigaBajt, to może zróbmy tak:

Tutaj jest cały mój kod (jest jeszcze klasa ramki dziedzicząca pod JFrame, tam ustawiam widoczność koniec programu po zamknięciu itd):

package zadanie;

import javax.swing.*;
import java.awt.*;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;


class Panel extends JPanel {
    private JButton[] tablicaButtonow = new JButton[42];
    private JButton nastepny, poprzedni;
    private JLabel miesiacRok;
    private Color kolorButton = new Color(116, 185, 255);
    private Color kolorButtonN = new Color(255,255,255);
    private Color niedziela = new Color(0, 184, 148);
    private Color sobota = new Color(85, 239, 196);
    private Color etykietaKolor = new Color(255, 211, 42);
    private JLabel etykieta = new JLabel("");
    private LocalDate dataAktualna = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());


    Panel(){

        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
        add(getMiesiacEtykieta());
        add(getDniTygPanel());
        add(Box.createRigidArea(new Dimension(0,5)));
        add(getMiesiacPanel());
        getDniTygPanel().setAlignmentX(Component.CENTER_ALIGNMENT);
        getMiesiacPanel().setAlignmentX(Component.CENTER_ALIGNMENT);
        generatorKalendarza();
    }

    private JComponent getMiesiacPanel(){
        JPanel panelMiesiac = new JPanel();
        panelMiesiac.setLayout(new GridLayout(6,7));
        panelMiesiac.setMaximumSize(new Dimension(710,460));
        panelMiesiac.setPreferredSize(new Dimension(710,460));
        panelMiesiac.setMaximumSize(new Dimension(710,460));
        
        for (int i=0; i<42; i++){
            JButton b = new JButton();
                b.setMaximumSize(new Dimension(95,70));
                b.setPreferredSize(new Dimension(95,70));
                b.setMaximumSize(new Dimension(95,70));
                b.setBorderPainted(false);
                b.setRolloverEnabled(false);
                b.setVisible(true);
            JPanel p = new JPanel();
            p.add(b);
            tablicaButtonow[i] = b;
            panelMiesiac.add(p);
        }
        return panelMiesiac;
    }

    private JComponent getDniTygPanel(){
        JPanel dniPanel = new JPanel();
            dniPanel.setBackground(etykietaKolor);
            dniPanel.setMinimumSize(new Dimension(700,35));
            dniPanel.setPreferredSize(new Dimension(700,35));
            dniPanel.setMaximumSize(new Dimension(700,35));
        String[] spisDni = {"pn.", "wt.", "śr.", "czw.", "pt.", "sob.", "niedz."};

        for (int i = 0; i < 7; i++){
            JLabel e = new JLabel("", JLabel.CENTER);
                e.setMinimumSize(new Dimension(95,25));
                e.setPreferredSize(new Dimension(95,25));
                e.setMaximumSize(new Dimension(95,25));
                e.setLayout(new GridLayout(1,7));
                e.setText(spisDni[i]);
                dniPanel.add(e);
        }
        return dniPanel;
    }

    private JComponent getMiesiacEtykieta(){
        JPanel miesiacEtykieta = new JPanel();
            miesiacEtykieta.setMinimumSize(new Dimension(700,45));
            miesiacEtykieta.setPreferredSize(new Dimension(700,45));
            miesiacEtykieta.setMaximumSize(new Dimension(700,45));
            miesiacEtykieta.setBackground(kolorButtonN);
            miesiacEtykieta.revalidate();
        nastepny = new JButton();
            ImageIcon ikonaN = new ImageIcon("n.png");
            nastepny.setMinimumSize(new Dimension(25,25));
            nastepny.setPreferredSize(new Dimension(25,25));
            nastepny.setMaximumSize(new Dimension(25,25));
            nastepny.setIcon(ikonaN);
            nastepny.setBorderPainted(false);
            nastepny.setBackground(new Color(255,255,255));
//            nastepny.addActionListener();
        poprzedni = new JButton();
            ImageIcon ikonaP = new ImageIcon("p.png");
            poprzedni.setMinimumSize(new Dimension(25,25));
            poprzedni.setPreferredSize(new Dimension(25,25));
            poprzedni.setMaximumSize(new Dimension(25,25));
            poprzedni.setIcon(ikonaP);
            poprzedni.setBorderPainted(false);
            poprzedni.setBackground(new Color(255,255,255));

        miesiacRok = new JLabel("MIESIĄC_ROK", JLabel.CENTER);
            miesiacRok.setMinimumSize(new Dimension(620,25));
            miesiacRok.setPreferredSize(new Dimension(620,25));
            miesiacRok.setMaximumSize(new Dimension(620,25));

        miesiacEtykieta.add(poprzedni);
        miesiacEtykieta.add(miesiacRok);
        miesiacEtykieta.add(nastepny);

        return miesiacEtykieta;
    }

    private void generatorKalendarza(){
        int iloscDni = dataAktualna.lengthOfMonth(); /// pobranie ilości dni danego miesiąca
        int indexPierwszegoDnia = (dataAktualna.getDayOfWeek().getValue() - 1); // pobranie wartości (numeru) pierwszego dnia miesiąca (odejmuję 1 ponieważ getValue() rozpoczyna się od 1 a tablica od 0
        int nrDnia = 1; // zmienna która służy do numerowania buttonów danego dnia
        int miesiac = (dataAktualna.getMonth().getValue() - 1); // zmienna która, przechowuje nr poprzedniego miesiąca, stąd - 1
        int rok = dataAktualna.getYear(); // pobranie aktualnego roku

            if (miesiac == 0){ // zabezpieczenie - gdy miesiąc = 0 ustawiam miesiąc na grudzień, a rok dekrementuję
                miesiac = 12;
                rok --;
            }

        LocalDate dataMiesiacPoprzedni = LocalDate.of(rok, miesiac, 1); // deklarowanie kolejnej zmiennej dla miesiąca poprzedniego
        int nrDnia2 = dataMiesiacPoprzedni.lengthOfMonth() - (indexPierwszegoDnia - 1);  // pobieranie ilości dni poprzedniego miesiąca (służy podobie do zmiennej nrDnia ale odpowiada za miesiąc poprzedni podczas wyświetlania
        etykieta.setText(""+nrDnia);

        for (int i = 0; i < indexPierwszegoDnia; i++){ // pętla uzupełniająca dni w buttonach miesiącem poprzednim
            tablicaButtonow[i].setText(""+nrDnia2);
            tablicaButtonow[i].setVisible(true);
            tablicaButtonow[i].setEnabled(false);
            tablicaButtonow[i].setBackground(kolorButtonN);
            nrDnia2++;
        }


        for (int i = indexPierwszegoDnia; i < iloscDni + indexPierwszegoDnia; i++){ // pętla uzupełniająca dni w buttonach w miesiącu aktualnym
            tablicaButtonow[i].setText(""+nrDnia);
            tablicaButtonow[i].setVisible(true);

            if (i == 6 || i == 13 || i == 20 || i == 27 || i == 34 || i == 41){

                tablicaButtonow[i].setBackground(niedziela);
            }
            else if (i == 5 || i == 12 || i == 19 || i == 26 || i == 33 || i == 40){
                tablicaButtonow[i].setBackground(sobota);
            }
            else{
                tablicaButtonow[i].setBackground(kolorButton);
            }
            miesiacRok.setText(""+tlumacz(dataAktualna.getMonth().getValue())+" "+rok); // metoda "tłumacz" służy do tłumaczenia dni miesiąca z angielskiego na polski
            nrDnia++;
        }

        nrDnia = 1; // ustawienie nrDnia na 1 ponieważ kolejny miesiąc zawsze zaczyna się od 1

        for (int i = (iloscDni + indexPierwszegoDnia); i < 42; i++){ // pętla uzupełniająca pozostałe, puste buttony nr dnia następnego miesiąca
            tablicaButtonow[i].setText(""+ nrDnia);
            tablicaButtonow[i].setVisible(true);
            tablicaButtonow[i].setEnabled(false);
            tablicaButtonow[i].setBackground(kolorButtonN);
            nrDnia++;
        }
    }

    private String tlumacz(int a){
        String miesiacPoPolsku = "";
        switch (dataAktualna.getMonth()){
            case JANUARY: miesiacPoPolsku = "Styczeń"; break;
            case FEBRUARY: miesiacPoPolsku = "Luty"; break;
            case MARCH: miesiacPoPolsku = "Marzec"; break;
            case APRIL: miesiacPoPolsku = "Kwiecień"; break;
            case MAY: miesiacPoPolsku = "Maj"; break;
            case JUNE: miesiacPoPolsku = "Czerwiec"; break;
            case JULY: miesiacPoPolsku = "Lipiec"; break;
            case AUGUST: miesiacPoPolsku = "Sierpień"; break;
            case SEPTEMBER: miesiacPoPolsku = "Wrzesień"; break;
            case OCTOBER: miesiacPoPolsku = "Październik"; break;
            case NOVEMBER: miesiacPoPolsku = "Listopad"; break;
            case DECEMBER: miesiacPoPolsku = "Grudzień"; break;
        }
        return miesiacPoPolsku;
    }
}

I teraz jak wywołam metodę generatorKalendarza(); w konstruktorze klasy Panel to ta metoda działa, a jak ją mieszczę pod ActionListener to nie działa i chciałem zapytać dlaczego tak się dzieję? ActionListener dodaje mniej więcej tak: button.addActionListener(e -> generatorKalendarza); używam Lambdy, nie korzystam z implementacji interfejsu.

Prościej już chyba nie umiem tego wyjaśnić

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