Γραφικά Ενδιάμεσα Χρήστη στην Java Δρ. Παναγιώτης Αλεφραγκής ΣΕΠ ΕΑΠ ΠΛΗ24 20-Μαρ-07
Σύγχρονα προγράμματα με γεγονότα Πολλαπλές πηγές εισόδου Ποντίκι πληκτρολόγιο Χρονιστές Εξωτερικά γεγονότα Απαιτείται νέα δομή προγράμματος Περίμενε γεγονός Επεξεργασία γεγονότος Έξοδος
Η Java κρύβει την επανάληψη ελέγχου γεγονότων Η επανάληψη γεγονότων περιέχεται στα Java GUIs GUI σημαίνει Graphical User Interface Η αλληλεπίδραση με ένα GUI Component (π.χ. κουμπί) δημιουργεί ένα γεγονός Στην Java το γεγονός (Event) είναι αντικείμενο Δημιουργούμε Listeners για τα ενδιαφέροντα γεγονότα Οι Listener παίρνουν Event σαν παραμέτρους
Κατασκευάζοντας ένα GUI... 1. Φτιάξτε χώρο για να τοποθετήσετε τα γραφικά αντικείμενα (ένα Container) Συνήθως χρησιμοποιούμε ένα JFrame ή ένα JApplet 2. Φτιάχνουμε μερικά Components (buttons, text areas, panels, κλπ.) Δηλώνουμε τα Components σαν πεδία της κλάσης, και Ορίζουμε κάποια μέθοδο αρχικοποίησης του GUI 3. Προσθέτουμε Listeners στα Components Δημιουργούμε εσωτερικές κλάσεις που υλοποιούν κάποιο Interface τύπου Listener Δημιουργούμε αντικείμενα των εσωτερικών κλάσεων Συνδέουμε αυτά τα αντικείμενα με τα αντίστοιχα Component 4. Προσθέτουμε τα Components Επιλέγουμε ένα layout manager Προσθέτουμε τα Components στον Container βάση των κανόνων που απαιτεί ο layout manager που επιλέξαμε
Containers και Components Ένα GUI δημιουργείται τοποθετώντας components σε containers Δουλειά του Container είναι να κρατά και να παρουσιάζει τα Components που περιέχει Συχνά χρησιμοπούμενες υποκλάσεις της Component είναι JButton, JCheckbox, JLabel, JTextField και JTextArea Οι Container είναι και Component Επιτρέπει να έχουμε ενφωλιασμένα Containers Σημαντικές υποκλάσεις Container είναι JFrame, JApplet και JPanel Στα JFrame και JApplet μπορούμε να πάρουμε τον χώρο τοποθέτηση γραφικών τμημάτων κάνοντας χρήση της getContentPane() Συνήθως κατασκευάζουμε και χρησιμοποιούμε απευθείας τα JPanels
Το JApplet είναι Panel είναι Container java.lang.Object | java.awt.Component | java.awt.Container | java.awt.Panel | java.applet.Applet javax.swing.JApplet …άρα μπορείτε να εμφανίσετε κάτι σε ένα Applet
Ξεκινώντας με ένα Container Πρώτα εισάγουμε μερικά πακέτα: import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; Μετά επεκτείνουμε ένα Container: Για να φτιάξουμε μία εφαρμογή επεκτείνουμε την JFrame public class MyClass extends JFrame { ... } Η κλάση JFrame περιέχει την μέθοδο getContentPane() η οποία επιστρέφει Container προς χρήση: getContentPane( ).doSomething( );
Μερικοί τύποι components JCheckBox JButton JLabel JScrollBar Choice JTextField JList JTextArea JButton ButtonGroup JRadioButton
Διατάσσοντας components Κάθε Container έχει ένα layout manager Δεν αποφασίζουμε άμεσα που θα τοποθετηθούν τα components, αυτό το αποφασίζει ο layout manager Το προεπιλεγμένο layout για το JPanel είναι FlowLayout Το προεπιλεγμένο layout για το JFrame είναι BorderLayout Μπορούμε να θέσουμε άμεσα το layout manager setLayout(new FlowLayout()); setLayout(new BorderLayout());
Παράδειγμα: FlowLayout import javaχ.swing.*; import java.awt.*; public class FlowLayoutExample extends JFrame{ public void init () { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout (new FlowLayout ()); add (new JButton ("One")); add (new JButton ("Two")); add (new JButton ("Three")); add (new JButton ("Four")); add (new JButton ("Five")); add (new JButton ("Six")); } public static void main(String[] args){ FlowLayoutExample f = new FlowLayoutExample(); f.setSize(200,150); f.init(); f.setVisible(true);
Παράδειγμα: BorderLayout import javax.swing.*; import java.awt.*; public class BorderLayoutExample extends JFrame{ public void init () { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout (new BorderLayout ()); add (new JButton ("One"),BorderLayout.NORTH); add (new JButton ("Two"),BorderLayout.WEST); add (new JButton ("Three"),BorderLayout.CENTER); add (new JButton ("Four"),BorderLayout.EAST); add (new JButton ("Five"), BorderLayout.SOUTH); add (new JButton ("Six"), BorderLayout.SOUTH); } public static void main(String[] args){ BorderLayoutExample f = new BorderLayoutExample(); f.setSize(200,150); f.init(); f.setVisible(true);
Χρησιμοποιώντας ένα JPanel import javax.swing.*; import java.awt.*; public class BorderLayoutExample extends JFrame{ public void init () { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout (new BorderLayout ()); add (new JButton ("One"),BorderLayout.NORTH); add (new JButton ("Two"),BorderLayout.WEST); add (new JButton ("Three"),BorderLayout.CENTER); add (new JButton ("Four"),BorderLayout.EAST); JPanel p = new JPanel(); add (p,BorderLayout.SOUTH); p.add (new JButton ("Five")); p.add (new JButton ("Six")); } public static void main(String[] args){ BorderLayoutExample f = new BorderLayoutExample(); f.setSize(200,150); f.init(); f.setVisible(true);
Φτιάχνοντας ενεργά components Για να συνδέσουμε μια ενέργεια με ένα component, προσθέτουμε ένα παρακολουθητή (listener) Τα Components δημιουργούν γεγονότα (events), οι παρακολουθητές ακούν τα γεγονότα Τα διάφορα components δημιουργούν διαφόρων τύπων γεγονότα και άρα απαιτούν διαφόρων τύπων παρακολουθητές
MyButtonListener 1 2 import javax.swing.*; import java.awt.*; import java.awt.event.*; public class ButtonListener extends JFrame{ JButton b1=new JButton ("Πάτα με"); JLabel l1=new JLabel("Πριν"); public void init () { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout (new FlowLayout ()); add (l1); add (b1); b1.addActionListener (new MyButtonListener ()); } public static void main(String[] args){ ButtonListener f = new ButtonListener(); f.setSize(200,100); f.init(); f.setVisible(true); class MyButtonListener implements ActionListener { public void actionPerformed (ActionEvent e) { l1.setText("Μετά"); 1 2
MyButtonListener 3 1 2 import javax.swing.*; import java.awt.*; import java.awt.event.*; public class ButtonListener extends JFrame{ JButton b1=new JButton ("Πάτα με"); JLabel l1=new JLabel("Πριν"); public void init () { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout (new FlowLayout ()); add (l1); add (b1); b1.addActionListener (new MyButtonListener ()); } public static void main(String[] args){ ButtonListener f = new ButtonListener(); f.setSize(200,100); f.init(); f.setVisible(true); class MyButtonListener implements ActionListener { public void actionPerformed (ActionEvent e) { l1.setText("Μετά"); 3 1 2
Φτιάχνοντας Μικροεφαρμογές Δημιουργούνται παρόμοια με τις εφαρμογές Eπεκτείνουμε την JApplet αντί της JFrame public class MyApplet extends JApplet { ... } Ορίζουμε την μέθοδο init() του applet για αρχικοποίηση Το JApplet περιέχει ένα JPanel για αυτό έχει διάταξη FlowLayout Τα JApplet δεν έχουν main.
GameStore - Ερώτηση 3 - Απάντηση (2) Υλοποίηση: Επαναλαμβάνουμε μέσα σε ένα βρόγχο, για κάθε παιχνίδι, τα βήματα της κατασκευής του αντίστοιχου JLabel και JTextField. Τα νέα αντικείμενα τα αποθηκεύουμε αντίστοιχα σε δύο πίνακες labels και textFileds. Για την παρουσίαση του συνολικού εισοδήματος και κέρδους κατασκευάζουμε από ένα ζευγάρι JLabel και JTextField τα l1, f1 και l2,f2. Κουμπί για την έναρξη της διαδικασίας για τον υπολογισμό του συνολικού εισοδήματος και κέρδους και την ενημέρωση των αντίστοιχων JTextField, δηλαδή των f1 , f2. Για καλύτερη χωροταξική τοποθέτηση των αντικειμένων του γραφικού περιβάλλοντος δημιουργούμε δύο JPanel για την τοποθέτηση των αντίστοιχων γραφικών αντικειμένων.
Από getContentsPane() UI Design JFrame JPanel Από getContentsPane() JLabel JTextField JPanel Το JPanel1 JButton JPanel Το JPanel2
UI Design contentPane = (JPanel)this.getContentPane(); contentPane.setLayout(verticalFlowLayout1); this.setSize(new Dimension(400, 300)); this.setTitle("Frame Title");
Γενικό, Υποστηρίζει περισσότερα παιχνίδια στο μέλλον UI Design Απλοϊκό Label[0] = “Lane1 (4,0)” textFields[0] = “0” Label[1] = “Lane2 (4,0)” textFields[1] = “0” Label[2] = “Table1 (4,0)” textFields[2] = “0” Γενικό, Υποστηρίζει περισσότερα παιχνίδια στο μέλλον textFields = new JTextField[s.games.length]; labels = new JLabel[s.games.length]; for (int i = 0; i < s.games.length; i++) { textFields[i] = new JTextField("0", 10); labels[i] = new JLabel(s.games[i].getName() + " (" + String.valueOf(s.games[i].getIncome()) + ")"); contentPane.add(labels[i]); contentPane.add(textFields[i]); }
UI Design jPanel1.add(l1, null); l1 = new JLabel("Έσοδα:"); jPanel1.add(f1, null); jPanel1.add(l2, null); jPanel1.add(f2, null); contentPane.add(jPanel1, null); l1 = new JLabel("Έσοδα:"); l2 = new JLabel("Κέρδος:"); f1 = new JTextField(10); f2 = new JTextField(10);
UI Design b1 = new JButton("Ανανέωση"); b1.addActionListener(h1); contentPane.add(jPanel2, null); jPanel2.add(b1, null); jPanel2.add(jButton1, null); b1 = new JButton("Ανανέωση"); b1.addActionListener(h1); jButton1.setText("ΣΤΑΤΙΣΤΙΚΑ"); jButton1.addActionListener(new StoreFrame_jButton1_actionAdapter(this));
UI Design _____ contentPane _____ jPanel1 _____ jPanel2 contentPane.add(jPanel1, null); contentPane.add(jPanel2, null);
Χειρισμός γεγονότων Δημιουργεί ένα γεγονός ActionListener actionPerformed Το γεγονός Αισθητήρας συμβάντος Συστατικό
Υλοποίηση της ενέργειας του «Ανανέωση» private class MyHandler1 implements ActionListener { public void actionPerformed(ActionEvent e) { for (int i = 0; i < s.games.length; i++) { s.updateGameUses(i, Double.parseDouble(textFields[i].getText())); } f1.setText(String.valueOf(s.getIncome())); f2.setText(String.valueOf(s.getProfit())); storeToLog();
Ανακεφαλαίωση I: Υλοποιώντας GUI Φτιάχνουμε ένα container, π.χ. JFrame ή JApplet Επιλέγουμε layout manager Φτιάχνουμε συνθετότερα layouts προσθέτοντας JPanels Κάθε JPanel μπορεί να έχει δικό του layout manager Δημιουργούμε τα διάφορα components και τα προσθέτουμε στο JPanels που επιθυμούμε
Ανακεφαλαίωση IΙ: Υλοποιώντας GUI Για κάθε ενεργό component, βρείτε τον τύπο του Listeners που επιθυμούμε Υλοποιούμε (implement) τους Listeners Συχνά έχουμε ένα Listener για κάθε component Μπορούμε να παρακολουθούμε περισσότερα από ένα components με ένα Listener Για κάθε Listener υλοποιούμε τις απαιτούμενες μεθόδους Για τα applets, γράφουμε και την σχετική HTML
Λεξιλόγιο Swing – Η βιβλιοθήκη γραφικών Container – ένα γραφικό τμήμα που μπορεί να περιέχει άλλα γραφικά τμήματα (είναι το ίδιο ένα Component) Component – ένα γραφικό τμήμα (π.χ JButton ή JTextArea) που παρέχεται από την βιβλιοθήκη γραφικών listener – Ένα τμήμα κώδικα που αναλαμβάνει να ενεργοποιηθεί όταν δημιουργηθεί ένα συγκεκριμένο είδος γεγονότος από τα γραφικά αντικείμενα που παρακολουθεί layout manager – Ένα αντικείμενο που αναλαμβάνει να τοποθετήσει τα Components σε ένα Container