簡體   English   中英

在 JPanel 加載時單擊 JButton 時,JLabel 不可見

[英]JLabel is not visible when JButton is clicked whilst JPanel is loading

當我單擊主面板上的背景選擇器時,加載 JPanel 需要一段時間,我想在加載背景選擇器面板時顯示加載 JLabel,然后在面板最終顯示時消失。 我試圖在我的按鈕動作監聽器中實現這一點。 但是由於某種原因,當我從動作偵聽器中刪除 backgroundPanel() 方法時(單擊 JButton 時未加載面板,而是僅顯示 JLabel),單擊按鈕時會顯示 label,但通常會顯示 label沒有出現。 我不明白為什么。

Window class:

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.io.IOException;

/**
 *
 */
public class Window {

public static JFrame frame;
GameWindow game;
BackgroundSelector background;
static DifficultySelector difficulty;
public static MainBackgroundImage main; // start window
JProgressBar progressBar = new JProgressBar();
private boolean loaded = false;

public Window() throws IOException {

    frame = new JFrame("Brick Builder Game"); // creates JFrame

    game = new GameWindow(); // creates new GAME window
    main = new MainBackgroundImage(); // creates MAIN screen
    background = new BackgroundSelector(); // creates BACKGROUND SELECTOR window
    difficulty = new DifficultySelector(); // creates DIFFICULTY SELECTOR window

    main.setLayout(null);

    frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
    frame.setSize(500,500);
    frame.setVisible(true);
    frame.setResizable(false);

    frame.getContentPane().add(main); // adds MAIN screen to frame


    JButton start = new JButton();
    Image startImg = ImageIO.read(getClass().getResource("start.png"));
    start.setIcon(new ImageIcon(startImg));
    start.setBounds(150,270,200,40);
    start.setOpaque(false);
    start.setBorderPainted(false);

    JButton backgroundSelector = new JButton();
    Image selectorImg = ImageIO.read(getClass().getResource("selector.png"));
    backgroundSelector.setIcon(new ImageIcon(selectorImg));
    backgroundSelector.setBounds(150, 320,200,40);
    backgroundSelector.setOpaque(false);
    backgroundSelector.setBorderPainted(false);


    JButton quit = new JButton();
    Image quitImg = ImageIO.read(getClass().getResource("quit.png"));
    quit.setIcon(new ImageIcon(quitImg));
    quit.setBounds(150,370,200,40);
    quit.setOpaque(false);
    quit.setBorderPainted(false);

    JLabel loading = new JLabel();
    loading.setBounds(150,400,100,20);

    main.repaint();

    start.setBackground(Color.white);
    backgroundSelector.setBackground(Color.white);
    quit.setBackground(Color.white);

    start.setFocusable(false);
    quit.setFocusable(false);
    backgroundSelector.setFocusable(false);
    start.setAlignmentX(Component.CENTER_ALIGNMENT);
    quit.setAlignmentX(Component.CENTER_ALIGNMENT);
    backgroundSelector.setAlignmentX(Component.CENTER_ALIGNMENT);
    
    main.add(start); // adds JButton
    main.add(quit);
    main.add(backgroundSelector);
    main.add(loading);
    main.add(progressBar);

    start.addActionListener(e -> difficultyPanel());

    quit.addActionListener(e -> {
        frame.dispose();
    });

    backgroundSelector.addActionListener(e -> {
        loading.setText("Loading...");
        backgroundPanel();
    });

    //backgroundSelector.addActionListener(e -> backgroundPanel());
}

public static void mainPanel(){
    frame.getContentPane().removeAll();
    frame.getContentPane().add(main);
    frame.validate();
}

public void backgroundPanel(){
    //loaded = false;
    frame.getContentPane().removeAll();
    background = new BackgroundSelector();
    frame.getContentPane().add(background);
    frame.revalidate();
}

public void difficultyPanel(){
    frame.getContentPane().removeAll();
    difficulty = new DifficultySelector();
    frame.getContentPane().add(difficulty);
    frame.requestFocusInWindow();
    frame.revalidate();
}

    public static void main (String[]args) throws IOException {
        new Window();
    }
}

背景選擇器 class:

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

/**
 * This class creates the background selector JPanel which allows the player to choose a background
 * of their choice. A choice of 6 backgrounds is given to the player to choose from.
 *
 */
public class BackgroundSelector extends JPanel{

    DifficultySelector difficulty = new DifficultySelector();

    private final ClassLoader cl = Thread.currentThread().getContextClassLoader();
    private final Image image = Toolkit.getDefaultToolkit().getImage(cl.getResource("black.jpg"));

    JLabel label;

    // creates the radioButtons which display the backgrounds to choose from
    JRadioButton radioButton;
    JRadioButton radioButton2;
    JRadioButton radioButton3;
    JRadioButton radioButton4;
    JRadioButton radioButton5;
    JRadioButton radioButton6;

    public static boolean option1 = false;
    public static boolean option2 = false;
    public static boolean option3 = false;
    public static boolean option4 = false;
    public static boolean option5 = false;
    public static boolean option6 = false;

    /**
 * Constructor which adds the radio buttons to a button group and displays them on the JPanel using a flow layout.
 *
 */
public BackgroundSelector(){

    label = new JLabel("Please select a background", JLabel.CENTER);
    label.setFont(new Font("Verdana", Font.BOLD, 18));
    label.setForeground(Color.white);

    setLayout(new FlowLayout());
    ButtonGroup group = new ButtonGroup();
    group.add(radioButton);
    group.add(radioButton2);
    group.add(radioButton3);
    group.add(radioButton4);
    group.add(radioButton5);
    group.add(radioButton6);

    option1();
    option2();
    option3();
    option4();
    option5();
    option6();
    add(label);
}


/**
 * Paints background image of panel to black chalk image.
 * @param g
 */
@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    image.getScaledInstance(500, 500,Image.SCALE_SMOOTH);
    while(!prepareImage(image, this)) {
        prepareImage(image, this);
    }
    g.drawImage(image,0,0,null);
}

/**
 * Converts the url to an image which will be used as the icon for the JRadioButton.
 *
 * @param url The url of the image.
 * @return The image with a specific height and width.
 */
public String URL(String url){
    return "<html><body><img src='" + url + "'width=128 height=128>";
}

/**
 * Adds radioButton to the JPanel, when clicked, creates a new game with the space background.
 *
 */
public void option1() {
    String url = URL("https://www.nasa.gov/sites/default/files/styles/full_width/public/thumbnails/image/main_image_star-forming_region_carina_nircam_final-1280.jpg");
    radioButton = new JRadioButton(url);
    add(radioButton);
    radioButton.addActionListener(e -> {
        Window.frame.getContentPane().removeAll();
        //game.changeFilepath("space.jpg");
        Window.frame.getContentPane().add(difficulty);
        Window.frame.requestFocusInWindow();
        Window.frame.revalidate();
        option1 = true;
    });
}

/**
 * Adds radioButton to the JPanel, when clicked, creates a new game with the bricks background.
 *
 */
public void option2(){
    String url = URL("https://appgrooves.com/cdn/mc/GAME_ARCADE/7_w1200.jpg");
    radioButton2 = new JRadioButton(url);
    add(radioButton2);
    radioButton2.addActionListener(e -> {
        Window.frame.getContentPane().removeAll();
        //game.changeFilepath("space.jpg");
        Window.frame.getContentPane().add(difficulty);
        Window.frame.requestFocusInWindow();
        Window.frame.revalidate();
        option2 = true;
    });
}

/**
 * Adds radioButton to the JPanel, when clicked, creates a new game with the stars background.
 *
 */
public void option3(){
    String url = URL("https://upload.wikimedia.org/wikipedia/commons/2/26/Oldest_star_in_solar_neighbourhood.jpg");
    radioButton3 = new JRadioButton(url);
    add(radioButton3);
    radioButton3.addActionListener(e -> {
        Window.frame.getContentPane().removeAll();
        //game.changeFilepath("stars.jpg");
        Window.frame.getContentPane().add(difficulty);
        Window.frame.requestFocusInWindow();
        Window.frame.revalidate();
        option3 = true;
    });
}

/**
 * Adds radioButton to the JPanel, when clicked, creates a new game with the bubbles background.
 *
 */
public void option4(){
    String url = URL("https://cdn.pocket-lint.com/assets/images/131835-phones-news-feature-cropped-best-iphone-wallpapers-image72-7pqcs1gy9h.jpg");
    radioButton4 = new JRadioButton(url);
    add(radioButton4);
    radioButton4.addActionListener(e -> {
        Window.frame.getContentPane().removeAll();
        //game.changeFilepath("stars.jpg");
        Window.frame.getContentPane().add(difficulty);
        Window.frame.requestFocusInWindow();
        Window.frame.revalidate();
        option4 = true;
    });
}

/**
 * Adds radioButton to the JPanel, when clicked, creates a new game with the forest background.
 *
 */
public void option5(){
    String url = URL("https://images.hdqwalls.com/download/blue-forest-minimal-4k-kz-2048x2048.jpg");
    radioButton5 = new JRadioButton(url);
    add(radioButton5);
    radioButton5.addActionListener(e -> {
        Window.frame.getContentPane().removeAll();
        //game.changeFilepath("stars.jpg");
        Window.frame.getContentPane().add(difficulty);
        Window.frame.requestFocusInWindow();
        Window.frame.revalidate();
        option5 = true;
    });
}

/**
 * Adds radioButton to the JPanel, when clicked, creates a new game with the japanese purple background.
 *
 */
public void option6(){
    String url = URL("https://www.pixelstalk.net/wp-content/uploads/images5/Cool-Japanese-Backgrounds-HD-Free-download.jpg");
    radioButton6 = new JRadioButton(url);
    add(radioButton6);
    radioButton6.addActionListener(e -> {
        Window.frame.getContentPane().removeAll();
        //game.changeFilepath("stars.jpg");
        Window.frame.getContentPane().add(difficulty);
        Window.frame.requestFocusInWindow();
        Window.frame.revalidate();
        option6 = true;
    });
}

}

無法運行代碼會導致一些假設。

根據您的描述,我會說您在加載圖像時阻塞了事件調度線程,這將阻止 UI 更新。

有關詳細信息,請參閱Swing中的並發。 我建議使用SwingWorker來實際加載圖像。

您還應該使用布局管理器,您會發現CardLayout對於在組件之間切換特別有用。

例如...

在此處輸入圖像描述

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.border.EmptyBorder;

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    JFrame frame = new JFrame();
                    frame.add(new MainPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }

    public class MainPane extends JPanel {

        public interface Observer {
            public void start();
            public void quit();
            public void didLoadBackground(BufferedImage img);
        }

        enum View {
            MAIN, START
        }

        private BufferedImage background;
        private CardLayout cardLayout;

        public MainPane() throws IOException {
            cardLayout = new CardLayout();
            setLayout(cardLayout);
            background = ImageIO.read(getClass().getResource("/images/Mando01.jpeg"));
            add(new OptionsPane(new Observer() {
                @Override
                public void start() {
                    show(View.START);
                }

                @Override
                public void quit() {
                    SwingUtilities.windowForComponent(MainPane.this).dispose();
                }

                @Override
                public void didLoadBackground(BufferedImage img) {
                    JOptionPane.showMessageDialog(MainPane.this, "You have a pretty picture", "Notice", JOptionPane.INFORMATION_MESSAGE);
                }
            }), View.MAIN);

            add(new GamePane(), View.START);
        }       

        public void add(Component component, View view) {
            add(component, view.name());
        }

        public void show(View view) {
            cardLayout.show(this, view.name());
        }

        @Override
        public Dimension getPreferredSize() {
            if (background != null) {
                return new Dimension(background.getWidth(), background.getHeight());
            }
            return super.getPreferredSize();
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (background == null) {
                return;
            }
            int x = (getWidth() - background.getWidth()) / 2;
            int y = (getHeight() - background.getHeight()) / 2;
            g.drawImage(background, x, y, this);
        }
    }

    public class OptionsPane extends JPanel {
        private MainPane.Observer observer;
        public OptionsPane(MainPane.Observer observer) {
            setOpaque(false);
            setLayout(new GridBagLayout());
            JButton start = new JButton("Start");
            start.setOpaque(false);
            start.setBorderPainted(false);
            start.setForeground(Color.WHITE);

            JButton backgroundSelector = new JButton("Background");
            backgroundSelector.setOpaque(false);
            backgroundSelector.setBorderPainted(false);
            backgroundSelector.setForeground(Color.WHITE);

            JButton quit = new JButton("Quit");
            quit.setOpaque(false);
            quit.setBorderPainted(false);
            quit.setForeground(Color.WHITE);

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weighty = 1;
            gbc.anchor = GridBagConstraints.SOUTH;
            gbc.insets = new Insets(4, 4, 4, 4);

            add(start, gbc); // adds JButton
            gbc.weighty = 0;
            gbc.gridy++;
            add(backgroundSelector, gbc);
            gbc.gridy++;
            add(quit, gbc);

            start.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    observer.start();
                }
            });

            quit.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    observer.quit();
                }
            });

            backgroundSelector.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    // This "could" use the glassPane, but that's
                    // an additional complexity
                    JPanel panel = new JPanel(new GridBagLayout());
                    JLabel label = new JLabel("Loading...");
                    label.setHorizontalAlignment(JLabel.CENTER);
                    JProgressBar progressBar = new JProgressBar(0, 100);

                    GridBagConstraints gbc = new GridBagConstraints();
                    gbc.gridx = GridBagConstraints.REMAINDER;
                    gbc.insets = new Insets(2, 2, 2, 2);
                    gbc.fill = gbc.HORIZONTAL;

                    panel.setBorder(new EmptyBorder(8, 8, 8, 8));
                    panel.add(label, gbc);
                    panel.add(progressBar, gbc);

                    gbc = new GridBagConstraints();
                    gbc.gridx = 0;
                    gbc.gridy = 0;
                    gbc.gridwidth = gbc.REMAINDER;
                    gbc.gridheight = gbc.REMAINDER;

                    add(panel, gbc);

                    revalidate();
                    repaint();

                    SwingWorker<BufferedImage, Void> worker = new SwingWorker<BufferedImage, Void>() {
                        @Override
                        protected BufferedImage doInBackground() throws Exception {
                            for (int progress = 0; progress <= 100; progress++) {
                                Thread.sleep(50);
                                setProgress(progress);
                            }
                            return null;
                        }
                    };
                    worker.addPropertyChangeListener(new PropertyChangeListener() {
                        @Override
                        public void propertyChange(PropertyChangeEvent evt) {
                            String name = evt.getPropertyName();
                            if (worker.getState() == SwingWorker.StateValue.DONE) {
                                remove(panel);
                                revalidate();
                                repaint();
                                try {
                                    observer.didLoadBackground(worker.get());
                                } catch (InterruptedException | ExecutionException ex) {
                                    ex.printStackTrace();
                                    JOptionPane.showMessageDialog(OptionsPane.this, "Failed to load image", "Error", JOptionPane.ERROR_MESSAGE);
                                }
                            } else if ("progress".equalsIgnoreCase(name)) {
                                progressBar.setValue((int)evt.getNewValue());
                            }
                        }

                    });
                    worker.execute();
                }
            });
        }
    }

    public class GamePane extends JPanel {
        public GamePane() {
            setOpaque(false);
            setLayout(new GridBagLayout());
            add(new JLabel("Let's get this party started"));
        }        
    }
}

現在,如果您在加載圖像時需要進度反饋,這是一個更復雜的解決方案,有關更多詳細信息,請參閱Using JProgressBar while convert image to byte array

只需將以下方法添加到背景選擇器:) 並在 window 中的 background() 方法上調用它

public void resetLayout() {
    radioButton.setSelected(false);
    radioButton2.setSelected(false);
    radioButton3.setSelected(false);
    radioButton4.setSelected(false);
    radioButton5.setSelected(false);
    radioButton6.setSelected(false);
}

真的很丑,可能會更好,但有效!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM