Таинственное одноразовое исключение на кастинг - PullRequest
0 голосов
/ 13 октября 2009

Я пытаюсь использовать PropertyChangeSupport класса JComponent. Но когда я выполняю следующий код, первое нажатие на кнопку меню дает исключение при кастинге во время выполнения, но затем оно всегда работает нормально.

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), то он работает отлично. Я старался изо всех сил, но не получая это. Спасибо заранее: -)

Ответы [ 3 ]

3 голосов
/ 14 октября 2009

Если вы внедрите PropertyListener, вы получите все изменения свойств для компонента (ов), с которым вы регистрируетесь. Может быть много типов, значения которых будут определяться типом изменения свойства.

Реализация Component метода setFont вызовет изменение свойства с именем "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 голос
/ 14 октября 2009

Мое предположение ...

Прослушивание изменения свойства не отличается по имени свойства. Поскольку вы слушаете все свойства FontSource, вы, несомненно, увидите вещи, которые не являются шрифтами.

В propertyChange () вы можете напечатать имя свойства в событии, чтобы убедиться, что это проблема.

Решение состоит в том, чтобы зарегистрировать только то свойство, которое вас интересует, или проверить имя свойства в методе propertyChange ().

0 голосов
/ 15 октября 2009

Наконец я понял.

Ответ отображается, когда вы компилируете и выполняете следующие файлы.

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();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...