Jak zrobić KeyEvents w klasie Controller? Efekt 3 tygodni nauki. Kilka pytan od Newbie.

0

Cześć Wszystkim!

Zwracam się do Was z prośbą o pomoc ponieważ nie bardzo mam już pomysł jak rozwiązać problem. Wybaczcie jeżeli pytanie należy do tych "głupich" ale próbowałem coś wyszukać w Google i niestety nie udało mi się. Uczę się programować łącznie od ok 3 tygodni i jest to praktycznie moje pierwsze doświadczenie z programowaniem w życiu więc nie wykluczam, że coś źle szukałem:P

Ostatnio skończyłem dwa poradniki odnośnie Javy i staram się teraz jak najwięcej popracować nad zdobytą wiedzą teoretyczną wykorzystując ja w praktyce, jednocześnie googlując jakieś nowe rzeczy, które uznam za ciekawe i przydatne na przyszłość.

Wczoraj zacząłem pisać swoja drugą własną aplikację i jestem nawet zadowolony z dotychczasowego efektu jednak chciałbym iść krok dalej w swojej nauce i pomyślałem, że fajnie byłoby dodatkowo sterować tą aplikacją za pomocą klawiatury.

Nie mam problemu z przechwytywaniem eventów z klawiatury w klasie Main jednak aplikacje pisałem tak jak było w poradnikach czyli rozbiłem wszystko na osobne pliki. Grafika w FXML, wygląd elementów w CSS oraz sterowanie w Controller.java.

Pytanie moje brzmi czy jest jakiś łatwy sposób na przechwytywanie eventów z klawiatury w klasie Controller? Może jakiś prosty aby odwołać się do pola Scene z klasy Main z której mógłbym wyciągnąć eventy tak jak w owej klasie i na ich podstawie coś zmieniać w kontrolerze?

Na przyszłość chciałbym też sprawić aby aplikacja zapisywała wyniki na serwer. Czytałem ostatnio w informacjach o dropboxie, że można tam się chyba dość łatwo połączyć bo udostępniają całe api do tego i wykorzystać to jako prosty serwer na dane w aplikacjach testowych. Co o tym myślicie?

Chętnie poczytam jakąś krytykę odnośnie obecnego kodu, aby lepiej pisać na przyszłość oraz może jakieś sugestie w jaką stronę dalej iść? Przypominam, że dopiero się uczę i sam widzę już drobne rzeczy do poprawy a to jest moja pierwsza aplikacja, która robi cokolwiek więcej niż wyświetla liczby :P

Póki co chciałbym osiągnąć poziom, który pozwoli mi podjąć prace na stanowisku Juniora w Javie a później myślałem o Androidzie jak ogarnę podstawy pisania aplikacji w Javie na komputerze.

Poniżej oczywiście kod:)
Dorzuciłem plik .jar jeżeli ktoś jest ciekawy jak działa całość z dźwiękami jednak nie wiem jeszcze jak obsłużyć plik *.src z zapisanym rekordem oby później .jar umiał dane w tym zapisać oraz odczytać więc tu kolejne pytanie o wskazówki :)

Main.java

package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;


public class Main extends Application {


    @Override
    public void start(Stage primaryStage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("/fxml/sample.fxml"));
        primaryStage.setTitle("Gierka");
        primaryStage.setScene(new Scene(root, 350, 300));
        primaryStage.show();
        primaryStage.setResizable(false);

        ////////////////////////////////////////////////////////////////////////////////
        // Test KeyPressed
        primaryStage.getScene().setOnKeyPressed(event -> {
            System.out.println(event.getCode().toString());
        });

    }


    public static void main(String[] args) {
        launch(args);
    }
}
package sample;

import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.media.AudioClip;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.util.Duration;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;


public class Controller {

    @FXML
    ImageView img11, img12, img13, img21, img22, img23;
    @FXML
    Button startButton, resumeButton, pauseButton, restartButton, restartButton2, restartRekord;
    @FXML
    Label lol;
    @FXML
    CheckBox mCheckBoxSounds, mCheckBoxMusic, mCheckBoxNiesmiertelnosc;

    List<ImageView> mListaImageViews;
    Integer mPunkty = 0;
    StringProperty pkt, poziom, wynik;
    Timeline mTimelineGry;
    Integer mWylosowanePole = 0;
    Integer mObecnyPoziom = 1;
    Integer mEventowNaTimeline = 5;
    Integer mRekordowyWynik = 0;
    Integer mDlugoscEventu = 1000;
    Integer mMinCzasEventu = 210;
    Boolean mCzyGraDalej = true;

    MediaPlayer mMediaPlayer = new MediaPlayer(new Media(getClass().getResource("/audio/lol.m4a").toExternalForm()));

    AudioClip mSoundClick = new AudioClip(getClass().getResource("/audio/click.mp3").toExternalForm());
    AudioClip mSoundError = new AudioClip(getClass().getResource("/audio/error.mp3").toExternalForm());
    AudioClip mSoundHappy = new AudioClip(getClass().getResource("/audio/happy.mp3").toExternalForm());

    Image mObrazOrange = new Image("/img/orangesq.png");
    Image mObrazYellow = new Image("/img/yellowsq.png");
    Image mObrazGreen = new Image("/img/green.png");


    public Controller() {

        pkt = new SimpleStringProperty();
        poziom = new SimpleStringProperty();
        wynik = new SimpleStringProperty();
        setPkt(String.format("Punkty: %d", mPunkty));
        setPoziom(String.format("Poziom: %d", mObecnyPoziom));
        mMediaPlayer.setVolume(0.2);

        mRekordowyWynik = odczytPliku();
        setWynik(String.format("Najlepszy: %d", mRekordowyWynik));
    }


    public String getWynik() {
        return wynik.get();
    }

    public StringProperty wynikProperty() {
        return wynik;
    }

    public void setWynik(String wynik) {
        this.wynik.set(wynik);
    }

    public String getPoziom() {
        return poziom.get();
    }

    public void setPoziom(String poziom) {
        this.poziom.set(poziom);
    }

    public StringProperty poziomProperty() {
        return poziom;
    }

    public String getPkt() {
        return pkt.get();
    }

    public void setPkt(String pkt) {
        this.pkt.set(pkt);
    }

    public StringProperty pktProperty() {
        return pkt;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // ZACHOWANIE APLIKACJI

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //Inicjalizacja planszy


    public void start(ActionEvent event) {
        im();
        mMediaPlayer.play();
        restartButton.setVisible(false);
        restartRekord.setVisible(false);
        for (ImageView iv : mListaImageViews) {
            iv.setOnMouseClicked(event1 -> koniec());
        }

    }

    private void im() {

        startButton.setVisible(false);
        pauseButton.setVisible(true);
        petlaGry();
        mTimelineGry.play();
        restart();

        mListaImageViews = new ArrayList<>();
        mListaImageViews.add(img11);
        mListaImageViews.add(img12);
        mListaImageViews.add(img13);
        mListaImageViews.add(img21);
        mListaImageViews.add(img22);
        mListaImageViews.add(img23);

        for (ImageView iv : mListaImageViews) {
            iv.setImage(mObrazOrange);
        }
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //Start Timeline i jego zachowanie

    private void petlaGry() {

        nowyTimeline();
        mTimelineGry.getKeyFrames().add(new KeyFrame(Duration.millis(mDlugoscEventu), event1 -> {
            eventGry();
        }));
    }


    private void eventGry() {

        losowaniePola();
        setPoziom(String.format("Poziom: %d", mObecnyPoziom));
        for (ImageView pole : mListaImageViews) {
            if (mListaImageViews.get(mWylosowanePole).equals(pole)) {
                pole.setImage(mObrazGreen);
                pole.setOnMouseClicked(event -> {
                    mCzyGraDalej = true;
                    mPunkty += mObecnyPoziom;
                    setPkt(String.format("Punkty: %d", mPunkty));
                    pole.setImage(mObrazOrange);
                    sound(mSoundClick);
                    pole.setOnMouseClicked(event1 -> {
                        if (!mCheckBoxNiesmiertelnosc.isSelected()) {
                            koniec();
                        } else pole.setOnMouseClicked(null);

                    });
                });

            } else {
                pole.setImage(mObrazOrange);
                if (!mCheckBoxNiesmiertelnosc.isSelected()) {
                    pole.setOnMouseClicked(event -> koniec());
                } else pole.setOnMouseClicked(null);


            }

        }
        czyNiesmiertelny();

    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //Metody

    private void losowaniePola() {
        Random random = new Random();
        int poprzedniaLosowa = mWylosowanePole;
        do {
            mWylosowanePole = random.nextInt(5) + 1;
        } while (mWylosowanePole == poprzedniaLosowa);
    }

    private void czyNiesmiertelny() {
        if (!mCheckBoxNiesmiertelnosc.isSelected()) {
            if (mCzyGraDalej == false) {
                koniec();
            }
            mCzyGraDalej = false;
        }
    }

    private void sound(AudioClip sound) {
        if (mCheckBoxSounds.isSelected()) {
            sound.play();
        }
    }

    private void infoZapis() {
        if (mPunkty > mRekordowyWynik) {
            mRekordowyWynik = mPunkty;
            sound(mSoundHappy);
            wynik.set(String.format("Najlepszy: %d%nNowy rekord!", mRekordowyWynik));
        } else {
            sound(mSoundError);
            wynik.set(String.format("Najlepszy: %d%nPrzegrałeś.", mRekordowyWynik));
        }
    }

    private void koniec() {

        stopButtony();
        mTimelineGry.stop();
        mMediaPlayer.stop();
        restartButton2.setVisible(true);
        startButton.setVisible(true);
        pauseButton.setVisible(false);
        resumeButton.setVisible(false);
        startButton.setVisible(false);
        restartButton.setVisible(false);
        startButton.setVisible(true);
        infoZapis();
        zapisPliku(mRekordowyWynik);


    }


    private void stopButtony() {
        for (ImageView iv : mListaImageViews) {
            iv.setOnMouseClicked(null);
        }
    }

    private void nowyTimeline() {
        if (mTimelineGry != null && mTimelineGry.getStatus() == Animation.Status.RUNNING) {
            mTimelineGry.stop();
        }

        mTimelineGry = new Timeline();
        mTimelineGry.setCycleCount(mEventowNaTimeline);

        mTimelineGry.setOnFinished(event2 -> {
            mDlugoscEventu = (mDlugoscEventu * 95) / 100;
            if (mDlugoscEventu > mMinCzasEventu) {
                petlaGry();
                mTimelineGry.play();
                mObecnyPoziom++;
            } else {
                infoZapis();
                koniec();
            }
        });
    }

    private void restart() {
        mPunkty = 0;
        mDlugoscEventu = 1000;
        mObecnyPoziom = 1;
        mWylosowanePole = 0;
        restartButton.setVisible(false);
        setPkt(String.format("Punkty: %d", mPunkty));
        setPoziom(String.format("Poziom: %d", mObecnyPoziom));
        wynik.set(String.format("Najlepszy: %d", mRekordowyWynik));
        restartRekord.setVisible(true);
    }


    public void Pause(ActionEvent event) {
        mTimelineGry.pause();
        pauseButton.setVisible(false);
        resumeButton.setVisible(true);
        stopButtony();
        mMediaPlayer.pause();
        restartButton.setVisible(true);
    }

    public void resume(ActionEvent event) {
        mTimelineGry.play();
        pauseButton.setVisible(true);
        resumeButton.setVisible(false);
        restartButton.setVisible(false);
        mMediaPlayer.play();
    }

    public void restartGame(ActionEvent event) {
        im();
        for (ImageView iv : mListaImageViews) {
            iv.setImage(mObrazGreen);
        }
        mTimelineGry.stop();
        pauseButton.setVisible(false);
        resumeButton.setVisible(false);
        startButton.setVisible(true);
        restartButton2.setVisible(false);
        restartButton.setVisible(false);
        mMediaPlayer.stop();
        mCzyGraDalej = true;
    }

    public void checkBox(ActionEvent event) {
        if (mCheckBoxMusic.isSelected()) {
            mMediaPlayer.setMute(false);
        } else {
            mMediaPlayer.setMute(true);
        }

    }

    private void zapisPliku(Integer rekordowyWynik) {

        try (
                FileOutputStream fos = new FileOutputStream("Resources/dane/rekord.ser");
                ObjectOutputStream oos = new ObjectOutputStream(fos);

        ) {
            oos.writeObject(rekordowyWynik);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private int odczytPliku() {
        int liczba = 0;
        try (
                FileInputStream fis = new FileInputStream("Resources/dane/rekord.ser");
                ObjectInputStream ois = new ObjectInputStream(fis);
        ) {
            liczba = (int) ois.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return liczba;

    }


    public void restartRekord(ActionEvent event) {
        mRekordowyWynik = 0;
        zapisPliku(mRekordowyWynik);
        setWynik(String.format("Najlepszy: %d", mRekordowyWynik));
    }
}

Sample.fxml

<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<GridPane fx:controller="sample.Controller"
          xmlns:fx="http://javafx.com/fxml" alignment="TOP_CENTER" hgap="10" vgap="5"
          stylesheets="/css/sample.css"
          gridLinesVisible="false">


    <ImageView fx:id="img11"
               styleClass="Button-Image"
               GridPane.columnIndex="0"
               GridPane.rowIndex="1"
               fitHeight="100"
               preserveRatio="true"
    ></ImageView>

    <ImageView fx:id="img12"
               styleClass="Button-Image"
               GridPane.columnIndex="1"
               GridPane.halignment="CENTER"
               GridPane.rowIndex="1"
               fitHeight="100"
               preserveRatio="true"
    ></ImageView>

    <ImageView fx:id="img13"
               styleClass="Button-Image"
               GridPane.columnIndex="2"
               GridPane.rowIndex="1"
               fitHeight="100"
               preserveRatio="true"
    ></ImageView>

    <ImageView fx:id="img21"
               styleClass="Button-Image"
               GridPane.columnIndex="0"
               GridPane.rowIndex="2"
               fitHeight="100"
               preserveRatio="true"
    ></ImageView>

    <ImageView fx:id="img22"
               styleClass="Button-Image"
               GridPane.columnIndex="1"
               GridPane.halignment="CENTER"
               GridPane.rowIndex="2"
               fitHeight="100"
               preserveRatio="true"
    ></ImageView>

    <ImageView fx:id="img23"
               styleClass="Button-Image"
               GridPane.columnIndex="2"
               GridPane.rowIndex="2"
               fitHeight="100"
               preserveRatio="true"
    ></ImageView>


    <Button text="Start Game"
            fx:id="startButton"
            onAction="#start"
            GridPane.columnIndex="1"
            GridPane.rowIndex="0"
            GridPane.halignment="CENTER"
            GridPane.fillWidth="true"
    ></Button>

    <Button text="Pause"
            fx:id="pauseButton"
            visible="false"
            onAction="#Pause"
            GridPane.columnIndex="1"
            GridPane.rowIndex="0"
            GridPane.halignment="CENTER"
            GridPane.fillWidth="true"
    ></Button>

    <Button text="Resume"
            fx:id="resumeButton"
            visible="false"
            onAction="#resume"
            GridPane.columnIndex="1"
            GridPane.rowIndex="0"
            GridPane.halignment="CENTER"
            GridPane.fillWidth="true"
    ></Button>

    <Button text="Restart"
            fx:id="restartButton"
            visible="false"
            onAction="#restartGame"
            GridPane.columnIndex="2"
            GridPane.rowIndex="4"
            GridPane.halignment="CENTER"
            GridPane.fillWidth="true"
            styleClass="dark"
    ></Button>


    <Button text="Restart Game"
            fx:id="restartButton2"
            visible="false"
            onAction="#restartGame"
            GridPane.columnIndex="1"
            GridPane.rowIndex="0"
            GridPane.halignment="CENTER"
            GridPane.fillWidth="true"

    ></Button>


    <Label text="${controller.pkt}"
           GridPane.rowIndex="0"
           GridPane.columnIndex="0"
           GridPane.halignment="LEFT"
           styleClass="info"
    ></Label>

    <Label text="${controller.poziom}"
           GridPane.rowIndex="0"
           GridPane.columnIndex="2"
           GridPane.halignment="RIGHT"
           styleClass="info"
    ></Label>

    <StackPane GridPane.columnIndex="0"
               GridPane.columnSpan="2"
               GridPane.rowIndex="4"
               GridPane.halignment="LEFT"
               GridPane.valignment="TOP">

        <Label text="${controller.wynik}"
               StackPane.alignment="TOP_LEFT"
               styleClass="info"

        ></Label>

        <Button text="Restart rekord"
                fx:id="restartRekord"
                visible="true"
                onAction="#restartRekord"
                styleClass="dark"
                StackPane.alignment="BOTTOM_LEFT"
        ></Button>

    </StackPane>


    <VBox GridPane.rowIndex="4"
          GridPane.columnIndex="1"
          GridPane.halignment="RIGHT">


        <CheckBox text="Sounds"
                  fx:id="mCheckBoxSounds"
                  selected="true"
                  onAction="#checkBox"

        ></CheckBox>
        <CheckBox text="Music"
                  fx:id="mCheckBoxMusic"
                  selected="true"
                  onAction="#checkBox"

        ></CheckBox>
        <CheckBox text="Nieśmiertelność"
                  fx:id="mCheckBoxNiesmiertelnosc"
                  selected="false"
                  onAction="#checkBox"

        ></CheckBox>


    </VBox>


</GridPane>

Sample.css

.root{
-fx-background-color:
        #090a0c,
        linear-gradient(#38424b 0%, #1f2429 20%, #191d22 100%),
        linear-gradient(#20262b, #191d22),
        radial-gradient(center 50% 0%, radius 100%, rgba(114,131,148,0.9), rgba(255,255,255,0));
}
.label {
    -fx-text-fill: #ffe4c4;
}

.check-box{
-fx-text-fill: #ffe4c4;
}

.Button-Image{
     -fx-image: url('/img/green.png');
     -fx-image-width:100%;
     -fx-image-height:auto;
     -fx-translate-x:0.1;
     -fx-translate-y:0.1;
}

.info {
    -fx-font-size: 15; -fx-font-weight: bold;
}

.button {
    -fx-background-color:
        #c3c4c4,
        linear-gradient(#d6d6d6 50%, white 100%),
        radial-gradient(center 50% -40%, radius 200%, #e6e6e6 45%, rgba(230,230,230,0) 50%);
    -fx-background-radius: 30;
    -fx-background-insets: 0,1,1;
    -fx-text-fill: black;
    -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 3, 0.0 , 0 , 1 );
    -fx-font-weight: bold;
}
1

Ja standardowo robię to tak, że w klasie Controller dodaję sobie metodę z adnotacją @FXML o wdzięcznej nazwie initialize(), w której to metodzie ustawiam sobie wszystkie handlery. W Twoim przypadku nic nie stoi na przeszkodzie, żeby kod dodający EventHandler przenieść do klasy Controller.
Referencję do obiektu klasy Scene uzyskasz wywołując metodę getScene() na dowolnym elemencie do tej sceny dodanym (na Buttonie czy czymkowiek innym).
Jeżeli chodzi o zapis / odczyt z pliku to napisz dokładnie z czym masz problem. Jakiś kod tam widzę jest, jeżeli coś w nim nie działa rzuca jakieś wyjątki to wklej stack trace albo opisz co nie działa tak jak chcesz.
Ogólnie to pliki zapisywać musisz poza jarem, jeżeli korzystasz z jakichś plików, których zawartość ma być zmieniana przez program to muszą się one znaleźć poza jarem. Konfiguracja deployowania aplikacji w javaFX jest relatywnie prosta, jakbyś potrzebował to mam gdzieś gotowy plik Anta, który buduje aplikację do single jara z wbudowanymi wszystkimi zależnościami, zawnętrznymi natywnymi bibliotekami, zewnętrznymi zasobami, wbudowanym runtimem i plikiem exe do uruchomienia.

0

Dzięki za odpowiedź. Nie wiedziałem o istnieniu metody initialize(). Doczytałem, że w skrócie jest ona wykonywana na samym końcu klasy Controllera a więc domyślam się, że lepiej ją stosować do uruchamiania różnych metod na początku programu niż poprzez konstruktor;)
Sprytny sposób na dostanie się do sceny, dzięki za podpowiedź:) jednak dalej nie potrafię wywołać tego kodu przy starcie aplikacji ponieważ po wrzuceniu go do konstruktora lub metody initialize() aplikacja mi się nie kompiluje. Kiedy natomiast ten sam kod podepnę pod button i odpalę go ręcznie z buttona to od tego momentu wszystko ładnie przechwytuje tak jak bym tego oczekiwał, jednak chciałbym na przyszłość wiedzieć jak się zabrać do aplikacji tak aby klawiatura działała od samego początku bez ręcznego odpalania jej. Znalazłem na stronie Oracle w "Introduction to FXML" sposób na dodawanie handlerow taki jak Ty opisałeś jednak dotyczył on buttonów i z buttonami faktycznie działa.

Co do problemów z zapisem plików to miałem na myśli, iż po wrzuceniu tego do .jar i odpaleniu aplikacji z niego nie zapisuje mi się plik z rekordowym wynikiem w grze i po każdym uruchomieniu aplikacja jest wyzerowana. Przy uruchamianiu jej poprzez IntelliJ wszystko zapisuje i wczytuje się jak powinno.
Na pytanie już mi sam odpowiedziałeś a więc pliki te muszą być zapisywane poza jarem. Jak wspomniałem przygodę z programowaniem dopiero co zacząłem i Anta nawet na oczy nie wiedziałem nigdy więc to jeszcze przede mną. Jara w załączniku póki co wyciągnąłem bezpośrednio z IntelliJ ;)

1

Kompilować się raczej kompiluje tyle, że się wywala od razu po starcie. Mea Culpa. W momencie wywoływania metody initialize graf obiektów nie jest jeszcze dodany do żadnej sceny - siłą rzeczy metoda getScene() zwróci null -> i leci NPE. Jedynym rozwiązaniem jakie mi na chwilę obecną przychodzi do głowy to dodatkowa metoda w kontrolerze, którą wywołasz po dodaniu obiektów do sceny:
W klasie Main:

@Override
public void start(Stage primaryStage) {
    try {
	FXMLLoader loader = new FXMLLoader();
	loader.setLocation(Main.class.getResource("/fxml/sample.fxml"));
	primaryStage.setScene(new Scene((Parent) loader.load()));
	Controller controller = loader.getController();
	controller.postInit();
        primaryStage.show();
    } catch (Exception ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    }
}

W klasie Controller:

public void postInit() {
	startButton.getScene().setOnKeyPressed(event -> {
		System.out.println(event.getCode().toString());
	});

}
0

Myślałem, że jest jakiś ogólny, uniwersalny sposób wywoływania takich kodów na starcie, a tak to zawsze przy wywołaniu nowej sceny po stage.show() będę musiał dopisywać podobna linijkę. Zawsze to jakieś rozwiązanie :) W taki sam sposób jak do sceny odwoływać się mogę do Stage i wywoływać metody .setScene(). Ale bajer :D

Jakieś sugestie w którą stronę iść dalej z nauką? Często przewija się też jeszcze stosunkowo tajemniczy dla mnie termin Springa i Hibernate odnośnie Javy. Jest może coś jeszcze dla początkującej osoby po drodze do nauczenia się przydatnego czy też mogę się zabierać za te dwie rzeczy? Hibernate po przeczytaniu kilku linijek opisu sprawia wrażenie mniej rozbudowanego frameworka więc może zacząć od niego a później zgłębiać Springa? Zgaduje, że w Springu można wykorzystać Hibernate więc to drugi argument byłby.

1

Na Twoim miejscu jescze bym się wstrzymał z tym Springiem i Hibernatem i pobawił trochę Javą SE. Po trzech tygodniach nauki to mogę Ci zagwarantować, że masz jeszcze czego się uczyć. Tutorial ze strony Oracle mniej więcej Ci nakreśli czego jeszcze nie umiesz. Równolegle do tego polecam zaznajomić się z podstawowymi wzorcami projektowymi i ich zastosowaniem w Javie.

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