pisanie fkcjie w actionPerformed

0

hej!
mam takie pytanie-czy jest mozliwosc napisania fkcji w ActionListener? w moim aplecie na przycisniecie odpowiedniego przycisku wywolywana jest odpowiednia akcja - mianowicie laczy z baza no i chcialabym od razu wypisac jakies tam pobrane dane. wyglada to mniej wiecej tak:

//jesli klikniemy na szukaj to pobieraja sie dane z bazy
     class ZdarzenieSzukaj implements ActionListener
     {  
 	   	 
         public void actionPerformed(ActionEvent zdarzenie) {
try
 {
     
Class.forName("org.postgresql.Driver"); 
     
  }
       catch(Exception wyjatek)
        {
               
           System.out.println("Blad wczytywania sterownika!");
           return;
        }

 
String URL ="jdbc:postgresql://127.0.0.1/test";
String username = "postgres";
String password ="";
Statement s=null;
Connection polaczenie = null;
        
try {
  
  polaczenie=DriverManager.getConnection(URL, username, password);
  s=polaczenie.createStatement();
  System.out.println("Polaczono!");  
 
  //pobieranie danych z bazy

	String zapytanie ="select * from t_tabela";
	
	ResultSet wynik = s.executeQuery(zapytanie);
//pobieram i wyswietlam dane
	
		while(wynik.next())
		{	
			String imie = wynik.getString("imie");
			}	
  
}

catch(Exception wyjatek)
    {   
    
    System.out.println("Nie mozna polaczyc sie z baza!");   
    }        
             		
         }     }

no i w tym miejscu gdzie dane pobieram chce tez je wyswietlic (w aplecie), czyli np.


	while(wynik.next())
		{	
			String imie = wynik.getString("imie");
		
 public void paint(Graphics g){
        	 g.drawString(imie, 200, 200)
        	 
         }		
	
		}	

jednak dostaje info ze w tym miejscu nie moze byc fkcji. tj. w jakim miejscu w actionPerformed bym nie dala, to zasze bedzie ze tu nie mozna fkcji wywolac. jak wywolalam w ActionListener, ale poza actionPerformed to bledu nie zwroci ale akcja nie zostanie wykonana. mam nadz ze w miare zrozumiale opisalam o co mi chodzi. moglby mi ktos podpowiedziec jak to rozwiazac?
Pzdr!

0

Odpowiedź na pytanie:
Bo nie można umieszczać funkcji w funkcji.

Uwagi (złe okrutne, ale warto posłuchać):
Generalnie kod jest, delikatnie mówiąc, tragiczny. Połączenie z bazą wywal do osobnego obiektu. Niech zajmuje się tylko i wyłącznie obsługą bazy. W ten sposób możesz później napisać:

public void actionPerformed(ActionEvent zdarzenie){
    DBConnector db = DBConnector.getInstance();
    PersonDAO personDAO = new PersonDAO(db);
    List<Person> wynikiZBazy = personDAO.get(...); // zamiast ..jakieś warunki
/// możesz obrabiać sobie listę obiektów by wyświetlić wyniki
}

Obiekt DBConnector niech obsługuje tyko połączenia z bazą danych.
Obiekt PersonDAO niech pozwala na wyciąganie informacji o osobach reprezentowanych jako obiekty Person.

0

no moze nie jest to jakis super kod, ale dopiero zaczynam sie uczyc (gl z ksiazki 'thinking in java'). jesli chodzi o to co mi zasugerowales to chyba bede musiala przejrzec na googlach co nieco, bo poki co jest mi to obce. ale dzieki za sugestie.

0

@misty, zapoznaj się z artykułem Podstawy Javy. TiJ jest fajny, szczególnie 4 wydanie, ale ma też małe wady. To co zasugerowałem to raczej ogólne podejście, którego należy szukać pod nazwą Wzorzec MVC. W Javie piękną rzeczą są klasy anonimowe i takie jak przedstawiłaś implementacje interfejsów. Swoją drogą jesteś pierwszą "początkującą" osobą, która nie popełniła błędu i nie implementujesz ActionListener w JFramie w którym ma być użyty. Chwali się takie podejście.

ps. jako że jesteś początkująca to pytaj, gnęb i męcz. Od tego jesteśmy...

0

po prostu jak przerzucam cale to polaczenie do osobnej klasy DBConnector to zglasza blad juz na samym poczatku klasy czyli przy pierwszym try :/

0

lol, nie spodziewalam sie takiej pozytywnej odpowiedzi-bylam pewna ze mnie wysmiejesz ze nie znam takich podstaw.
ja jestem przyzwyczajona do programowania proceduralnego. ale postanowilam poszerzyc horyzonty. szczerze-ciezko idzie, obiektowosc to jeszcze dla mnie abtrakcjam chociaz powoli sie przejasnia;)
poki co-przejrze ten art co zaproponowales.

0

mam jeszcze jedno male pytanie. bo jesli wrzuce to cale polaczenie do nowej klasy:

public class DBConnector{
public polaczenie(
//i tu skopiowalam cala obsluge polaczenia z baza
)
}

i wtedy:

    class ZdarzenieSzukaj implements ActionListener
     {  
    	 
        public void actionPerformed(ActionEvent zdarzenie) {
	DBConnector db =  DBConnector.getInstance();
             		
         }
     }

to otrzymuje taki blad:

getInstance() is undefined for the type TestAppletDBConnector

?

0

aj.. błąd składniowy!!!

public class DBConnector{
  public void polaczenie(){
   //i tu skopiowalam cala obsluge polaczenia z baza
  }
}

Zresztą i tak jest źle ;) Lektura na jutro... hm.... zapoznać się ze wzorcem singleton:
http://en.wikipedia.org/wiki/Singleton_pattern#Java

Podam ci też szablon klasy, która może służyć do zarządzania połączeniem:

import java.sql.Connection;
import java.util.Properties;

public class DBConnector {

	private static Connection CONNECTION_INSTANCE;

	private DBConnector() {
	}

	public static void init(Properties properties) {
		// tu inicjalizujesz połączenie - tworzysz obiekt. Plik properties
		// powinien zawierać informacje o sterowniku, hościem, bazie, userze i
		// haśle.
	}

	public static Connection getCONNECTION_INSTANCE() {
		if (CONNECTION_INSTANCE == null)
			throw new NullPointerException(
					"Connection is null! Call init() first...");
		return CONNECTION_INSTANCE;
	}

	@Override
	protected void finalize() throws Throwable {
		// Połączenie jest zamykane w momwncie niszczenia obiektu
		CONNECTION_INSTANCE.close();
	}
}

ps. nie mam w zwyczaj u jeździć po "zielonej trawce"... koniec końców "Szanuj Zieleń" :)

0

hej, w sumie nawet skumalam teraz idee tego o czym pisales wczesniej. odrobilam tez prace domowa i przeczytalam ten art:P
sprobowalam to zaimplementowac, na razie tylko z polaczeniem, pobieraniem i wyswietlaniem danych zajme sie pozniej. ale dostaje blad :

Thread [AWT-EventQueue-1] (Suspended(exception NoSuchMethodError))
EventDispatchThread.run() line:not available

i otwiera sie plik z EventDispatchThread.class (w sumie w netbeans sa chyba jakos lepiej bledy opisane niz w eclipse? ale pewnie sie myle heh).
zrobilam to na bazie tego co mi podpowiedziales czyli wyglada to mniej wiecej tak:

  public class BazaConnector	{
    	 
   private static Connection Polacz;
  
  //konstruktor
  	private BazaConnector()	{}
    	 
  	public static void init (properties Properties){
  
 //tu obsluga polaczenia, czyli wrzucilam to co w pierwszym
//poscie bylo-takie samo polaczenie		
  		 
     		}//koniec init
  
  	public static Connection getPolacz() {
  		if (Polacz == null)
  				throw new NullPointerException("Polaczenie is null!");
  		
  		return Polacz;
  		} 	
  	 }

no a w moim listenerze:

//jesli klikniemy na szukaj to pobieraja sie dane z bazy
     class ZdarzenieSzukaj implements ActionListener
     {  
    	 
   BazaConnector baza;
    	 public void actionPerformed(ActionEvent zdarzenie) {
      		 baza = new BazaConnector();
    		 baza.getPolacz();
         }
        
     }

hm. no i dostaje ten blad o ktorym wspomnialam. sie zastanwiam czemu, mam w sumie wszystkie biblio ktore potrzeba (i pewnie pare za duzo;)).
sprobowalam tez zrobic tak, ze w tej klasie BazaConnector bylo robione cokolwiek, tj. wyrzucialm czesc odpowiedzialna za polaczenie i napisalam fkcje ktora ma wyrzucic tylko System.out.println("cos"). kumasz, chcialam zobaczyc czy zadziala cokolwiek. no ale blad ten sam. masz pomysl czemu?

0

Ok. Na początek słowo o błędach. Klasa Exception ma pole message, które jest wyświetlane w momencie wyrzucenia wyjątku. Nie ma zatem różnicy pomiędzy Eclipsem i NetBeansami. Komunikat zawsze będzie ten sam. Sam wyjątek jest dość ciekawy, ale chyba nie wkleiłaś całego komunikatu.

Teraz o twoim kodzie listenera. Jest nie bangla, ponieważ nie inicjujesz połączenia (chyba że robisz to wcześniej). Metoda init() została przeze mnie tak pomyślana byś musiała ją choć raz wywołać. Jeżeli zatem przed wywołaniem getPolacz() nigdzie nie jest wywołane init() to całość, w obecnej formie, się posypie. Można to dość łatwo poprawić troszkę zmieniając metodę getPolacz(). Jak ? Pokombinuj chwilę.

Mam jeszcze jedną uwagę. Pola w obiektach powinno nazywać się z małej litery. Pod tym adresem:
http://java.sun.com/docs/codeconv/
jest artykuł poświęcony nazewnictwu w Javie. Zasady nie są obowiązkowe, ale bardzo ułatwiają życie jak trzeba konsultować kod.

ps. uwaga do edycji jak wklejasz kod to daj code=java zamiast samego code. Ładnie podświetli składnię. Lepiej się to wtedy czyta.

pps. jak pracujesz na kompie z dwurdzeniowym prockiem to mogą się niektóre rzeczy wysypywać. To są bugi javy niestety.

0

wiesz co, postanowilam tak chamsko nie kopiowac tego co mi podeslales, a jedynie skorzystac z idei by stworzyc na polaczenie odzielna klase. tzn. generalnie jest podobnie, ale prosciej no i dziala;) wiec zrobilam cos takiego:

     	class BazaConnector {
     		
     //konstruktor
     		private BazaConnector()	{
     			
     		}
     //fkcja odpowiedzialna za polaczenie z baza
     		private void  getPolaczenie ()
     		{	
//tutaj wrzucilam te cala probe polaczenia
}
}

a w moim listenerze wywoluje ja po prostu tak:

     class ZdarzenieSzukaj implements ActionListener
     {  
   
    	 BazaConnector baza;
    	 
         public void actionPerformed(ActionEvent zdarzenie) {
        	 baza = new BazaConnector();
        	 baza.getPolaczenie();

}}

i dziala:) pewnie nadal co nieco brakuje (tj. musze dopisac jeszcze zamykanie polaczenia co zaraz zrobie;)) ale generalnie oblsuga jakis podstawowych bledow jest juz zawarta w tej fkcji getPolaczenie() - to jest robione try-catch - czyli zawsze jak sie cos nie uda to jest odpowiedni wyjatek wypisywany. mysle ze jak na razie cos takiego mi starczy i moge sie zajac pisaniem klasy Person:)
co sadzisz o tym co Ci podeslalam?

ps. apropos bledu ktorego fragment Ci wczesniej wkleilam - okazalo sie ze mialam wczesniej jakis blad. juz jest si.

0

takie jedno male pytanie jeszcze. moja klasa ktora bedzie odpowiedzialna za pobieranie jakis tam danych musi dziedziczyc po klasie BazaConnector.
ale jak jak pisze

class PobierzDane extends BazaConnector{
    private PobierzDane() {}
}

to wpierw w ogóle sie czepial i mowil ze sa bledy. a teraz mowi ze sa bledy jak probuje wykorzystac ktoras ze zmiennych z BazaConnector (np. statement s).
w klasie BazaConnector fkcja odpowiedzialna za inicjacje polaczenia jest typu private. w jej wnetrzu nie definiowalam czy takie zmienne jak statement, username itd maja byc public/protected/private. moze powinnam? albo moze w klasie PobierzDane powinnam je przywolac?


0

A fuj...

Dziedziczenie to zło!

Szczególnie w javie, która pozwala na dziedziczenie tylko po jednej klasie. Lepszym rozwiązaniem jest kompozycja:
Definiujemy sobie interfejs dla wszystkich klas do obróbki danych

public interface Pobieranie<Dana, Warunek> {

	public Dana pobierz(Warunek warunek);

	public void usun(Dana dana, Warunek warunek);

	public void dodaj(Dana dana);

	public void aktualizuj(Dana stara, Dana nowa);
}

Chcemy pobierać osoby:

public class Osoba {
	private String imie;
	private String nazwisko;

	public String getImie() {
		return imie;
	}

	public void setImie(String imie) {
		this.imie = imie;
	}

	public String getNazwisko() {
		return nazwisko;
	}

	public void setNazwisko(String nazwisko) {
		this.nazwisko = nazwisko;
	}

}

po nazwisku, które będzie String'iem:

public class OsobaDAO implements Pobieranie<Osoba, String> {

	private DBConnector connector;

	public void aktualizuj(Osoba stara, Osoba nowa) {
	}

	public void dodaj(Osoba dana) {
	}

	public Osoba pobierz(String warunek) {
		return null;
	}

	public void usun(Osoba dana, String warunek) {
	}

	public DBConnector getConnector() {
		return connector;
	}

	public void setConnector(DBConnector connector) {
		this.connector = connector;
	}

	public OsobaDAO(DBConnector connector) {
		super();
		this.connector = connector;
	}

}

Dobra co tu jest tak naprawdę istotne. Otóż nasza klasa OsobaDAO posiada (relacja ma) referencję do DBConnector. Ma to tą zaletę, że klasa pobierająca dane nie jest tak naprawdę na sztywno związana ze sposobem w jaki odbywa się połączenie ze źródłem danych. Mówiąc obrazowo lepiej mieć młotek do wbijania gwoździ i śrubokręt do wkręcania śrub niż być młotkiem, a ze śrubkami kombinować jak łysy koń pod górę. Relacja jest, czyli rozszerzanie klas nie powinna być często stosowana.

Co zaś tyczy się błędu to pól prywatnych nie możesz wywoływać z poza obiektu. Lepszym rozwiązaniem (i jedynym słusznym) jest tworzenie funkcji zwracających (getterów), za pomocą których, będziesz pobierać wartości pól.

0

wiesz co, chyba nie do konca to rozumiem.
interface to zbior jakis metod do pobierania/usuwania etc danych.
potem mam do napisania klase odpowiedzialna za poberanie danych, ale ona musi skorzystac z jakis tam rzeczy z DBConnector.
hm, nie wiem jak Ci wytlumaczyc o co mi chodzi. generalnie przedstawiles mi szkielet 3ech modulow - interfejs + 2 klasy. nie widze zaleznosci miedzy nimi. po co mi interfejs jesli napisze odpowiednia klase. a jak pozniej wywolam jej obiekt i odpowiednia metode to bede miala co chce. no i nie rozumiem za bardzo jak w tym przypadku wyglada/dziala referencja do DBConnector, czyli nadal nie wiem jak skorzystac z takich rzeczy jak np. connector z klasy DBConnector w klasie odpowiedzialnej za pobieranie danych

0

Hm... Jak by ci tu wytłumaczyć ideę. DBConnector jest tylko dodatkowym narzędziem i jako taki powinien być całkowicie niezależny od Twojej aplikacji. Dlaczego? Otóż przy kolejnym programie będziesz mogła użyć już gotowego narzędzia. '

Obiekt DAO służy do wybierania informacji o osobach i korzysta z DBConnectora. Interfejs w tym przypadku pozwala na zrobienie pewnej sztuczki polegającej na ujednoliceniu wszystkich DAO tak by można było korzystać z nich w jednolity sposób.

Wspominałem też już o wzorcu MVC, który tu jest całkiem przydatny. Poszczególne warstwy są ze sobą luźno powiązane, a niektóre funkcjonalności (w tym przypadku obsługa DB) wyniesione całkowicie poza logikę aplikacji i służą jako narzędzia wielokrotnego użytki.

0

hm.. idee interfejsu poki co pominelam bo na razie nie widze tak do konca potrzeby jego stosowania w moim projekcie (moze pozniej sie to zmieni). chce po prostu by klasa PobierzDane mogla korzystac z "rzeczy" zawartych w klasie BazaConnector.
jesli chce w klasie PobierzDane pobrac jakies dane, to bede potrzebowala Statement s z BazaConnector. i wlasnie nie wiem jak to zrobic. powiedziales ze dziedziczenie to zlo, ale w sumie nawet ono mi nie zadzialalo:

class PobierzDane extends BazaConnector{

public PobierzDane(){
  String zapytanie = "select imie from t_osoba";
 ResultSet odpowiedz = s.executeQuery(zapytanie);

}
}

zwaraca mi unhandled sql exception. zreszta jesli dobrze rozumuje (heh, a pewnie zle;)) to PobierzDane - potomek BazaConnector skoro dziedziczy po rodzicu to powinien miec dostep do jego funkcji i zmiennych? wiec chocby proba wypisania w PobierzDane nazwy uzytkownika (username = postgres zdefiniowanej w BazaConnector) powinna po prostu wypisac nazwe uzytkownika? a czemu zwraca null?

jesli mialabym porzucic to dziedzicznie i zrobic tak by PobierzDane mialo referencje do BazaConnector (czyli moglo korzystac z tych potrzebnych mi "rzeczy" jak np. Statement s) to jak mam to zrobic?

0

Niekoniecznie musi mieć dostęp. Ma dostęp tylko do tych które nie są oznaczone jako prywatne.

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