Pierwszy program okienkowy
Po krótkim wstępie czas przejść do rzeczy i napisać Hello World po raz trzeci. Tym razem będzie to jednak aplikacja okienkowa a nie tylko tekst na konsoli. W celu ułatwienia sobie pracy skorzystaj ze środowiska Eclipse.
Jak wspomnieliśmy we wstępie, podstawowym komponentem, dzięki któremu możemy stworzyć okienko jest JFrame. Aby ją wykorzystać moglibyśmy utworzyć nowy obiekt w dowolnej metodzie main(), byłoby to jednak bardzo niepraktyczne, ciężko byłoby dodawać do ramki inne elementy.
Podejście, które powinieneś stosować jest następujące:
- Utwórz klasę rozszerzającą klasę JFrame
- Dodaj wszystkie elementy (panele, przyciski ...) w konstruktorze
- Ustaw podstawowe cechy (rozmiar, akcja na zamknięcie aplikacji)
- Uwidocznij ramkę za pomocą metody setVisible() z parametrem true
- Utwórz obiekt swojej klasy w nowym wątku dystrybucji zdarzeń
Aby to wszystko omówić nieco dokładniej zacznijmy od razu od przykładu. Utwórzmy dwie klasy:
- Klasa z ramką o nazwie MyFrame, która rozszerza klasę JFrame
- Klasa Testowa o nazwie Test, w której stworzymy obiekt naszego okna
import javax.swing.JFrame;
public class MyFrame extends JFrame {
public MyFrame() {
super("Hello World");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
}
import java.awt.EventQueue;
public class Test {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new MyFrame();
}
});
}
}
W klasie MyFrame rozszerzamy (extends) klasę JFrame, ponieważ chcielibyśmy w przyszłości dodać do niej dodatkowe funkcjonalności i przede wszystkim ją ustawić po swojemu. Utworzyliśmy w niej jeden publiczny i bezparametrowy konstruktor (równie dobrze może przyjmować jakieś wartości, lub nawet być prywatny, a klasa udostępniać statyczną metodę zwracającą instancję klasy). W pierwszej kolejności zarówno w prostym oknie jak i innych komponentach powinniśmy wywołać instrukcję super(), czyli konstruktor nad klasy - w naszym wypadku podajemy również parametr "Hello World", który będzie stanowił tytuł naszego okna.
Następnie musimy zadbać o to, że nasza aplikacja po wciśnięciu przycisku zamknięcia (krzyżyk w rogu) będzie faktycznie zamykana. W tym celu należy wywołać metodę setDefaultCloseOperation() z odpowiednim argumentem. My chcemy, aby program się zamykał, więc podajemy stałą zdefiniowaną w klasie JFrame - EXIT_ON_CLOSE . Wpisując w Eclipse JFrame. i wciskając Ctrl+spacja możesz podejrzeć jakie inne wartości możesz przekazać (np DO_NOTHING_ON_CLOSE).
Ostatnią rzeczą jaką musimy zrobić to wyświetlenie naszej ramki na ekranie, za co odpowiedzialna jest metoda setVisible() . Przekazujemy jej wartość true, lub false, dzięki czemu, możemy naszą ramkę również ukryć - w końcu nasz program może posiadać kilka okienek i nie chcemy, aby zamknięcie jednego z nich zawsze powodowało koniec aplikacji. Żeby nasz program działał nie możemy oczywiście zapomnieć o zaimportowaniu odpowiedniej biblioteki, nam będzie potrzebna jedynie klasa JFrame znajdująca się w pakiecie javax.swing. (Najłatwiej zaimportować ją w Eclipse klikając na podkreślony tekst JFrame i wcisnąć kombinację klawiszy Ctrl+Shift+M, lub skorzystać z automatycznej organizacji importów - Ctrl+Shift+O).
W drugiej klasie dzieje się nieco magii. Aplikacje wykorzystujące komponenty Swing powinny być podatne na przechwytywanie zdarzeń (na przykład na wciśnięcie przycisku zamknięcia okna), w tym celu powinniśmy je uruchamiać z tzw. wątku dystrybucji zdarzeń. Ponieważ nie zajmowaliśmy się jeszcze problemem wielowątkowości potraktujmy drugą klasę jako magiczny fragment kodu i wykorzystujmy ją jako wzorzec w swoich kolejnych projektach, będzie ona prawie zawsze wyglądała tak samo.Wykorzystano tu również klasę anonimową, której jeszcze nie omawialiśmy - w skrócie implementacja klasy odbywa się podczas tworzenia obiektu.
Ciekawostką może być też dla niektórych adnotacja @Override. Pisząc programy w Eclipse i importując metody, których wymaga implementowany interfejs adnotacja ta pozwala zachować bezpieczeństwo przed na przykład literówkami w nazwach. Jeżeli zmienilibyśmy nazwę run() na np. runnn(), wyświetlony zostałby komunikat o błędzie.
Po uruchomieniu programu w lewym górnym rogu ekranu powinna pokazać się nasza ramka w najbardziej skondensowanej formie, jakiej tylko się dało. Co ciekawe można zauważyć, że możemy dowolnie rozciągać naszą ramkę pomimo, że nie dodawaliśmy samodzielnie takiej funkcjonalności - jest ona domyślna i można ją oczywiście wyłączyć - konkretnie za pomocą metody setResizable(), z argumentem false.
W celu ćwiczenia wypróbuj tą metodę w swoim programie. Spróbuj także ustawić inne parametry, jak na przykład położenie, lub rozmiar, odpowiednio używając metod setLocation() i setSize(). To co należy im przekazać podejrzyj za pomocą kombinacji klawiszy Ctrl+spacja w Eclipse.
Dyskusja i komentarze
Masz pytania do tego wpisu? Może chcesz się podzielić spostrzeżeniami? Zapraszamy dyskusji na naszej grupie na Facebooku.
Poniżej znajdziesz archiwalne wpisy z czasów, gdy strona była jeszcze hobbystycznym blogiem.
Jakub
Hey! Taka sie zastanwiem czym sie roznie i w czym jest lepsze, takie tworzenie okna: public class Main { public static void main(String[] args) { EventQueue.invokeLater(new Runnable(){ public void run(){ new MyFrame(); } }); } } od takiego: public class Main { public static void main(String[] args) { new MyFrame(); } }
``
Jestem początkujący ale wygląda mi na to że w pierwszym sposobie tworzysz okno w osobnym wątku. Drugim sposobem okno jest tworzone w tym samym wątku.
Anonim
To sa dwie klasy, a nie 2 sposoby do wyboru. Chyba nie czytales programowania obiektowego
NAME (WYMAGANE)
Witam, ja mam pytanie - dlaczego autor ustawia setDefaultExitAction? Wykomentowalem to i okno sie zamyka. Czy chcial pokazac ze takie cos istnieje czy jest inny powod?
DjCoraxa
Teraz otworz sobie menadzer zadan i zobacz ze ten program okienkowy jest dalej w pamieci ...
Tomek
Eclipse domaga się serialVersionUID, ale wyczytałem, że serializowanie nie jest konieczne, a jedynie mocno zalecane, więc uznałem, że na razie sobie to daruję. Działam na Eclipse 3.5.2 pod Ubuntu 11.04 i niestety przy kodzie klasy Test jaki podałeś w kursie okienko pojawia się u mnie w wersji prawie szpiegowskiej. Tzn. jest praktycznie niewidocznym prostokątem o wymiarach około 2x3 pixele. Kombinowałem już z ustawieniami setSize(), ale nic to nie daje. Przy użyciu kodu jaki podał Jakub, czyli: public class Main { public static void main(String[] args) { new MyFrame(); } } Okienko jest widoczne, pojawia się tam gdzie chcę setLocation()) i w takim rozmiarze, jak chcę (setSize()). Niestety setResizable() wciąż nie działa. Z czego wynikają te komplikacje?
bartek
spróbuj tak: import javax.swing.JFrame; public class Ramka extends JFrame{ public Ramka () { super("Program Bartka"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); setLocation(300,100); setResizable(false); setSize(400,400); } }
Norbert
Witam, mam taki problem, że gdy klikam CTRL+SHIFT+M lub O to nic się nie dzieje. Klikając CTRL+SHIFT+O pisze na dole "0 imports added". Klikałem to prawie w każdym miejscu i nic. Gdy próbuje uruchomić aplikacje pisze Errors exist in required project(s): Frame. Proszę pomóżcie!
Norbert
Albo jednak coś się dodaje ale mam dalej ten błąd. Exception in thread "main" java.lang.Error: Unresolved compilation problem: at pl.javastart.first.Test.main(Test.java:4)
Yaqp
Warto dodać, że setLocation() i setSize() można zastąpić setBounds()
POTTER
Jak powinien wyglądać JFrame??
lukas
dlaczego przy linijkach z frazą JFRAME pojawia mi się wykrzyknik z objaśnieniem: "the type jframe is not accessible due to restriction on required library c:\Program Files\java\jre7\lib\rt.jar" biblioteka nie jest aktualna ??
Slawek
Szczerze nie spotkałem się z tym błędem, ale tutaj są rozwiązania, które podobno działają: http://stackoverflow.com/questions/860187/access-restriction-on-class-due-to-restriction-on-required-library-rt-jar osobiście wypróbowałbym tą z usunięciem i ponownym dodaniem biblioteki do projektu.
lukas
Neatbeans nie pokazuje żadnego błędu, lecz po kompilacji nie wyskakuje żadne okienko.
lukas
Jre już mi nie krzyczy :) wyskakuje natomiast inny problem : The serializable class MyFrame does not declare a static final serialVersionUID field of type long
Slawek
Ale to tylko warning, a nie błąd, nie powinno mieć to wpływu na działanie programu. Dla spokoju można powiedzieć eclipsowi, czy netbeansowi, żeby sobie dodał to pole w postaci domyślnej, lub losowej. Jest ono potrzebne, gdy serializujemy obiekty, czyli zapisujemy je na dysku, dzięki polu serialVersionUID można je identyfikować.
70stick
Szkoda, że nie robisz filmików było by łatwiej bo mi wciąż wychodzą błędy' i za chwile napisze że mam błąd bo mam nie chce się odpalić, ale i tak super poradniki/lekcje/kursy
Akryl
Utwórz klasę rozszerzającą klasę JFrame. Nic mi to nie mówi.
Witek
Witam Tworzysz nową klasę o nazwie MyFrame, która dziedziczy po klasie JFrame, tak jak masz to napisane w przykładzie musisz to jeszcze raz dokładnie przeczytać jest bardzo dobrze wyjaśnione.
Akryl
Tak zrobiłem i chyba już to rozumiem.
radek
Czy jest ktoś kto pomógłby zrobić zadanie z diagramami?
bartman001
Można jeszcze zrobić tak: setDefaultCloseOperation(3); zamiast JFrame.EXIT_ON_CLOSE dać 3
Marcin
Hej mam takie pytanko: w klasie 'Test' przy "new MyFrame();" wyskakuje mi błąd "Myframe cannot be resolved to a type" co może być tego powodem?
Marcin
Damn o_o Sorry za moją głupotę, problem rozwiązany. Dzięki wielkie za ten kurs, odwaliłeś kawał ŚWIETNEJ roboty :)
bronkz
spoko tylko ja niemoge odpalic tego programu. biore run as i nic niema dalej
Karol2
Jak zrobić żeby okno automatycznie się maksymalizowało(pełny ekran)?
bartek
setExtendedState(JFrame.MAXIMIZED_BOTH);
Anonim
Jak ustawić ikonke programu??? (ta z lewego gornego rogu)
Witek
Witam Ten kod poniżej wstawia nową ikonkę w lewym górnym rogów zamiast ikonki z logiem Javy masz inową ikonkę w tym wypatku jet to Flaga Włoch Toolkit zdjecie = Toolkit.getDefaultToolkit(); Image imag = zdjecie.getImage("wlochy.jpg"); setIconImage(imag);
bartek
Nie wiem dlaczego ale mi się obrazek nie podmienia ? Ktoś wie dlaczego ? W jakiej ma być lokalizacji ?
Janusz
Gdzie umarł nieźle zapowiadający się kurs? Java Start umarło na Swingu. Już polimorfizm został przedstawiony po łebkach z przykładami na kolekcjach. Początkującemu w żaden sposób nie wyjaśniło to po co to dziedziczenie i interfejsy, bo się z kolekcjami nie zapoznał. Pierwsze okienko graficzne i mamy thread runnable uruchamiany run. Proste dla kogoś, kto poznał wątki javy. Cóż, wątków na tym kursie nie było w ogóle. Autorowi zabrakło czasu i weny twórczej, ale chciał kontynuować kurs, więc skończył zagadnienia GUI na skróty, posiłkując się kodem niezrozumiałym dla początkującego. np: EventQueue.invokeLater(new Runnable() { @Override public void run() { new MyFrame();
Sławek Ludwiczak
<i>Autorowi zabrakło czasu i weny twórczej</i> Niestety to prawda - szczególnie pierwszy wymieniony element
Pedro
A jest szansa, że kurs zostanie reaktywowany?
krzysiek
kurs pierwsza klasa, super robota wykonana ale dołączam się do kolegów :) "my chcemy cd kursu" hehe nie zależnie od tego czy będzie cd. czy nie powodzenia i dziękuję za Twoją pracę.
pawel
wyrzuca mi: Error: Could not find or load main class Test dlaczego?
ja
jak sobie z nim poradziles?
pawel
ok już działa
Marcinowy
Sławku, czy jest szansa, że będziesz się opiekował dalej tym kursem, uzupełniając treści? Siedzę już jakiś czas w javie dlatego dużo łatwiej przełyka mi się elementy które tutaj się pojawiają, ale sądzę, że fajnie by było zrozumieć po co się wstawia tego EventQueue z tymi a nie innymi parametrami i w ogóle. Pozdrawiam i dzięki wielkie
m
szkoda że u konkurencji lepiej jest opisana lekcja
Marcin Kunert
Dobrze, że nasi czytelnicy potrafią korzystać z więcej niż jednego źródła :)
NAME (WYMAGANE)
Witam, ja mam pytanie – dlaczego autor ustawia setDefaultExitAction? Wykomentowalem to i okno sie zamyka. Czy chcial pokazac ze takie cos istnieje czy jest inny powod? //Czytaj więcej na: http://javastart.pl/grafika_awt_swing/pierwszy-program-okienkowy/#ixzz2FycaEQTv
Mateusz
Witam, mam takie pytanie, moze sie wydać błache ale nie wiem w jakiej kolejności mam czytać te kursy. Przeniosło mnie do tego kursu ale nic z niego praktycznie nie rozumiem. Mam klikać porostu następna lekcja i samemu dochodzić ocb czy po koleji lecieciec.
PIotrek 112
Witam chciałbym stworyć silnik gry w Javie a potem wrzucić go na strone HTML. Wiem że to nie jest takie proste chciałbym poprosić jak zacząć pisać taki silnik podstwawy.
fokadobra
Zaczynasz od zaawansowane programowanie, pozniej polecalbym przeczytac przydatne klasy, pozniej efektywne programowanie, dopiero pozniej podstawy jezyka java. Pozostałe czesci to juz jak chcesz.
Alex
Po napisaniu: import java.awt.EventQueue; public class Test { public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { new MyFrame(); } }); } } Pokazuje mi błąd The method run() of type new Runnable(){} must override a superclass method w @Override
Piotr
Mam pytanie, tworze aplikację w Netbeans, jednak dostaje komunikat że w jednym pliku mogę utworzyć tylko jedną klasę publiczną. A ponadto importy muszę zrobić w górnej części pliku(a nie w środku). Czy autor tworzy obie klasy w osobnych plikach?
bartek
Jeśli chcesz utworzyć klasy w jednym pliku to jedna z nich powinna być bez public. Jeśli obydwie mają być public to powinny być w osobnych plikach.
fdgfd
haha
Damian
Wie może ktoś jaka jest funkcja która zamyka cały program? Chcę zrobić przycisk który będzie wychodził z programu ale nie mam pojęcia jak to zrobić.
Zatherz
dispose();
Janosch
Czy ktoś może odpowiedzieć na moje pytanie? Treść i kod umieściłem na forum bo tutaj coś nie zapisywało gdy chciałem wysłać komentarz. http://forum.javastart.pl/Thread-Pierwszy-program-okienkowy?pid=1071#pid1071
Kaśka
"Tym razem będzie to jednak aplikacja okienkowa a nie tylko tekst na konsoli. W celu ułatwienia sobie pracy skorzystaj ze środowiska Eclipse." Ach, czyżby? Autor tego kursu zakłada oczywiście, że osoby, które pierwszy raz na poprzednich lekcjach poznały środowisko Eclipse, od razu będą w nim smigać??? Niestety kompletnie nie moge sobie poradzić z ta lekcją, próbuję robić na czuja, ale wciąż jakies błedy wyskakują, nie ma w tej lekcji słowa, co jak zrobić z Eclipse, by to zadziałało, tylko sam kod. Kod sprawy nie załatwia niestety... bo błedy wyskakują Szkoda, bo szło tak dobrze chciałam się nawet ten praktyczny kurs wykupić, bo na studiach nie uczą, sesja się zbliża, a tu taki zonk :/ więcej irytacji niż nauki :(
Kaśka
już nie ważne, zagotowałam sie trochę i to mi chyba pomogło rozwiażać problem, zobaczymy jak to dalej pójdzie, może poprzez "metodą prób i błędów" naucze się jakoś tej Eclipse :) Lecimy dalej :)
lolo
A czytałaś: http://javastart.pl/wprowadzenie/eclipse-ide-wstep-i-instalacja/ http://javastart.pl/wprowadzenie/eclipse-ide-pierwszy-projekt/ http://javastart.pl/wprowadzenie/eclipse-ide-uzytkowanie/
H264
Podzielam wypowiedź #48 Kaśka Troszkę czasu mi to zajęło również mimo że programuję także w innych językach. Mimo to uważam że jest to dość dobrze napisane. Wystarczy pomyśleć i uważnie czytać poprzednie lekcje. Dzięki temu wie się jak to działa tutaj. Początkujący którzy są niecierpliwi mogą się zniechęcić, jednak by programować trzeba mieć cierpliwość, zatem uczyć się :-) Idę dalej z kursem, ciekawe jakie będą następne przeszkody...
lukipt
Tyle ze pamietajmy ze to mial byc kurs od zera.. A tu pierwsza aplikacja okienkowa i mamy tylko dwa kody i tyle... Jest napisane utwórz dwie klasy ale skąd to się bierze: import javax.swing.JFrame; już nie ma ani słowa... tylko coś tam rozszerz jrame..
Lolo
Teoretycznie po wcześniejszych lekcjach powinieneś już potrafić zrozumieć to co jest w tej lekcji. import javax.swing.JFrame; Jest to zaimportowanie Klasy JFrame z pakietu Swing znajdującego się w bibliotece Javax. Była wcześniej mowa o dziedziczeniu więc powinieneś wiedzieć co oznacza rozszerzanie klasy.
bartek
Mam taki problem: zmienną typu string mam w głównej klasie (tam gdzie main) i tam wykonuję większość operacji. W drugim pliku typu class mam zadeklarowane buttony i cały interfejs użytkownika. W jaki sposób (proszę o przykład kodu) przypisać wartość z pola text1 do zmiennej typu string w klasie głównej (wewnątrz main) po kliknięciu buttona ?