Problem z GUI w Javie

0

Witam.

Moim zadaniem jest stworzyć prosty interfejs graficzny. Uprzedzając pytanie - tak jestem świadomy, że do stworzenia GUI mogę wykorzystać builder wbudowany np w NetBeansa. Przejdźmy do sedna problemu.

Obecnie wszystko działa tak jak powinno z jednym wyjątkiem. Po uruchomieniu programu, okno albo jest puste albo nie wyświetlają się wszystkie elementy. Może wyświetlić się np. samo menu, albo menu z jednym z JButtonow (z tym że tło programu wtedy jest jednolite białe - nie widać paneli) albo jeszcze jakoś inaczej. Najczęściej nie wyświetla się nic. Wszystko wraca do normy gdy zmienimy rozmiar okna dosłownie o 1 piksel (rozszerzając za pomocą myszki po odpaleniu programu). Wtedy w magiczny sposób pojawia się wszystko - i menu i oba panele ze wszystkimi elementami i kolorami tła. Dlaczego tak się dzieje i jak to naprawić?

I jeszcze kolejne pytanie: Jak teraz zrobić, żeby pokazywały się odpowiednie panele w zależności od tego co wybierzemy z Menu?

Proszę o pomoc.

Klasa Start z metodą main:

 import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Start {

    public static void main(String[] args) {
        Okno program = new Okno();
        
       
    }
}

Klasa Okno:

 import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Okno extends JFrame{
    
    Okno(){
        super("Nazwa Robocza");
        this.setVisible(true);
        this.setDefaultCloseOperation(3);
        this.setLayout(null);
        this.setSize(615,410);
        this.setLocation(100,100);
        initComponent();
          
    }
    
    
    void initComponent(){
        JMenuBar menu = new Menu();
        setJMenuBar(menu);
                
        JPanel noweKontoSuperKontoPanel = new NoweKontoSuperKontoPanel();
        add(noweKontoSuperKontoPanel);
        
        JPanel wplataKontoPanel = new WplataKontoPanel();
        add(wplataKontoPanel);

    }
    
}

Klasa Menu:

 import javax.swing.*;
import java.awt.*;

public class Menu extends JMenuBar{
    
    Menu(){
        JMenu konto = new JMenu("Konto      ");
        JMenu kontoWalutowe = new JMenu("Konto Walutowe     ");
        JMenu kontoSuper = new JMenu("Super Konto       ");
        add(konto);
        add(kontoWalutowe);
        add(kontoSuper);
        
        JMenuItem wplata = new JMenuItem("Wpłata");
        JMenuItem wyplata = new JMenuItem("Wypłata");
        JMenuItem noweKonto = new JMenuItem("Nowe Konto");
        JMenuItem wplataWalutowe = new JMenuItem("Wpłata");
        JMenuItem wyplataWalutowe = new JMenuItem("Wypłata");
        JMenuItem noweKontoWalutowe = new JMenuItem("Nowe Konto");
        JMenuItem noweKontoSuper = new JMenuItem("Nowe Konto");
        
        konto.add(wplata);
        konto.add(wyplata);
        konto.add(noweKonto);
        
        kontoWalutowe.add(wplataWalutowe);
        kontoWalutowe.add(wyplataWalutowe);
        kontoWalutowe.add(noweKontoWalutowe);
        
        kontoSuper.add(noweKontoSuper);
        
        this.setVisible(true);
        
    }
    
}

Klasa NoweKontoSuperKontoPanel:

 import javax.swing.*;
import java.awt.*;

public class NoweKontoSuperKontoPanel extends JPanel{
    
    NoweKontoSuperKontoPanel(){
        JLabel labelSuperKontoNoweKontoImie = new JLabel("Imie:");
        add(labelSuperKontoNoweKontoImie);
        JTextField textSuperKontoNoweKontoImie = new JTextField();
        add(textSuperKontoNoweKontoImie);
        
        JLabel labelSuperKontoNoweKontoNazwisko = new JLabel("Nazwisko:");
        add(labelSuperKontoNoweKontoNazwisko);
        JTextField textSuperKontoNoweKontoNazwisko = new JTextField();
        add(textSuperKontoNoweKontoNazwisko);
        
        JButton superKontoNoweKontoUtworzkonto = new JButton("Utwórz Super Konto");
        add(superKontoNoweKontoUtworzkonto);
        
        //ROZKŁAD ELEMENTÓW
        this.setLayout(null);
        this.setSize(300,350);
        this.setLocation(0,0);
        this.setBackground(Color.blue);
        
        labelSuperKontoNoweKontoImie.setLocation(10,40);
        labelSuperKontoNoweKontoImie.setSize(100,50);
        textSuperKontoNoweKontoImie.setLocation(150,55);
        textSuperKontoNoweKontoImie.setSize(120,25);
        
        labelSuperKontoNoweKontoNazwisko.setLocation(10,110);
        labelSuperKontoNoweKontoNazwisko.setSize(100,50);
        textSuperKontoNoweKontoNazwisko.setLocation(150,120);
        textSuperKontoNoweKontoNazwisko.setSize(120,25);
        
        superKontoNoweKontoUtworzkonto.setLocation(10,210);
        superKontoNoweKontoUtworzkonto.setSize(260,50);
        
    }
    
}

Klasa WplataKontoPanel:

 import javax.swing.*;
import java.awt.*;

public class WplataKontoPanel extends JPanel{
    
    WplataKontoPanel(){
    
        JLabel labelKontoWplataWybierzKonto = new JLabel("Wybierz Konto:");
        add(labelKontoWplataWybierzKonto);
        JList listaKontoWplata = new JList();
        add(listaKontoWplata);
        
        JLabel labelKontoWplataKwota = new JLabel("Kwota:");
        add(labelKontoWplataKwota);
        JTextField textKontoWplataKwota = new JTextField();
        add(textKontoWplataKwota);
        
        JButton kontoWplata = new JButton("Wpłata");
        add(kontoWplata);
        
        //ROZKŁAD ELEMENTÓW
        this.setLayout(null);
        this.setSize(300,350);
        this.setLocation(300,0);
        this.setBackground(Color.pink);
        
        labelKontoWplataWybierzKonto.setLocation(10,40);
        labelKontoWplataWybierzKonto.setSize(100,50);
        listaKontoWplata.setLocation(150,60);
        listaKontoWplata.setSize(120,100);
        
        labelKontoWplataKwota.setLocation(10,195);
        labelKontoWplataKwota.setSize(100,50);
        textKontoWplataKwota.setLocation(150,210);
        textKontoWplataKwota.setSize(120,25);
        
        kontoWplata.setLocation(10,280);
        kontoWplata.setSize(260,50);
        
    }
    
}

Oraz cały projekt do pobrania jeśli ktoś chce się pobawić:
https://www.dropbox.com/s/g7sd0rk6ie9fn0m/ProjektZaliczeniowy.rar

Pozdrawiam

3

Za szybko wyświetlasz okno, ono jest dopiero konstruowane.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Start {

    public static void main(String[] args) {
        //Okno program = new Okno();
        SwingUtilities.invokeLater(new Runnable() 
        {
            public void run() 
            {
                new Okno();
            }
        });               
    }
}
0

Wielkie dzięki ;)

A jak teraz zrobić, żeby pokazywały się odpowiednie panele w zależności od tego co wybierzemy z JMenuBar?

Potrafię w klasie Menu napisać instrukcję actionPerformed dzięki której po wyborze z Menu --> Konto --> Wplata w konsoli pojawi się tekst:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Menu extends JMenuBar implements ActionListener{
    
    Menu(){
        JMenu konto = new JMenu("Konto      ");
        JMenu kontoWalutowe = new JMenu("Konto Walutowe     ");
        JMenu kontoSuper = new JMenu("Super Konto       ");
        add(konto);
        add(kontoWalutowe);
        add(kontoSuper);
        
        JMenuItem wplata = new JMenuItem("Wpłata");
        JMenuItem wyplata = new JMenuItem("Wypłata");
        JMenuItem noweKonto = new JMenuItem("Nowe Konto");
        JMenuItem wplataWalutowe = new JMenuItem("Wpłata");
        JMenuItem wyplataWalutowe = new JMenuItem("Wypłata");
        JMenuItem noweKontoWalutowe = new JMenuItem("Nowe Konto");
        JMenuItem noweKontoSuper = new JMenuItem("Nowe Konto");
        
        konto.add(wplata);
        konto.add(wyplata);
        konto.add(noweKonto);
        
        kontoWalutowe.add(wplataWalutowe);
        kontoWalutowe.add(wyplataWalutowe);
        kontoWalutowe.add(noweKontoWalutowe);
        
        kontoSuper.add(noweKontoSuper);
        
        this.setVisible(true);
        
        wplata.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent x){
                System.out.println("Klik");
            }
        });
        
    }
    
        public void actionPerformed(ActionEvent p){    
        }  
}

Co ciekawe musiałem na końcu dodać pustą metodę actionPerformed, ponieważ bez niej wywalało błąd przy implements ActionListener:

Menu is not abstract and does not override abstract method actionPerformed(ActionEvent) in ActionListener

Coraz ciekawsza robi się ta Java...

Dobra, do rzeczy. Potrafię już zrobić, żeby pojawiał się w konsoli tekst po wybraniu elementu Menu. Ale ja potrzebuję, żeby zamiast tego wyświetlały się odpowiednie panele.
Z tym, że metodę z tekstem zapisałem w klasie Menu, a żeby zrobić wyświetlanie paneli potrzebuję napisać odpowiednią metodę w klasie Okno. I tutaj pojawia się problem. W klasie Okno tworzę obiekt klasy Menu:

JMenuBar menu = new Menu();
setJMenuBar(menu);

I teraz nie mogę odnieść się w żaden sposób do konkretnego JMenuItem z klasy Menu, tak jak jest w przykładzie z tekstem w konsoli:

wplata.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent x){
                System.out.println("Klik");
            }
        });

Jak widać odwoływałem się do JMenuItem o nazwie wplata. W jaki sposób mogę odnieść się do tego w innej klasie (Okno)?
Miałęm zamiar zrobić to mniej więcej tak:

wplata.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent x){
                JPanel wplataKontoPanel = new WplataKontoPanel();
                add(wplataKontoPanel);
            }
        });

Ale się nie da ;(
Co robię nie tak?

0
Technolog napisał(a):

Co ciekawe musiałem na końcu dodać pustą metodę actionPerformed, ponieważ bez niej wywalało błąd przy implements ActionListener:

Menu is not abstract and does not override abstract method actionPerformed(ActionEvent) in ActionListener

Coraz ciekawsza robi się ta Java...

No a po co Menu ma interfejs ActionListener?
Interfejsy narzucają nadpisanie swoich metod w klasie, która je implementuje - co też zrobiłeś dodając pustą metodę actionPerformed.
Wywal po prostu kawałek "implements ActionListener".

Te panele które chcesz żeby się pokazywały, mogłyby być chyba oknami dialogowymi hmm?

0

No a po co Menu ma interfejs ActionListener?
Interfejsy narzucają nadpisanie swoich metod w klasie, która je implementuje - co też zrobiłeś dodając pustą metodę actionPerformed.
Wywal po prostu kawałek "implements ActionListener".

Myślałem, że bez tego nie będzie działało ActionListener w konstruktorze Menu.

Te panele które chcesz żeby się pokazywały, mogłyby być chyba oknami dialogowymi hmm?

Nie mogłyby być. Wkleiłem kod dwóch paneli - WplataKontoPanel oraz NoweKontoSuperKontoPanel. Mają się pokazywać w JFrame pod menu po wybraniu z niego odpowiedniej opcji, a jak wybiorę potem inną opcję z menu to ma znikać i pojawiać się inny. Brzmi prosto tylko za cholerę nie potrafię tego zrobić. Siedzę przed komputerem od południa i nie podsunąłem się do przodu nawet o krok. Nie potrafię zrozumieć jak działają obiekty Container, jakieś getContentPane, zarządcy rozkładu itd. Tworze jakieś nowe, proste projekty żeby to przetestować i za każdym razem efekt jest inny od przewidywanego. Np. stworze 3 Containery. Do pierwszego dodam 2 JButtony i ustawie różowe tło. Do drugiego dodam 2 JButtony i dodam żółte tło. Do trzeciego dodam Container pierwszy i drugi i ustawie niebieskie tło. Jeszcze pokombinuje z zarządcami rozkładu, rozmiarami, lokalizacjami itp., a na końcu i tak będą w jednym rzędzie 4 przyciski na niebieskim tle, albo nie będzie nic. Dla mnie to jest kompletny bezsens to tworzenie GUI w Javie.

0

Najlepiej po prostu uczyć się Javy (w tym tworzenia GUI w Javie) od podstaw, zamiast "skakać na głęboką wodę".

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