本文介绍了从另一个类更新 GUI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 NetBeans 作为 IDE,使用 Swing 用 Ja​​va 构建蛇和梯子游戏.问题是当我编写一个函数来处理另一个类中主类之外的 GUI 的某些方面(例如设置标签图标)时,应用程序运行但必须在该函数中使用该代码发生的更改不会申请.

I am building a Snake and Ladders game in Java with Swing using NetBeans as the IDE. The problem is when i write a function which handles some aspects of the GUI (e.g setting icon of a label) OUTSIDE of the main class in another class, the application runs but the changes that have to happen using that code in that function doesn't apply.

    import javax.swing.JLabel;
    import javax.swing.JOptionPane;

    public class Game extends javax.swing.JFrame
    {
            protected javax.swing.JLabel diceLabel;
            private static final Dice diceObj = new Dice();
            protected int diceNumber;

            private void dicePlayer1ButtonActionPerformed(java.awt.event.ActionEvent evt) {

            diceObj.setDiceIMG(diceNumber);

            }
            public static void main(String args[]){
        java.awt.EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                new Game().setVisible(true);
            }
        });
        }
    }
    class Dice extends Game
    {
            public void setDiceIMG(int dice)
            {
                  if(dice == 1)
                  {
                       diceLabel.setIcon(new javax.swing.ImageIcon("D:\\dice\\dice11.jpg"));
                  }
                  else if(dice == 2)
                  {
                       diceLabel.setIcon(new javax.swing.ImageIcon("D:\\dice\\dice22.jpg"));
                  }

                  else
                  {
                       diceLabel.setIcon(new javax.swing.ImageIcon("D:\\dice\\dice66.jpg"));
                  }
            }

    }

如果我运行此代码,图像将不会设置在标签上,但如果我在 Game 类中创建 setDiceIMG 函数,它就可以完美运行.任何与此相关的信息都会有所帮助.

If i run this code, the image won't be set on the label but if my make the setDiceIMG function inside the Game class, it works perfectly. Any information regarding this would be helpful.

推荐答案

MadProgrammer 评论的基本解决方案或新手方法"是将 diceLabel 的引用指向 Dice 构造函数或 setDiceIMG 方法,如下面的 mre 所示:

The basic solution, or "novice approach" as commented by MadProgrammer is to path a reference of diceLabel to Dice constructor or setDiceIMG method as demonstrated in the following mre:

import java.awt.BorderLayout;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;

public class Game extends JFrame
{
    protected JLabel diceLabel;
    private final Dice diceObj; //should not be static
    protected int diceNumber;

    Game() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);

        diceLabel = new JLabel();
        diceLabel.setHorizontalAlignment(SwingConstants.CENTER);
        JButton changeIcon = new JButton("Change Icon");
        changeIcon.addActionListener(e -> changeLabelIcon());

        diceObj = new Dice(diceLabel); //path a reference of the lable to Dice
        changeLabelIcon();

        add(diceLabel, BorderLayout.NORTH);
        add(changeIcon, BorderLayout.SOUTH);

        pack();
    }

    private void changeLabelIcon() {
        diceNumber = new Random().nextInt(3);
        diceObj.setDiceIMG(diceNumber);
    }

    public static void main(String args[]){
        java.awt.EventQueue.invokeLater(() -> new Game().setVisible(true));
    }
}

class Dice //   no need to extend Game
{
    //use web resources to make code mre
    private static final String[] CIRCLES_64 = {
            "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/64x64/Circle_Green.png",
            "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/64x64/Circle_Red.png",
            "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/64x64/Circle_Yellow.png",
    };
    private final JLabel diceLabel;

    Dice(JLabel diceLabel) {
        this.diceLabel = diceLabel;
    }

    public void setDiceIMG(int dice)
    {
        try {
            if(dice == 1)
            {
                diceLabel.setIcon(new ImageIcon(new URL(CIRCLES_64[0])));
            }
            else if(dice == 2)
            {
                diceLabel.setIcon(new ImageIcon(new URL(CIRCLES_64[1])));
            }
            else
            {
                diceLabel.setIcon(new ImageIcon(new URL(CIRCLES_64[2])));
            }
        } catch (MalformedURLException ex) {
            ex.printStackTrace();
        }
    }
}

引入一个模型可以实现更好的设计,在视图和Dice之间共享:

A better design can be achieved by introducing a model, shared between the view and Dice:

public class Game extends JFrame
{
    protected JLabel diceLabel;
    private final Dice diceObj; //should not be static
    private final DiceModel model;

    Game() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);

        diceLabel = new JLabel();
        diceLabel.setHorizontalAlignment(SwingConstants.CENTER);
        JButton changeIcon = new JButton("Change Icon");
        changeIcon.addActionListener(e -> changeLabelIcon());

        model = new DiceModel(4);
        diceObj = new Dice(model);
        changeLabelIcon();

        add(diceLabel, BorderLayout.NORTH);
        add(changeIcon, BorderLayout.SOUTH);

        pack();
    }

    private void changeLabelIcon() {
        model.rollDice();
        diceLabel.setIcon(new ImageIcon(diceObj.imageURL()));
    }

    public static void main(String args[]){
        java.awt.EventQueue.invokeLater(() -> new Game().setVisible(true));
    }
}

class DiceModel {

    private int diceNumber;
    private final int max;
    private final Random rnd;

    DiceModel(int max) {
        this.max = max;
        rnd = new Random();
        diceNumber = 0;
    }

    void rollDice() {
        diceNumber = rnd.nextInt(max+1);
    }

    int getDiceNumber(){
        return diceNumber;
    }
}

class Dice
{
    //use web resources to make code mre
    private static final String[] CIRCLES_64 = {
            "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/64x64/Circle_Green.png",
            "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/64x64/Circle_Red.png",
            "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/64x64/Circle_Yellow.png",
    };

    private final DiceModel model;

    Dice(DiceModel model) {
        this.model = model;
    }

     URL imageURL()
    {
        try {
            if(model.getDiceNumber() <= CIRCLES_64.length && model.getDiceNumber() > 0)
                return new URL(CIRCLES_64[model.getDiceNumber()-1]);
            else
                return new URL(CIRCLES_64[0]);

        } catch (MalformedURLException ex) {
            ex.printStackTrace();
        }

        return null;
    }
}

下一步改进可能是重构代码以添加控制器以遵循 MVC设计模式:

Next improvement could be refactoring the code to add a controller to follow the MVC design pattern:

import java.awt.BorderLayout;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeListener;

public class Game //acts as game controller
{
    Game() {

        DiceModel model = new DiceModel();
        View view = new View(model);
        view.update();//initialize icon
        model.setListener(e->view.update());//respond to model changes
        view.setVisible(true);
    }

    public static void main(String args[]){
        java.awt.EventQueue.invokeLater(() -> new Game());
    }
}

class View{

    private final JLabel diceLabel;
    private final DiceModel model;
    private final JFrame frame;

    View(DiceModel model) {
        this.model = model;
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);

        diceLabel = new JLabel();
        diceLabel.setHorizontalAlignment(SwingConstants.CENTER);
        JButton changeIcon = new JButton("Roll Dice");
        changeIcon.addActionListener(e -> model.rollDice()); //change model

        frame.add(diceLabel, BorderLayout.NORTH);
        frame.add(changeIcon, BorderLayout.SOUTH);
    }

    void setVisible(boolean visible){
        frame.pack();
        frame.setVisible(visible);
    }

    void update() {
        diceLabel.setIcon(new ImageIcon(model.imageURL()));
    }
}

class DiceModel {

    //use web resources to make code mre
    private static final String[] CIRCLES_64 = {
            "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/64x64/Circle_Green.png",
            "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/64x64/Circle_Red.png",
            "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/64x64/Circle_Yellow.png",
            "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/64x64/Circle_Blue.png",
            "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/64x64/Circle_Orange.png",
            "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/64x64/Circle_Grey.png"
    };

    private int diceNumber;
    private final Random rnd;
    private ChangeListener listener;

    DiceModel() {
        rnd = new Random();
        diceNumber = 0;
    }

    void rollDice() {
        diceNumber = rnd.nextInt(CIRCLES_64.length);
        notifyListener();
    }

    int getDiceNumber(){
        return diceNumber;
    }

    void notifyListener(){
        if(listener != null){
            listener.stateChanged(null);
        }
    }

    void setListener(ChangeListener listener) {
        this.listener = listener;
    }

    URL imageURL()
    {
        try {
            return new URL(CIRCLES_64[diceNumber]);
        } catch (MalformedURLException ex) {
            ex.printStackTrace();
        }
        return null;
    }
}

在线运行.

这篇关于从另一个类更新 GUI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 01:46