. .. : Swf.hu 1.0 archívum : Swf.hu főoldal >>> : .. .


 
 
SEGÉDLETEK Flash+Java

SimpleChat V1.0 - Flash-Chat alkalmazás készítése (JAVA)
  feltöltve: 2004.02.02 | szerző: tenegri | olvasva: 11798 alkalommal

       
 

Kliens oldal - vizuális chat komponens

A kezelőfelületet - mint korábban említettük - vizuális komponensként valósítjuk meg. Egy olyan komponenst fogunk készíteni, amelyik illeszkedik a Flash MX 2004 komponensmodelljébe. Mindezt azért teszzük, hogy a chat kezelőfelületéhez felhasználhassuk a már kész UI komponenseket (nyomógomb, szövegmező görgetősávval, stb.), s ne kelljen a segédletben ezekhez hasonló elemek elkészítésével vesződni és összezavarni az olvasókat :) Persze ha megtennénk, az akár jelentős méretcsökkenéssel járhatna (most így a végeredmény kb. 50 kilobájtos), de nem tesszük :)

Az MX 2004-es komponensmodellben a komponens-hierarchia alapját az mx.core.UIObject és az mx.core.UIComponent osztály jelenti, ezekből lehet származtatni a saját komponensosztályokat. Az UIComponent olyan alapvető tulajdonságokkal ruházza fel a származtatott osztályt, mint az eseménykezelés (event modell), gyermekobjektumok kezelése, méretezés, fókuszálás, stb.

A komponens elkészítéséhez a következőket kell tenni: nyissunk egy új fla-t, mondjuk SimpleChat.fla néven (SimpleChat lesz a komponensünk neve, bár ez független a fla nevétől). Hozzunk létre a library-ban egy új movie clip szimbólumot, a neve ennek is legyen SimpleChat. A linkage tulajdonságok között jelöljük ki az Export for ActionScript-et, linkage azonosítónak adjuk meg megint csak a SimpleChat-et, míg az AS 2.0 Class-hoz írjuk, hogy chat.SimpleChat.

Ezután a Component Definition ablakban is adjuk meg az AS 2.0 Class-nál, hogy chat.SimpleChat, s pipáljuk ki a Display in Components panel jelölőnégyzetet. A felső Component Parameters részt nem kell kitöltenünk, mert a Flash MX 2004 már felismeri a komponensosztály forráskódjában levő jelöléseket és automatikusan megteszi ezt helyettünk. Saját tulajdonság-beállító felületet (Custom UI) nem készítünk, előnézetre (Live preview) pedig nem lesz szükségünk, ugyanis az MX 2004 az IDE-ben történő szerkesztéskor megjeleníti magát a komponenst (akár a scripttel létrehozott elemeket is), s ez az esetek többségében elegendő. A leírást (Description) és rövid feliratot (Tool tip text) mindenki töltse ki ízlése szerint.

Most nézzük mi kerüljön a timeline-ra! Hozzunk létre két réteget, a Background nevűn legyen egy kulcskocka, az Assets nevűn kettő. A Background rétegre nem rakunk mást, mint a kezelőfelület hátterét, azaz egy szürke téglalapot és egy feliratot, hogy ha a komponenst felhasználjuk, akkor a Flash IDE-ben is látszódjon, hogy mi az (ezt a feliratot a kezelőelemek később úgyis eltakarják). Akinek esetleg ennél több kell, az készíthet live preview-t, de én inkább mellőzöm. A háttéren kívül mást, azaz a kezelőelemeket (gomb-, szövegmező-komponens, stb.) nem teszünk a képkockára, azon egyszerű oknál fogva, hogy ha elhelyeznénk azokat a színpadon, akkor a SimpleChat osztály konstruktorában még nem tudnánk hozzájuk férni, mert annak lefutásakor még nem lettek létrehozva. Mivel a konstruktorban szeretnénk kicsit ügyködni a kezelőelem-komponenseken (pl. az eseménykezelőket beállítani), nem marad más lehetőség, mint hogy dinamikusan hozzuk létre azokat.

Az Assets réteg fogja tartalmazni azokat a szimbólumokat (mc-k, komponensek), amelyeket a SimpleChat komponensben használni fogunk. Ezek egy-egy példányát mindenképpen be kell illesztenünk a komponones moziklipbe, s nem elég ha csupán a library-ban vannak, mert különben nem kerülnek be a komponens végső formáját tartalmazó .swc (és azon belül .swf) fájlba. A felhasznált szimbólumok példányait az Assets réteg második kulcskockájára helyezzük el, az első kulcskockára pedig írjunk egy egyszerű stop(); utasítást, így az összetevők nem fognak látszódni feleslegesen, sőt a konkrét példányok még létre sem jönnek (ez kevesebb memóriát igényel), hiszen a stop(); miatt a lejátszás nem jut el a második kockáig. Az Assets réteg második kockájára tehát a következő szimbólumokat (komponenseket) kell beillesztenünk: Button, TextArea, TextInput, Label.

Ha ezzel megvagyunk, a fla része kész is van a komponensnek, már csak az osztálydefiníciót kell elkészíteni. Ehhet nyissunk egy új szövegfájlt (SimpleChat.as) az alábbi kóddal:

import mx.core.UIObject;
import mx.controls.Button;
import mx.controls.TextArea;
import mx.controls.TextInput;
import mx.controls.Label;
import chat.ChatEngine;

class chat.SimpleChat extends mx.core.UIObject {

  /* Ezek a statikus adatok a Flash MX 2004 UI komponensmodelljének felépítése miatt kellenek,
  s az adott osztályról tartalmaznak információkat */

  static var symbolName: String = "SimpleChat";
  static var symbolOwner: Object = Object(chat.SimpleChat);
  var className:String = "SimpleChat";
  static var version: String = "1.0";

  /* A bejövő üzenetek szövegének színe */
  public var colorMessage: String = "#FFFFFF";
  /* Az üzenetet küldő felhasználó neve jelenik meg ezzel a színnel */
  public var colorNick: String = "#FFFF00";
  /* Az egyéb (nem felhasználótól hanem a programtól származó) üzenetek
  szövegének színe */

  public var colorNotification: String = "#FFCCCC";

  /* A chat-szerver neve. Az Inspectable sorral jelöljük, hogy ezt a tulajdonságot
  a fejlesztőkörnyezetben is meg lehessen adni. */

  [Inspectable(defaultValue="localhost")]
  public var hostName: String;
  /* A kapcsolódáshoz használt port száma. Az Inspectable sorral jelöljük, hogy ezt
  a tulajdonságot a fejlesztőkörnyezetben is meg lehessen adni. */

  [Inspectable(defaultValue="4321")]
  public var port: Number;

  /* A chat-motor objektum, amit használni fogunk */
  private var chatEngine: ChatEngine;

  /* A felhasználói felület elemei */
  private var taOutput: TextArea;
  private var tiInput: TextInput;
  private var tiNick: TextInput;
  private var lblNick: Label;
  private var btnSend: Button;
  private var btnUserList: Button;
  private var btnConnect: Button;
  private var btnDisconnect: Button;

  /* Ez a konstruktorunk, nem csinálunk benne semmit */
  public function SimpleChat(Void) {
  }

  /* Ez inicializálja a komponenst (közvetve az UIObject osztály konstruktora hívja meg). */
  private function init(Void): Void {
  var d: Number = 1;

    /* Meghívjuk a szülő osztály init() metódusát */
    super.init();

    /* Létrehozunk egy példányt a ChatEngine-ból */
    chatEngine = new ChatEngine();

    /* És hozzárendeljük a jelen objektumpéldányt, mint az eseménykezelőket tartalmazó objektumot. */
    chatEngine.addListener(this);

    /* Létrehozzuk a felhasználói felület elemeit. Milyen kényelmes is lenne, ha használhatnánk
    a getNextHighestDepth() függvényt az új objektumok szintjének (depth) megadásához, de mivel
    az csak 7-es playeren működik, most eltekintünk tőle :) */


    /* Ez a kimeneti szövegdoboz, ahol az üzenetek megjelennek */
    createClassObject(mx.controls.TextArea, "taOutput", d++, {html: true, editable: false, wordWrap: true});
    taOutput.move(10, 10);
    taOutput.setSize(450, 300);
    taOutput.setStyle("backgroundColor", 0x404040);

    /* A felhasználónév megadására szolgáló beviteli mező */
    createClassObject(mx.controls.TextInput, "tiNick", d++);
    tiNick.move(220, 342);
    tiNick.setSize(100, 22);
    tiNick.setStyle("backgroundColor", 0xCCCCCC);
    /* Megadjuk az [Enter] gomb megnyomásakor keletkező esemény kezelőjét */
    tiNick.addEventListener("enter", this);

    /* Az új üzenetek bevitelére szolgáló beviteli mező */
    createClassObject(mx.controls.TextInput, "tiInput", d++);
    tiInput.move(10, 315);
    tiInput.setSize(450, 22);
    tiInput.setStyle("backgroundColor", 0xCCCCCC);
    /* Megadjuk az [Enter] gomb megnyomásakor keletkező esemény kezelőjét */
    tiInput.addEventListener("enter", this);

    /* Az felhasználónév megadásához használt bevitli mező cimkéje */
    createClassObject(mx.controls.Label, "lblNick", d++, {text: "Név:"});
    lblNick.move(180, 342);
    lblNick.setSize(40, 22);
    lblNick.setStyle("textAlign", "right");

    /* Az üzenet elküldésére szolgáló gomb */
    createClassObject(mx.controls.Button, "btnSend", d++, {label: "Küldés"});
    btnSend.move(10, 342);
    btnSend.setSize(60, 20);
    btnSend.addEventListener("click", this);

    /* A belépett felhasználók listájának lekérésére szolgáló gomb */
    createClassObject(mx.controls.Button, "btnUserList", d++, {label: "Felhasználók"});
    btnUserList.move(80, 342);
    btnUserList.setSize(90, 20);
    btnUserList.addEventListener("click", this);

    /* A chat szerverhez való csatlakozára szolgáló gomb */
    createClassObject(mx.controls.Button, "btnConnect", d++, {label: "Belépés"});
    btnConnect.move(330, 342);
    btnConnect.setSize(60, 20);
    btnConnect.addEventListener("click", this);

    /* A chat-ről való kilépésre szolgáló gomb */
    createClassObject(mx.controls.Button, "btnDisconnect", d++, {label: "Kilépés"});
    btnDisconnect.move(400, 342);
    btnDisconnect.setSize(60, 20);
    btnDisconnect.addEventListener("click", this);

    /* És beállítjuk a kezelőelemek állapotát */
    setConnectedStatus(false);
  }

  /* Ez méretváltozás után rendezgetné a komponens elemeit, de mivel nincs ilyenre
  szükségünk, nem csinálunk benne semmit */

  private function size(Void): Void {
  }

  /* A nick tulajdonság get függvénye, mely a felhasználónevet tartalmazza. A felhasználónevet a
  tiNick szövegbeviteli mezőben tároljuk. Ez a tulajdonság csak azért van, hogy esetleg programból
  is beléptethessük a felhasználót a chat-re */

  public function get nick(): String {
    return tiNick.text;
  }

  /* A nick tulajdonság set függvénye */
  public function set nick(aNick: String): String {
    /* Ha élő kapcsolat van, akkor nem változtathatjuk a felhasználónevet */
    if (!connected)
      tiNick.text = aNick;
  }

  /* A connected tulajdonság get függvénye. Ez a tulajdonság mutatja, hogy van-e élő kapcsolat.
  Set függvénye nincs, mert ezt a tulajdonságot nem lehet kívülről megváltoztatni. */

  public function get connected(): Boolean {
    return chatEngine.connected;
  }

  /* Kapcsolódás a szerverhez */
  public function connect(Void): Void {
    /* Természetesen csak akkor, ha még nem vagyunk kapcsolódva és a felhasználónév sem üres */
    if (!connected && nick != "") {
      chatEngine.hostName = hostName;
      chatEngine.port = port;
      chatEngine.nick = nick;
      chatEngine.connect();
    }
  }

  /* Kapcsolat bontása a szerverrel, azaz kilépés a chat-ről */
  public function disconnect(Void): Void {
    if (connected)
      chatEngine.disconnect();
  }

  /* Üzenet küldése */
  public function send(Void): Void {
    if (connected && tiInput.text != "") {
      chatEngine.sendMessage(tiInput.text);
      tiInput.text = "";
    }
  }

  /* Hibaüzenet keletkezésekor hívódik meg (akkor is ha az a hibaüzenet, hogy nincs hiba :)).
  Ennek az eseménynek a segítségével tudhatjuk meg azt is, hogy sikeres volt-e a kapcsolódási
  kísérlet. A hibakódokat lásd a ChatEngine.as fájlban. */

  public function onStatus(aCode: Number, aStatusMessage: String): Void {
    /* Kiírjuk a hibaüzenetet */
    outputText(formatText(aStatusMessage, colorNotification));
    /* Beállítjuk a kezelőelemek állapotát, attól függően, hogy sikeresen létrejött
    kapcsolatról kaptunk-e értesítést */

    setConnectedStatus(aCode == 100);
  }

  /* A kapcsolat megszakadt */
  public function onDisconnected(Void): Void {
    outputText(formatText("A kapcsolat megszakadt.", colorNotification));
    setConnectedStatus(false);
  }

  /* Üzenet érkezett valamely felhasználótól. A két paraméter a küldő neve és
  az üzenet szövege */

  public function onMessage(aSender: String, aMessage: String): Void {
    outputText(formatText(aSender + ": ", colorNick) + formatText(aMessage, colorMessage));
  }

  /* Új felhasználó csatlakozott a chat-hez */
  public function onUserConnected(aName: String): Void {
    outputText(formatText(aName + " belépett.", colorNotification));
  }

  /* Egy felhasználó kilépett a chat-ről */
  public function onUserDisconnected(aName: String): Void {
    outputText(formatText(aName + " kilépett.", colorNotification));
  }

  /* Tájékoztató üzenet érkezett a szervertől */
  public function onNotification(aNotification: String): Void {
    outputText(formatText(aNotification, colorNotification));
  }

  /* A szerverről megérkezett a belépett felhasználók listája. A paraméterként
  kapott tömbben a felhasználók nevei vannak */

  public function onUserList(aUserList: Array): Void {
  var i: Number;

    outputText(formatText("Jelenleg " + aUserList.length + " belépett felhasználó van:", colorNotification));
    for (i = 0; i < aUserList.length; i++)
      outputText(formatText(aUserList[i], colorNotification));
  }

  /* HTML formájúvá alakítja a megadott szöveget és színt, s közben a szövegben
  esetleg előforduló, HTML-ben jelentéssel bíró karaktereket is semlegesíti */

  private function formatText(aText: String, aColor: String): String {
  var s: String;

    s = aText.split("&").join("&");
    s = s.split("<").join("<");
    s = s.split(">").join(">");
    return "" + s + "";
  }

  /* Kiírja a megadott szöveget a kimeneti szövegmezőbe */
  private function outputText(aText): Void {
    taOutput.text += aText;
    /* A szövegmező aljára görgetünk, hogy látszódjon is az utolsó sor, amit hozzáadtunk */
    taOutput.vPosition = taOutput.maxVPosition;
  }

  /* A csatlakozás állapotának megfelelően állítja be a vezérlőelemeket */
  private function setConnectedStatus(aConnected: Boolean): Void {
    btnSend.enabled = aConnected;
    btnUserList.enabled = aConnected;
    btnConnect.enabled = !aConnected;
    btnDisconnect.enabled = aConnected;
    tiNick.editable = !aConnected;
    tiInput.editable = aConnected;
  }

  /* Ez a gombok eseménykezelője, mindegyik gomb click eseményét ez kezeli le */
  private function click(e: Object): Void {
    /* Attól függően tesszük a dolgunk, hogy melyik gomb váltotta ki az eseményt */
    switch (e.target) {
      case btnSend:
        send();
        break;
      case btnUserList:
        chatEngine.getUserList();
        break;
      case btnConnect:
        connect();
        break;
      case btnDisconnect:
        disconnect();
    }
  }

  /* Ez kezeli le, ha a felhasználó név vagy az üzenet szövegének megadására szolgáló
  beviteli mezőben [Enter]-t nyomott a felhasználó */

  private function enter(e: Object): Void {
    /* Melyik beviteli mező is váltotta ki az eseményt? */
    switch (e.target) {
      case tiNick:
        connect();
        break;
      case tiInput:
        send();
    }
  }

}

Miután a forrásfájl kész van, mentsük el ugyanabba a könyvtárba, ahova a ChatEngine.as-t is tettük (azaz a chat nevű package-be), majd térjünk vissza a SimpleChat.fla-hoz, ahol is a library-ban kattintsunk a jobb egérgombbal a SimpleChat szimbólumon, majd a menüben válasszuk az Export SWC File... menüpontot. A mentés helyéül adjuk meg a C:\Documents and Settings\felhasználónév\Local Settings\Application Data\Macromedia\Flash MX 2004\en\Configuration\Components\Chat könyvtárat (a későbbiekben ide tehetjük a más kezeleőfelülettel ellátott chat-komponenseinket is). Ezután újra kell indítani a Flash-t, s a komponens palettán máris megjelenik felhasználásra készen a SimpleChat komponens a Chat kategória alatt.

Példa alkalmazás

Miután a komponens már készen van, próbáljuk is ki. Nyissunk egy új fla-t (mondjuk SimpleChatTest.fla néven), a színpad méretét állítsuk 470x380-ra, majd a komponens palettáról húzzuk a SimpleChat komponenst a színpadra. Pozícionáljuk 0, 0-ra, s a properties panelen állítsuk be a Host name és Port tulajdonságokat. Ha a saját gépünkön akarjuk kipróbálni, hagyjuk a Host name tulajdonságot az alapértelmezett localhost-on. Eresszünk rá egy publish-t (ha azt akarjuk, hogy 6-os playeren is menjen, állítsuk be a kimeneti formátumot erre), melynek eredményeképp elkészül a SimpleChatTest.swf és SimpleChatTest.html fájl.

Mivel most a chat-en kívül nem akarunk más tartalmat megjeleníteni, ezért úgy fog jól mutatni, ha egy popup ablakba tesszük. Ehhez készítsük el az alábbi HTML dokumentumot, mondjuk SimpleChatPopup.html néven:

<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
<TITLE>Chat</TITLE>
<SCRIPT LANGUAGE="JavaScript">
  window.open("SimpleChatTest.html", "_blank", "menubar=0, toolbar=0, status=0, scrollbars=0, location=0, resizable=0, width=470, height=380");
  window.opener = null;
  window.close();
</SCRIPT>
</HEAD>
<BODY>
</BODY>
</HTML>

Ezután már csak a SimpleChatTest.html BODY tag-jéhez kell beillesztenünk egy attribútumot (style="margin: 0"), hogy ne legyen hely kihagyva a flash mozi körül, majd megnyithatjuk a böngészőben a SimpleChatStart.html-t, s egy popup ablakban megjelenik maga a chat (persze ha a chat-szervert is elindítottuk, a Flash moziban megadott portszámon).

Hogyan tovább?

Az itt tárgyalt chat program meglehetősen egyszerű, mind szolgáltatásaiban, mind pedig a megvalósítás igényességében. Ha csak a jelenlegi tudásánál is maradnánk, akkor is lehetne sokkal robosztusabbra és hibatűrőbbre készíteni, de nem akartam elveszejteni az olvasókat az ilyen részletekben (a legalapvetőbb hibaforrások így is le vannak kezelve). Látványos fejlődést a szolgáltatások bővítésével lehetne elérni, úgymint felhasználók regisztrációja, szobák használata, privát üzenetek küldése, kiemelt jogú felhasználók, megjelenés testreszabhatósága, stb., de olyan apróságokon is lehet csiszolgatni, mint hogy a felhasználók listája ábécé sorrendben jelenjen meg. Ezek mind hasznos szolgáltatások, de a működési elv megértéséhez nem szükségesek, a fenti segédletre támaszkodva némi munkával elkészíthetők, s amúgy is túlmutatnának egy segédlet keretein.

Jó chat-elést!

 
       
 
 

© Devnet.hu. A segédletek semmilyen formában nem másolhatók, publikálhatók a Devnet.hu és a szerzők közös írásos engedélye nélkül.
 
. .. : Swf.hu 1.0 archívum : Swf.hu főoldal >>> : .. .