Gyakorlati alapok IV.
Végre ablakozunk! (AWT, Swing, JavaFX)
Eseménykezelés + Button + Textfield + IP-cím
Az előző, Eseménykezelés + Button + IP-cím című fejezetben gombeseményként implementáltunk egy DNS-lekérdezést. Azonban egyre jobban láthatjuk az ablakos és konzolos alkalmazásaink közti egyéb korlátokat, különbségeket. Ebben a konkrét esetben nagyon nem volt elegáns a hostnév szövegét a kódba helyezni (String hostName = "localhost";). Pontosan erre való a szövegdoboz (textfield) nevű objektum, amely ilyen módon szövegek fogadására alkalmas és ezen változtatást a Java-rendszer önálló eseményként képes értelmezni.
A textfield és egyéb további vizuális objektumok segítségével ebben a projektben egy olyan programot fogunk megalkotni, amely már teljes egészében GUI-alapokon áll (Graphical User Interface), azaz ez lesz az 1. olyan eset, ahol teljesen kizárjuk a konzolt és a forráskódot.
Alkalmazásunk formai jellegzetességeit érdemes előzetesen vagy precízen, vagy elnagyoltan megtervezni. A magam részéről egy rajzoló program segítségével viszonylag könnyen felvázoltam a program keretét és 3 db interaktív objektumát...
...ahol a legfelső a textfield, a középső a button, az alsó pedig a label lesz. Ez azért is volt hasznos, mert a grid (rácsozat) segítségével pixelre pontosan ki tudtam számítani az objektumok szimmetrikus helyeit:
textfield.setBounds(100, 50, 200, 25);
button.setBounds(100, 100, 200, 25);
label.setBounds(100, 150, 200, 25);
frame.setSize(400, 300);
A GUI-alapok azt is megkövetelik, hogy minden problémát, kivételt, érvénytelen szövegbevitelt szintén vizuálisan kezeljünk le (értsd: a felhasználót vizuális objektumokkal tájékoztassuk). Ebben a programban mindez nem volt túl bonyolult, csupán 2 esetet kellett lekezelni:
-
ha a textfield üres, ám a felhasználó mégis rákattint a Resolve it! gombra,
-
ha bármilyen kivétel keletkezik, amely lehet:
-
bármely olyan beírt szöveg, amelyet a Java-rendszer nem tud névfeloldani,
-
egyéb hálózati hiba, probléma.
-
A hiba formai lekezelése egységesen üzenetablakokkal történt, amelyet viszonylag könnyű meghívnunk, például üres textfield esetében:
JOptionPane.showMessageDialog(frame, "Empty textfield!");
Az eredmény kiíró label alaptulajdonságaival a magam részéről nem voltam megelégedve, ezért a szükséges importálás után (import java.awt.Font;) a...
label.setFont(new Font("Serif", Font.PLAIN, 25));
...rutinnal tovább állítottam. Ugyanakkor azt is jól láthatjuk, hogy az objektumok belső adatait az objektumorientált elveknek megfelelően valóban nem tudjuk direktben elérni, azokat csak nagyon ellenőrzött kröülmények között getter-setter függvények segítségével módosíthatjuk.
Nézzük meg a futtatható Java-kódot:
Main.java
public class Main {
public static void main(String[] args) {
Window window = new Window();
}
}
Window.java
import java.awt.Font;
import javax.swing.*;
class Window extends JFrame {
JFrame frame = new JFrame();
JButton button = new JButton("Resolve it!");
JLabel label = new JLabel();
JTextField textfield = new JTextField();
Window() {
super();
textfield.setBounds(100, 50, 200, 25);
button.setBounds(100, 100, 200, 25);
label.setBounds(100, 150, 200, 25);
label.setFont(new Font("Serif", Font.PLAIN, 25));
frame.add(button);
frame.add(label);
frame.add(textfield);
label.setText("The IP-number is...");
textfield.setText("");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button.addActionListener(event -> buttonAction());
Center center = new Center();
frame.setSize(400, 300);
frame.setTitle("PJP - Penzes Java Programming");
center.setCenter(frame);
frame.setLayout(null);
frame.setVisible(true);
}
private void buttonAction() {
label.setFont(new Font("Serif",
Font.PLAIN, 25));
String ipNumber = "";
if(textfield.getText().equals("")) {
JOptionPane.showMessageDialog(frame, "Empty textfield!");
label.setText("The IP-number is...");
return;
}
String hostName =
textfield.getText();
try{
ipNumber =
java.net.InetAddress.getByName(hostName).getHostAddress();
label.setText(ipNumber);
label.setFont(new Font("Serif",
Font.PLAIN, 33));
}catch(Exception ex){
JOptionPane.showMessageDialog(frame, "Name resolution or network problem!");
label.setText("The IP-number is...");
textfield.setText("");
return;
}
}
}
Center.java
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import javax.swing.JFrame;
public class Center {
void setCenter(JFrame frame) {
Point center =
GraphicsEnvironment.getLocalGraphicsEnvironment().getCenterPoint();
int x = (int) center.getX() -
(frame.getWidth() / 2);
int y = (int) center.getY() -
(frame.getHeight() / 2);
Point ablakCenter = new Point(x, y);
frame.setLocation(ablakCenter);
}
}
Végeredmény (a monitor közepén / felbontástól függetlenül/):
-
exit, a Resolve it! és a textfield működik, kivételek lekezelve