2009-10-13 73 views
0

我想使用JComponent类的PropertyChangeSupport。 但是,当我执行下面的代码时,第一次点击菜单按钮会给出运行时抛出异常,但它总是运行良好。神秘的一次铸造异常

FrameListener.java

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

public class FrameListener extends JFrame implements ActionListener, PropertyChangeListener 
{ 

    JLabel lblMessage; 
    JMenuItem changeFont; 
    FontSource fe = new FontSource(this,"Font Editor"); 

    public FrameListener(){ 

     super("Hello World"); 
     setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE) ; 
     increaseReadability() ; 

     changeFont.addActionListener(this); 

     fe.addPropertyChangeListener(this); 

     setSize(400,200); 
     setVisible(true); 
    } 

    private void increaseReadability(){ 
     JPanel panel = new JPanel(); 
     Font f = new Font("Times New Roman",Font.BOLD,24); 
     lblMessage = new JLabel("HELLO WORLD",SwingConstants.CENTER); 
     lblMessage.setFont(f); 
     panel.add(lblMessage); 


     JMenuBar actionBar = new JMenuBar();  
     JMenu edit = new JMenu("Edit"); 
     changeFont = new JMenuItem("Font"); 

     actionBar.add(edit); 
     edit.add(changeFont); 
     add(actionBar,BorderLayout.NORTH); 
     add(panel,BorderLayout.CENTER); 
    } 

    public void propertyChange(PropertyChangeEvent pcevent){ 
     Object obj = pcevent.getNewValue() ; 
     System.out.println(obj.getClass()) ; 

     //Statement occuring problem 1st time 
     Font newFt = (Font)obj; 

     lblMessage.setFont(newFt); 
    } 

    public void actionPerformed(ActionEvent evt){ 
     fe.setVisible(true); 
    } 

    public static void main(String argv[]) { 
     new FrameListener(); 
    } 
} 

FontSource.java

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


public class FontSource extends JDialog implements ActionListener { 

    private Font newFont = new Font("Times New Roman",Font.BOLD,12); 

    JComboBox cbfType,cbfStyle,cbfSize; 
    JButton btnOk,btnCancel; 

    //protected PropertyChangeSupport changes = new PropertyChangeSupport(this); 

    public Font getNewFont(){ 
     return newFont; 
    } 

    public void setNewFont(Font f){ 
     Font old = newFont; 

     try{ 

      //this statement calls the propertyChange() of FrameListener 
         //if u are removing comments, replace the following statement with 
         // changes.firePropertyChange("Font Changed",old,f); 
      firePropertyChange("Font Changed",old,f); 

      newFont = f; 
     } 
     catch(Exception e){ 
      System.out.println(e); 
     } 
    } 

    public FontSource(Frame fr,String title){ 

     super(fr,title); 
     // getting font family from the graphics environment. 
     GraphicsEnvironment gf = GraphicsEnvironment.getLocalGraphicsEnvironment(); 
     String myfont[] = gf.getAvailableFontFamilyNames(); 
     cbfType = new JComboBox(myfont); 
     add(cbfType); 

     String fontStyle[] = {"PLAIN","ITALIC","BOLD",}; 
     cbfStyle = new JComboBox(fontStyle); 
     add(cbfStyle); 

     String fontSize[] = {"10","12","14","16","18","20","24","26","28","36","48","72"}; 
     cbfSize = new JComboBox(fontSize); 
     add(cbfSize); 

     btnOk =new JButton("OK"); 
     btnCancel =new JButton("Cancel"); 

     add(btnOk); 
     add(btnCancel); 

     // adding action listener 
     btnOk.addActionListener(this); 
     btnCancel.addActionListener(this); 

     // setting layout and size for the dialog 
     setLayout(new FlowLayout()); 
     setSize(170,170); 
    } 

    public void actionPerformed(ActionEvent ae){ 

     if(ae.getSource()==btnOk){ 
      String type = (String) cbfType.getSelectedItem(); 
      String style = (String)cbfStyle.getSelectedItem(); 
      int s = 0; 
      int size = Integer.parseInt((String)cbfSize.getSelectedItem()); 
      if(style=="PLAIN") 
       s= Font.PLAIN; 
      else { 
       if(style =="BOLD") 
        s= Font.BOLD; 
       else 
        s= Font.ITALIC; 
      } 

      Font f = new Font(type,s,size); 

      setNewFont(f); 
     } 
     else{ 
      this.setVisible(false); 
     } 
    } 

    /* 
    public void addPropertyChangeListener(PropertyChangeListener l){ 
     System.out.println("attachement done..."); 
     changes.addPropertyChangeListener(l); 
    } 

    public void removePropertyChangeListener(PropertyChangeListener l){ 
     changes.removePropertyChangeListener(l); 
    } 
    */ 
} 

,但如果我用我自己的PropertyChangeSupport(除去FontSource.java的评论),那么它的正常使用。 我尽我所能,但没有得到这个。 日Thnx提前: - )

+3

的异常堆栈跟踪将是有益的 – skaffman 2009-10-13 19:59:41

+0

你为什么不只是采取什么pcevent.getNewValue偷看( )第一次回来?这肯定会告诉你为什么会发生异常。 – 2009-10-13 20:20:07

+0

它首次返回java.awt.SystemColor? – mogli 2009-10-13 20:31:19

回答

3

如果您实施PropertyListener,您将收到您注册的组件的所有属性更改。可以有多种类型,其值将由财产变化的类型决定。

setFontComponent方法的实现将火与"font"名称的属性更改。如果你测试这个名字,你应该没问题:

public void propertyChange(PropertyChangeEvent pcevent){ 
    Object obj = pcevent.getNewValue() ; 
    System.out.println(obj.getClass()) ; 

    //Problem should not occur with this call. 
    if (pcevent.getPropertyName().equals("font")){ 
     Font newFt = (Font)obj; 

     lblMessage.setFont(newFt); 
    } 
} 
1

我的猜测......

属性更改收听不受属性名称区分。由于您正在聆听FontSource的所有属性,因此您无疑会看到不是Font的东西。

在propertyChange()中,您可以在事件中打印属性名称以确保问题存在。

解决方案是只注册您感兴趣的属性或检查propertyChange()方法中的属性名称。

0

最后我明白了。

答案显示,当u编译和执行下列文件。

FontSource.java

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


public class FontSource extends JDialog{ 

    public FontSource(Frame fr,String title){ 

     super(fr,title); 
     setSize(600, 400) ; 
     JTextArea area = new JTextArea() ; 
     area.setEditable(false) ; 
     add(new JScrollPane(area)) ; 

     String str = "If u look at the command prompt, then it is very clear," + "\n" + 
        "that, only on your first click on JMenuItem (font)," + "\n" + 
        "u get an output on cmd, for next future clicks on JMenuItem (font), u get no output on cmd." + "\n\n" + 
        "Reason : On first click, ActionListener attached to JMenuItem (font) invokes," + "\n" + 
        "fe.setVisible(true), which internally calls setBackground method of Component class only once." + "\n" + 
        "Now, setBackground method calls firePropertyChange(\"background\", oldValue, newValue)," + "\n" + 
        "which in turn also gets executed once." + "\n\n" + 
        "Now, solution to this is clearly mentioned in the reply" + "\n" + 
        "provided by akf for my question asked on stackoverflow. cheers :-)" ; 

     area.setText(str) ; 
    }  
} 

FrameListener.java

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

public class FrameListener extends JFrame implements ActionListener, PropertyChangeListener 
{ 

    JLabel lblMessage; 
    JMenuItem changeFont; 
    FontSource fe = new FontSource(this,"Font Editor"); 

    public FrameListener(){ 

     super("Hello World"); 
     setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE) ; 
     increaseReadability() ; 

     changeFont.addActionListener(this); 

     fe.addPropertyChangeListener(this); 

     setSize(400,200); 
     setVisible(true); 
    } 

    private void increaseReadability(){ 
     JMenuBar actionBar = new JMenuBar();  
     JMenu edit = new JMenu("Edit"); 
     changeFont = new JMenuItem("Font"); 
     actionBar.add(edit); 
     edit.add(changeFont); 
     add(actionBar,BorderLayout.NORTH); 
    } 

    public void propertyChange(PropertyChangeEvent pcevent){ 
     Object obj = pcevent.getNewValue() ; 
     System.out.println(obj.getClass() + ", " + pcevent.getPropertyName()) ; 
    } 

    public void actionPerformed(ActionEvent evt){ 
     fe.setVisible(true); 
    } 

    public static void main(String argv[]) { 
     new FrameListener(); 
    } 
}