简体   繁体   English

一次神秘的铸造异常

[英]Mysterious one time Casting Exception

I am trying to use the PropertyChangeSupport of JComponent class. 我正在尝试使用JComponent类的PropertyChangeSupport。 But when I am executing the following code, Clicking on the menu button first time gives Runtime casting Exception, but then it runs fine always. 但是,当我执行以下代码时,第一次单击菜单按钮会给出Runtime Casting Exception,但随后它总是可以正常运行。

FrameListener.java 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 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);
    }
    */
}

But If i use my own PropertyChangeSupport (remove the comments in FontSource.java), then it's working perfectly. 但是,如果我使用自己的PropertyChangeSupport(删除FontSource.java中的注释),那么它运行良好。 I tried my best, but not getting this. 我尽力了,但没有得到。 Thnx in advance :--) 提前Thnx:-)

If you implement PropertyListener , you will receive all of the property changes for the component(s) with which you register. 如果实现PropertyListener ,您将收到注册时所用组件的所有属性更改。 There can be many types, whose values will be determined by the type of property change. 可以有许多类型,其值将取决于属性更改的类型。

The implementation of Component method of setFont will fire a property change with the name of "font" . setFontComponent方法的实现将触发名为"font"的属性更改。 If you test for that name, you should be fine: 如果测试该名称,则可以:

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);
    }
}

My guess... 我猜...

The property change listening is not distinguishing by property name. 属性更改侦听不能通过属性名称来区分。 Since you are listening to all of the properties of FontSource then you will undoubtedly see things that are not a Font. 由于您正在侦听FontSource的所有属性,因此无疑会看到不是Font的内容。

In propertyChange() you can print the property name in the event to be sure that's the problem. 在propertyChange()中,您可以在事件中打印属性名称,以确保是问题所在。

Solution is to register for just the property in which you are interested or to check the property name in the propertyChange() method. 解决方案是只注册您感兴趣的属性,或者在propertyChange()方法中检查属性名称。

Finally i got it. 终于我明白了。

The answer is displayed, when u compile and execute the following files. 当您编译并执行以下文件时,将显示答案。

FontSource.java 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 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();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM