这是《JAVA2核心编程》第8章的例题8-2,程序1和程序2都没有编译错误,也能运行,但是程序1运行结果的窗口面板无法实现面板切换,而程序2却可以正常切换,本人是新手,怀疑是不是对象引用问题,但实在找不出问题在哪里,还请高手赐教!不胜感激!程序1:(无法实现面板切换)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;public class PlatTest
{
public static void main(String[] args)
{
PlatFrame frame = new PlatFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}class PlatFrame extends JFrame
{
public PlatFrame()
{
Toolkit kit = Toolkit.getDefaultToolkit();
Dimension screenSize = kit.getScreenSize();
int screenWidth = screenSize.width;
int screenHeight = screenSize.height;
setBounds(screenWidth / 4, screenHeight / 4, screenWidth / 2, screenHeight / 2);
setTitle("PlatTest");
Image img = kit.getImage("icon.gif");
setIconImage(img);

PlatPanel panel = new PlatPanel();
add(panel);
}
}class PlatPanel extends JPanel
{
public PlatPanel()
{
String metalPlaf = "javax.swing.plaf.metal.MetalLookAndFeel";
String motifPlaf = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
String windowsPlaf = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";

makeButton("Metal", metalPlaf);
makeButton("CDE/Motif", motifPlaf);
makeButton("GTK+", windowsPlaf);
}

public void makeButton(String n, String plaf)
{
JButton button = new JButton(n);
add(button);
PlatAction action = new PlatAction(plaf);
button.addActionListener(action);
}

public class PlatAction implements ActionListener
{
public PlatAction(String name)
{
plafName = name;
}
public void actionPerformed(ActionEvent event)
{
try
{
UIManager.setLookAndFeel(plafName);
SwingUtilities.updateComponentTreeUI(PlatPanel.this);
}
catch (Exception e) {e.printStackTrace();}
}
}
private String plafName;
}程序2:(可以实现预期效果)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;public class PlatTest1
{
public static void main(String[] args)
{
PlatFrame frame = new PlatFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}class PlatFrame extends JFrame
{
public PlatFrame()
{
Toolkit kit = Toolkit.getDefaultToolkit();
Dimension screenSize = kit.getScreenSize();
int screenWidth = screenSize.width;
int screenHeight = screenSize.height;
setBounds(screenWidth / 4, screenHeight / 4, screenWidth / 2, screenHeight / 2);
setTitle("PlatTest");
Image img = kit.getImage("icon.gif");
setIconImage(img);

PlatPanel panel = new PlatPanel();
add(panel);
}
}class PlatPanel extends JPanel
{
public PlatPanel()
{
String metalPlaf = "javax.swing.plaf.metal.MetalLookAndFeel";
String motifPlaf = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
String windowsPlaf = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";

makeButton("Metal", metalPlaf);
makeButton("CDE/Motif", motifPlaf);
makeButton("GTK+", windowsPlaf);
}

public void makeButton(String n, final String plafName)
{
JButton button = new JButton(n);
add(button);
button.addActionListener(new
ActionListener()
{
public void actionPerformed(ActionEvent event)
{
try
{
UIManager.setLookAndFeel(plafName);
SwingUtilities.updateComponentTreeUI(PlatPanel.this);
}
catch(Exception e) {e.printStackTrace();}
}
});
}
}

解决方案 »

  1.   

    看代码没问题,我这里运行正常!
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;public class Test {
      public static void main(String[] args) {
        PlatFrame frame = new PlatFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
      }
    }class PlatFrame extends JFrame {
      public PlatFrame() {
        Toolkit kit = Toolkit.getDefaultToolkit();
        Dimension screenSize = kit.getScreenSize();
        int screenWidth = screenSize.width;
        int screenHeight = screenSize.height;
        setBounds(screenWidth / 4, screenHeight / 4, screenWidth / 2, screenHeight / 2);
        setTitle("PlatTest");
        Image img = kit.getImage("icon.gif");
        setIconImage(img);
        PlatPanel panel = new PlatPanel();
        add(panel);
      }
    }class PlatPanel extends JPanel {
      public PlatPanel() {
        String metalPlaf = "javax.swing.plaf.metal.MetalLookAndFeel";
        String motifPlaf = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
        String windowsPlaf = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
        makeButton("Metal", metalPlaf);
        makeButton("CDE/Motif", motifPlaf);
        makeButton("GTK+", windowsPlaf);
      }  public void makeButton(String n, final String plafName) {
        JButton button = new JButton(n);
        add(button);
        button.addActionListener(new ActionListener() {
          public void actionPerformed(ActionEvent event) {
            try {
              UIManager.setLookAndFeel(plafName);
              SwingUtilities.updateComponentTreeUI(PlatPanel.this);
            } catch (Exception e) {
              e.printStackTrace();
            }
          }
        });
      }
    }
      

  2.   

    今天中午调试了一下,把程序1中变量plafName(private String plafName;)放到内部类PlatAction中,就能够得到预期效果了,即面板的切换。但是我却不是很明白为什么
    问题:
        内部类不是可以调用外围类的实例域吗?
    是不是在运行的时候,当程序运行到内部类时它调用了外围类的变量后在运行结束时会释放掉,而没有将正确结果返回??是这样子吗?
      

  3.   

    private String plafName;
    plafName应该是PlatAction的属性,你定义成了PlatPanel的属性
    定义的三个PlatAction都共用这个属性,plafName为最后定义的windowsPlaf的值,所以只实现了一种外观 public class PlatAction implements ActionListener
        {
            private String plafName;//放到类PlatAction 中
            public PlatAction(String name)
            {
                plafName = name;
            }
            public void actionPerformed(ActionEvent event)
            {
                try
                {
                    UIManager.setLookAndFeel(plafName);
                    SwingUtilities.updateComponentTreeUI(PlatPanel.this);
                }
                catch (Exception e) {e.printStackTrace();}
            }
        }   
      

  4.   

    你new了3个 PlatAction的对象,这3个对象调用的外部类的属性plafName是同一个
    makeButton("Metal", metalPlaf);
    外部类plafName的值为metalPlaf
    makeButton("CDE/Motif", motifPlaf);
    外部类plafName的值被改为motifPlaf
    makeButton("GTK+", windowsPlaf);
    外部类plafName的值被改为windowsPlaf所以最后plafName的值是windowsPlaf对应得值"com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
    所以点击按钮看到的都是"com.sun.java.swing.plaf.windows.WindowsLookAndFeel";得外观
      

  5.   


    System.out.println(plafName);   //取得都是com.sun.java.swing.plaf.windows.WindowsLookAndFeel 因为,plafName是全局的变量,PlatAction的构造函数里platName都是同一个变量
    UIManager.setLookAndFeel(plafName);