![](/img/trans.png)
[英]Set JLabel Visible when JButton is clicked in actionPerformed
[英]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.