2009-10-13 77 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(); 
    } 
}