Mam aplikację w Gui, gdzie po przyciśnięciu przycisku "Dodaj" do obiektu muszą być wprowadzone 4-5 danych jednocześnie. Do teraz wszystkie moje programy wyglądały na takiej zasadzie, że ActionListener otrzymywał jakieś jedno źródło i na nim wykonywał daną operację. A jak zebrać kilka danych w tym samym momencie, po kliknięciu jednego buttona? Ma ktoś jakiś pomysł?
Kod oczywiście jest niepełny - generalnie ActionListener pobiera informację, która jest przypisana do zdarzenia, a następnie przypisuje ją konkretnemu polu w obiekcie "Adres". Hipotetycznie mogę to zrobić starą metodą, ale pojawia się problem, w którym momencie zdefiniować nowy obiekt, no i po wpisaniu jakiejkolwiek informacji do Textfielda wymagane jest odświeżenie, żeby informacje się nie dublowały, troiły, bo ActionListener i tak przyjmie w jednej chwili jeden obiekt.
public void actionPerformed(ActionEvent e)
{
Object źródło = e.getSource();
if (źródło == rbMezczyzna)
{
}
if (źródło == cTytul)
{
String tytul = cTytul.getSelectedItem().toString();
if (tytul.equals("Brak"));
}
if (źródło == bDodaj)
{
Adres object = new Adres();
}
Dobra, na szybko z palca:
Pierwsza klasa to twój panel/okno, cotainer:
package pl.bgora;
import javax.swing.*;
public class MyPanel extends JPanel {
private JTextField firstName;
private JTextField surname;
private JButton add;
private JButton remove;
//Konstruktor...
public MyPanel() {
initLayout();
initListeners();
}
private void initListeners() {
add.addActionListener(new AddActionListsner(this));
//tutaj dodajesz do remove buttona
}
private void initLayout() {
firstName = new JTextField();
surname = new JTextField();
remove = new JButton();
add = new JButton();
//tutaj dodajesz do panelu i layoutu
}
public JTextField getFirstName() {
return firstName;
}
public void setFirstName(JTextField firstName) {
this.firstName = firstName;
}
public JTextField getSurname() {
return surname;
}
public void setSurname(JTextField surname) {
this.surname = surname;
}
public JButton getAdd() {
return add;
}
public void setAdd(JButton add) {
this.add = add;
}
public JButton getRemove() {
return remove;
}
public void setRemove(JButton remove) {
this.remove = remove;
}
}
I tu masz listener:
package pl.bgora;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class AddActionListsner implements ActionListener {
private MyPanel mypanel;
public AddActionListsner(MyPanel myPanel) {
this.mypanel = myPanel;
}
@Override
public void actionPerformed(ActionEvent e) {
this.mypanel.getFirstName();
this.mypanel.getSurname();
//tu cos robisz
}
}
Poniżej: mojego ActionListenera już wyrzuciłem. Tutaj już nie wykorzystam starych metod:). Cel aktualny - dodać obiekt do listy i swobodnie tym operować, potem się zajmę usuwaniem, edycją, wyświetlaniem.
MainForm.java - odpowiedzialny za wygląd wszystkich okien
package com.company;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.Object;
import java.util.ArrayList;
import javax.swing.AbstractListModel;
/**
* Created by Marcin on 2016-04-01.
*/
public class MainForm extends JFrame implements ActionListener {
public JLabel lImie, lNazwisko, lMiasto, lPoczta, lPlec, lTytul, lKategoria;
public JTextField tImie, tNazwisko, tMiasto, tPoczta;
public ButtonGroup bPlec, bKategoria;
public JRadioButton rbMezczyzna, rbKobieta, rbRodzina, rbZnajomi, rbWspolpracownicy;
public JButton bDodaj;
public JComboBox cTytul;
// ArrayList ma zmienną długość
ArrayList<Object> object = new ArrayList<Object> ();
MainForm()
{
setSize(600,300);
setTitle("Książka adresowa");
setLayout(null);
// labele
lImie = new JLabel("Imię: ");
lImie.setBounds(250,25,80,20);
add(lImie);
lNazwisko = new JLabel("Nazwisko: ");
lNazwisko.setBounds(250,50,80,20);
add(lNazwisko);
lMiasto = new JLabel("Miasto: ");
lMiasto.setBounds(250,75,80,20);
add(lMiasto);
lPoczta = new JLabel("Poczta: ");
lPoczta.setBounds(250,100,80,20);
add(lPoczta);
lPlec = new JLabel("Płeć: ");
lPlec.setBounds(250,125,80,20);
add(lPlec);
lTytul = new JLabel("Tytuł: ");
lTytul.setBounds(250,150,80,20);
add(lTytul);
lKategoria = new JLabel("Kategoria: ");
lKategoria.setBounds(250,175,80,20);
add(lKategoria);
// pola tekstowe
tImie = new JTextField ("");
tImie.setBounds(330,25,180,20);
add(tImie);
tNazwisko = new JTextField("");
tNazwisko.setBounds(330,50,180,20);
add(tNazwisko);
tMiasto = new JTextField("");
tMiasto.setBounds(330,75,180,20);
add(tMiasto);
tPoczta = new JTextField("");
tPoczta.setBounds(330,100,180,20);
add(tPoczta);
// buttony
bDodaj = new JButton("Dodaj");
bDodaj.setBounds (250, 210, 100,30);
add(bDodaj);
bDodaj.addActionListener(this);
bPlec = new ButtonGroup();
rbMezczyzna = new JRadioButton("Mężczyzna");
rbMezczyzna.setBounds(330,125,100,20);
bPlec.add(rbMezczyzna);
add(rbMezczyzna);
rbMezczyzna.addActionListener(this);
rbKobieta = new JRadioButton("Kobieta");
rbKobieta.setBounds(430,125,80,20);
bPlec.add(rbKobieta);
add(rbKobieta);
rbKobieta.addActionListener(this);
// buttony - rbRodzina, rbZnajomi, rbWspolpracownicy
bKategoria = new ButtonGroup();
rbRodzina = new JRadioButton("Rodzina");
rbRodzina.setBounds(330,175,80,20);
bKategoria.add(rbRodzina);
add(rbRodzina);
rbRodzina.addActionListener(this);
rbZnajomi = new JRadioButton("Znajomi");
rbZnajomi.setBounds(410,175,80,20);
bKategoria.add(rbZnajomi);
add(rbZnajomi);
rbZnajomi.addActionListener(this);
rbWspolpracownicy = new JRadioButton("Znajomi");
rbWspolpracownicy.setBounds(490,175,80,20);
bKategoria.add(rbWspolpracownicy);
add(rbWspolpracownicy);
rbWspolpracownicy.addActionListener(this);
// ComboBox
cTytul = new JComboBox();
cTytul.setBounds(330,150,180,20);
cTytul.addItem("Brak");
cTytul.addItem("Inżynier");
cTytul.addItem("Magister");
cTytul.addItem("Doktor");
cTytul.addItem("Profesor");
add(cTytul);
}
Object.java - klasa przechowująca informacje o pojedynczej osobie w książce adresowej (następnie taki pojedynczy obiekt wsadzamy do Arraylisty typu Object)
package com.company;
/**
* Created by Marcin on 2016-04-01.
*/
public class Object {
public enum Tytul {
brak, magister, inzynier, doktor, profesor;
}
public enum Kategoria {
znajomi, rodzina, wspolpracownicy;
}
private String imie;
private String nazwisko;
public String getImie() {
return imie;
}
public String getNazwisko() {
return nazwisko;
}
public String getMiasto() {
return miasto;
}
public String getMeil() {
return meil;
}
public double getNumer() {
return numer;
}
public boolean isPlec() {
return plec;
}
public Tytul getTytul() {
return tytul;
}
public Kategoria getKategoria() {
return kategoria;
}
private String miasto; // Adres
private String meil;
private double numer;
public void setTytul(Tytul tytul) {
this.tytul = tytul;
}
public void setKategoria(Kategoria kategoria) {
this.kategoria = kategoria;
}
public void setNumer(double numer) {
this.numer = numer;
}
public void setPlec(boolean plec) {
this.plec = plec;
}
public void setMeil(String meil) {
this.meil = meil;
}
public void setMiasto(String miasto) {
this.miasto = miasto;
}
public void setImie(String imie) {
this.imie = imie;
}
public void setNazwisko(String nazwisko) {
this.nazwisko = nazwisko;
}
private boolean plec;
private Kategoria kategoria;
private Tytul tytul;
}
Main wywołujący obiekt typu Mainform.
package com.company;
import javax.swing.*;
public class Main {
public static void main(String[] args) {
MainForm appMenu = new MainForm(); // obiekt klasy main
appMenu.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
appMenu.setVisible(true); // nasze okno jest widzialne
}
}
I z czym dokładnie masz problem? Musisz utworzyć obiekt klasy Object (dlaczego nie nazwałeś go Osoba?). W tym momencie mógłbyś zrobić po prostu tak:
com.company.Object osoba = new com.company.Object();
osoba.setImie(...);
osoba.setNumer(...);
...
Jednak istnieje coś takiego jak konstruktor, czyli coś, co pozwoli Ci zrobić:
com.company.Object osoba = new com.company.Object(imie, nazwisko, numer, ...);
Tworzy się go tak:
public class Object {
...
public Object(String imie, String nazwisko, int numer, ...) {
this.imie = imie;
this.nazwisko = nazwisko;
this.numer = numer;
...
}
...
}
Klasa Main jest ok. Dobrze, że masz to zrobione w osobnej klasie.
Teraz tak: Bardzo ważna uwaga: Nie nazywaj Klasy Object - bo java.lang.Object jest Klasą rodzicem wszystkiego, każda klasa w Javie dziedziczy po klasie Object (niejawnie).
Zmień tą klasę np. Na PhonePerson, PhoneData coś takiego.
Jeśli chodzi o MainForm, tu usuń implements ActionListener i zamiast tego w pakiecie com.company dodaj sobie Klasy, które implelementują ActionListener, dla każdego Przycisku np:
bDodaj = new JButton("Dodaj");
bDodaj.setBounds (250, 210, 100,30);
add(bDodaj);
bDodaj.addActionListener(this);
Zamień na:
bDodaj = new JButton("Dodaj");
bDodaj.setBounds (250, 210, 100,30);
add(bDodaj);
bDodaj.addActionListener(new DodajListener(this));
gdzie DodajListener będzie wyglądać tak:
public class DodajListener implements ActionListener {
private MainForm mainForm;
public DodajListener(MainForm mainForm){
this.mainForm = mainForm;
}
@Override
public void actionPerformed(ActionEvent e) {
//tutaj cos robisz z mainForm
}
}
W porządku, dzięki za podpowiedzi. Popracuję nad tym i wrzucę niedługo edytowany kod :).
Okej, póki co kod wygląda tak:
package com.company;
import com.company.MainForm;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class DodajListener implements ActionListener {
private MainForm mainForm;
public DodajListener(MainForm mainForm){
this.mainForm = mainForm;
}
@Override
public void actionPerformed(ActionEvent e) {
Object źródło = e.getSource();
Osoba osoba = new Osoba();
if (źródło == mainForm.bDodaj)
{
osoba.setImie(mainForm.tImie.getText());
osoba.setNazwisko(mainForm.tNazwisko.getText());
osoba.setMiasto(mainForm.tMiasto.getText());
osoba.setMeil(mainForm.tPoczta.getText());
//osoba.setPlec(mainForm.getInputContext(mainForm.rbMezczyzna));
System.out.println(osoba.getImie());
System.out.println(osoba.getNazwisko());
System.out.println(osoba.getMiasto());
System.out.println(osoba.getMeil());
mainForm.ksiazkaAdresowa.add(osoba);
}
}
}
Mamy dokonać walidacji danych FocusListenerem. Ma ktoś jakiś dobry poradnik, jak to obsługiwać? Chodzi o sprawdzanie poprawności danych, czy coś wpisaliśmy, czy mamy znak "@" w meilu. Kolejna sprawa - jak pobrać wartości logiczne z RadioButtonów i ComboBoxa? Chodzi mi o to, że jak np. button rbMezczyzna ma wartość "true", to go wstawiamy do naszego obiektu "osoba" (będę robił oczywiście ify).
Niepotrzebnie sprawdzasz if(żródło....) - jeśli dodałeś tego listenera do bDodaj, to jesteś pewny, że akcja wywołana jest na kliknięcie bDodaj.
bUsun powinien mieć własny listener i tak dalej i tak dalej. Generalnie każdy jeden button= 1 listener.
Widzę dużo przyzwyczajeń z C++ :).
Rada praktyczna: w Javie używamy camelCase i nie wpisujemy skrótu od typu danych np. int counter a nie int iCounter.
Jeśli chodzi o focusListener to osobiście byłem programistą Swinga jakieś 6 lat temu, wtedy tego nie było :D, ale https://docs.oracle.com/javase/7/docs/api/java/awt/event/FocusListener.html z tego co rozumiem, to działa w momencie jak "wchodzisz" na kontrolkę, albo jak "wychodzisz" z kontrolki.
Po prostu robisz listener, który używa wyrażeń regularnych (są gotowce na sieci) do sprawdzenia, czy np. email jest w dobrym formacie.