IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

24. diel - Java chat - Klient - Dokončenie 2. časť

V minulej lekcii, Java chat - Klient - Dokončenie 1. časť , sme začali práce na GUI nášho chat klienta v Jave. V dnešnom poslednom Java tutoriálu dokončíme implementáciu chat klienta a tým aj uzavrieme celú sériu o tvorbe Java servera.

Obsluha pre zobrazenie konverzácie

Začneme tým, že zobrazíme konverzáciu s vybraným užívateľom. Pri dvojitom kliknutí na užívateľa v ListView sa zobrazí buď nová záložka s konverzáciou, alebo sa prepne na už existujúce konverzáciu. V triede MainController vytvoríme novú konštantu, ktorá bude obsahovať anonymné funkciu, ktorá bude obsluhovať dvojité kliknutie do ListView:

private final EventHandler <<? super MouseEvent> listContactsClick = event -> {
    final int clickCount = event.getClickCount();
    if (clickCount != 2) {
        return;
    }

    final ChatContact contact = lvContactList.getSelectionModel().getSelectedItem();
    if (contact == null) {
        return;
    }

    showConversation(contact);
};

Na začiatku sa skontroluje, či ak sme naozaj klikli 2x. Ak podmienka nie je splnená, nebude sa nič robiť. Ďalej skontrolujeme, že sme klikli na nejaký kontakt a nie do prázdneho miesta. Ak sme klikli na kontakt, zobrazíme konverzáciu metódou showConversation().

Zobrazenie vybrané konverzácie

Vybranú konverzáciu budeme zobrazovať pomocou metódy showConversation():

private void showConversation(ChatContact contact) {
    final Optional <ChatTab> optionalTab = paneChatContainer.getTabs()
        .stream()
        .filter(tab -> tab.getUserData() == contact)
        .map(tab -> (ChatTab) tab)
        .findFirst();

    if (optionalTab.isPresent()) {
        paneChatContainer.getSelectionModel().select(optionalTab.get());
    } else {
        paneChatContainer.getTabs().add(makeNewTab(contact));
    }
}

Metóda prijíma ako parameter inštanciu triedy ChatContact, ktorá predstavuje kontakt, pre ktorý chceme zobraziť konverzáciu. Najskôr sa pozrieme, či je už konverzácie v TabPane prítomná. Ak áno, jednoducho na nej prepneme metódou select(). V opačnom prípade vytvoríme novú záložku s konverzáciou a vložíme ju medzi ostatné konverzácie.

Vytvorenie novej konverzácie

Vytvorenie novej konverzácie necháme na samostatnú metódu, ktorú nazveme makeNewTab():

private ChatTab makeNewTab(ChatContact chatContact) {
    final ChatTab chatTab = new ChatTab(chatContact);
    chatTab.setUserData(chatContact);
    return chatTab;
}

Najskôr vytvoríme novú inštanciu triedy ChatTab. Metódou setUserData() nastavíme vlastné používateľské dáta. Týchto dát potom využívame v predchádzajúcom kóde, kde filtrujeme Tab podľa zadaného kontaktu.

Registrácia obsluhy pre zobrazenie konverzácie

Nakoniec v metóde initialize() zaregistrujeme obsluhu na kliknutie pre ListView:

lvContactList.setOnMouseClicked(this.listContactsClick);

Test funkčnosti

Teraz, keď pustíte server, pustíte klienta, pripojíte sa na server a zobrazí sa v ListView jediný kontakt - Vy, môžete na tento kontakt 2x kliknúť a zobrazí sa v pravej časti okna nová záložka s konverzáciou.

Okno s prázdnou konverzáciou - Server pre klientskej aplikácie v Jave

Odoslanie správy

V nasledujúcej časti implementujeme odoslanie správy. Do textového poľa budeme môcť písať len vtedy, ak je vybraná nejaká konverzácie. Tlačidlo pre odoslanie bude prístupné iba za predpokladu, že textové pole obsahuje nejaký text. Začneme teda implementáciou týchto podmienok.

Ovládanie prvkov

Ovládanie prvkov nastavíme v metóde initialize(). Najskôr ovládanie tlačidla. Tlačidlu nabindujeme vlastnosť disableProperty() na textProperty().isEmpty().

btnSend.disableProperty().bind(txtMessage.textProperty().isEmpty());

Textové pole nabindujeme podobným spôsobom:

txtMessage.disableProperty().bind(paneChatContainer.getSelectionModel().selectedItemProperty().isNull());

Obsluha tlačidlá pre odoslanie správy

Pri stlačení tlačidla odoslať sa odošle správa. Už máme všetku potrebnú logiku implementovanú, stačí ju len zavolať:

private void handleSendMessage(ActionEvent actionEvent) {
    final ChatTab tab = (ChatTab) paneChatContainer.getSelectionModel().getSelectedItem();
    if (tab == null) {
        return;
    }

    final String id = ((ChatContact) tab.getUserData()).getId();
    final String message = txtMessage.getText();
    chatService.sendMessage(id, message);
    txtMessage.clear();
    txtMessage.requestFocus();
}

Najskôr sa otestuje, či ak máme otvorený Tab. Ak nie, metóda nič nevykoná. Id kontaktu získame z užívateľských dát v Tab ua obsah správy z textového poľa. Nakoniec zavoláme našu service, ktorá sa postará o odoslanie správy. Nasleduje vymazanie textového poľa a požiadavku o získanie fokusu, aby sme mohli znovu písať.

Zobrazenie správ

Prijaté správy už majú implementovanú všetku logiku, takže po odoslaní správy sa automaticky zobrazí. Pokiaľ práve konverzácie nebude zobrazená, zobrazí sa v kontakt liste napravo od mena počet neprečítaných správ.

Informácie o písaní

Teraz implementujeme funkciu, ktorá bude používateľa informovať, či ak klient na druhom konci píše, alebo nie. V triede MainController založíme novú triednu konštantu, ktorá bude obsahovať anonymné funkciu, ktorá sa bude volať pri zmene obsahu textového poľa so správou:

private ChangeListener <<? super String> messageContentListener = (observable, oldValue, newValue) -> {
    final ChatTab tab = (ChatTab) paneChatContainer.getSelectionModel().getSelectedItem();
    if (tab == null) {
        return;
    }

    final String id = ((ChatContact) tab.getUserData()).getId();
    chatService.notifyTyping(id, !newValue.isEmpty());
};

Dôležité je volanie metódy notifyTyping() na poslednom riadku funkcie, pomocou ktorej budeme informovať, či ak používateľ píše, alebo nie.

Ošetrenie prepnutie konverzácií

Je pekné, že sme informovali používateľa, že píšeme, ale môže sa stať, že počas písania sa prepneme do inej konverzácie, pretože si uvedomíme, že správa je určená niekomu inému. Vytvoríme teda listener, ktorý bude reagovať na zmenu konverzácie. Založíme ďalšie triedne konštantu, ktorá bude obsahovať anonymné funkciu reagujúce na zmenu konverzácie:

private ChangeListener <<? super Tab> tabChangeListener = (observable, oldValue, newValue) -> {
    if (oldValue != null) {
        final ChatTab oldTab = (ChatTab) oldValue;
        final String id = ((ChatContact) oldTab.getUserData()).getId();
        chatService.notifyTyping(id, false);
    }

    if (newValue != null) {
        if (!txtMessage.getText().isEmpty()) {
            final ChatTab newTab = (ChatTab) newValue;
            final String id = ((ChatContact) newTab.getUserData()).getId();
            chatService.notifyTyping(id, true);
        }
    } else {
        txtMessage.clear();
    }
};

Funkcia dostane ako parametre oldValue (stará konverzácie) a newValue (nová konverzácia). Ak sa naozaj prepíname zo starej konverzácie, tak hodnota oldValue nebude null a informujeme užívateľa v starej konverzáciu, že už nepíšeme správu pre neho. Ak sme sa prepli do novej konverzácie a textové pole pre správu obsahuje nejaký text, tak informujeme nového používateľa, že najskôr píšeme správu pre neho.

Registrácia poslucháčov písanie

Nakoniec zaregistrujeme poslucháčov na zmenu konverzácie v metóde initialize().

paneChatContainer.getSelectionModel().selectedItemProperty().addListener(this.tabChangeListener);

Test indikátora písania

Teraz, keď otvoríte konverzáciu a začnete písať, zmení sa ikona v Tabu na veľmi jednoduchú animáciu.

Výsledok

Nižšie môžete vidieť výsledného chat klienta. U kontaktov sa zobrazuje počet neprečítaných správ. Ďalej indikátor písania sa zobrazuje v tabu. Ak je konverzácia dlhší, zobrazí sa scrollbar.

Príklad konverzácie - Server pre klientskej aplikácie v Jave

Ukončenie série

Týmto by sme mali uzavretú celú sériu o tvorbe jednoduchého chat klienta. Klient samozrejme zaslúži ešte rad vylepšení, ktoré nechám na samotných čitateľoch. Dúfam, že sa vám seriál páčil a ak budete mať akékoľvek pripomienky, dole sú k dispozícii komentáre.

V nasledujúcom kvíze, Kvíz - Server pre klientske aplikácie Java, si vyskúšame nadobudnuté skúsenosti z kurzu.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 61x (141.84 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Java

 

Predchádzajúci článok
Java chat - Klient - Dokončenie 1. časť
Všetky články v sekcii
Server pre klientskej aplikácie v Jave
Preskočiť článok
(neodporúčame)
Kvíz - Server pre klientske aplikácie Java
Článok pre vás napísal Petr Štechmüller
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje primárně programování v Javě, ale nebojí se ani webových technologií.
Aktivity