小弟写了一个日历控件(从网上下载后自己修改),有如下问题:
当我把该日历控件放在某一个UI界面上,使用该控件选择了某一个时间之后,如果需要点击同一个界面上的其他类型的Swing控件,必须点击两次才能激活该类型的Swing控件;而如果点击同一类型的另外一个日历控件,则不存在这样的问题
紧急求助!源代码如下:
import java.awt.*;
import java.awt.event.*;
import java.util.Calendar;
import java.text.SimpleDateFormat;
import javax.swing.*;
import javax.swing.event.PopupMenuListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.plaf.ComboBoxUI;
import javax.swing.plaf.basic.ComboPopup;
import javax.swing.plaf.metal.MetalComboBoxUI;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;
import javax.swing.border.EmptyBorder;import com.sun.java.swing.plaf.motif.MotifComboBoxUI;
import com.sun.java.swing.plaf.windows.WindowsComboBoxUI;import javax.swing.JTextField;
import javax.swing.plaf.basic.BasicComboBoxUI;//////////////////////////////////////////////////////////////
public class DateComboBox
    extends JComboBox
{  protected SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");  public DateComboBox()
  {
    this.setEditable(true);
    JTextField textField = ( (JTextField)this.getEditor().getEditorComponent());
    textField.addKeyListener(new KeyAdapter()
    {
      public void keyReleased(KeyEvent e)
      {
        if (e.getKeyCode() == KeyEvent.VK_ENTER)
        {
          textFieldTransferFocus();
        }
      }
    });
    setSelectedItem(dateFormat.format(new java.util.Date()));
  }  public void textFieldTransferFocus()
  {
    ((JTextField)this.getEditor().getEditorComponent()).transferFocusDownCycle();
  }  public void setDateFormat(SimpleDateFormat dateFormat)
  {
    this.dateFormat = dateFormat;
  }  public void setSelectedItem(Object item)
  {
    removeAllItems(); 
    addItem(item);
    super.setSelectedItem(item);
  }  public void updateUI()
  {
    ComboBoxUI cui = (ComboBoxUI) UIManager.getUI(this);
    if (cui instanceof MetalComboBoxUI)
    {
      cui = new MetalDateComboBoxUI();
    }
    else if (cui instanceof MotifComboBoxUI)
    {
      cui = new MotifDateComboBoxUI();
    }
    else if (cui instanceof WindowsComboBoxUI)
    {
      cui = new WindowsDateComboBoxUI();
    }
    //实现水晶风格
    else if (cui instanceof com.birosoft.liquid.LiquidComboBoxUI)
    {
      cui = new LiquidDateComboBoxUI();
    }
    //实现简约风格
    else if (cui instanceof jane.ui.lf.jane.JaneComboBoxUI)
    {
      cui=new JaneComboBoxUI();
    }
    //实现艺术风格
    else if (cui instanceof napkin.NapkinComboBoxUI)
   {
     cui=new NapkinComboBoxUI();
   }
   //swing.addon.plaf.threeD.ThreeDLookAndFeel
   //实现3D风格
   else if (cui instanceof swing.addon.plaf.threeD.ThreeD_ComboBoxUI )
   {
     cui=new ThreeD_ComboBoxUI();
   }
   //实现gtk风格
   else if (cui instanceof org.gtk.java.swing.plaf.gtk.GtkComboBoxUI )
   {
     cui=new GtkComboBoxUI();
   }
   setUI(cui);
  }  // UI Inner classes -- one for each supported Look and Feel
  class MetalDateComboBoxUI
      extends MetalComboBoxUI
  {
    protected ComboPopup createPopup()
    {
      return new DatePopup(comboBox);
    }
  }  class WindowsDateComboBoxUI
      extends WindowsComboBoxUI
  {
    protected ComboPopup createPopup()
    {
      return new DatePopup(comboBox);
    }
  }  class MotifDateComboBoxUI
      extends MotifComboBoxUI
  {
    protected ComboPopup createPopup()
    {
      return new DatePopup(comboBox);
    }
  }  class LiquidDateComboBoxUI
      extends com.birosoft.liquid.LiquidComboBoxUI
  {
    protected ComboPopup createPopup()
    {
      return new DatePopup(comboBox);
    }
}
 class JaneComboBoxUI
   extends  jane.ui.lf.jane.JaneComboBoxUI
  {
    protected ComboPopup createPopup()
    {
      return new DatePopup(comboBox);
    }
}
  class NapkinComboBoxUI
    extends  napkin.NapkinComboBoxUI
   {
     protected ComboPopup createPopup()
     {
       return new DatePopup(comboBox);
     }
 } class ThreeD_ComboBoxUI
   extends  swing.addon.plaf.threeD.ThreeD_ComboBoxUI
  {
    protected ComboPopup createPopup()
    {
      return new DatePopup(comboBox);
    }
}  class GtkComboBoxUI
    extends  org.gtk.java.swing.plaf.gtk.GtkComboBoxUI
   {
     protected ComboPopup createPopup()
     {
       return new DatePopup(comboBox);
     }
 }

解决方案 »

  1.   

    (续上)
    // DatePopup inner class
      class DatePopup
          implements ComboPopup, MouseMotionListener,KeyListener, PopupMenuListener,
          MouseListener
      {    protected JComboBox comboBox;
        protected Calendar calendar;
        protected JPopupMenu popup;
        protected JLabel monthLabel;
        protected JPanel days = null;
        protected SimpleDateFormat monthFormat = new SimpleDateFormat("yyyy-MM");    protected Color selectedBackground;
        protected Color selectedForeground;
        protected Color background;
        protected Color foreground;    public DatePopup(JComboBox comboBox)
        {
          this.comboBox = comboBox;
          calendar = Calendar.getInstance();
          // check Look and Feel
          background = UIManager.getColor("ComboBox.background");
          foreground = UIManager.getColor("ComboBox.foreground");
          selectedBackground = UIManager.getColor(
              "ComboBox.selectionBackground");
          selectedForeground = UIManager.getColor(
              "ComboBox.selectionForeground");      initializePopup();
        }    //========================================
        // begin ComboPopup method implementations
        //
        public void show()
        {
          try
          {
            // if setSelectedItem() was called with a valid date, adjust the calendar
            calendar.setTime(dateFormat.parse(comboBox.getSelectedItem().
                                              toString()));
          }
          catch (Exception e)
          {}
          updatePopup();
          popup.show(comboBox, 0, comboBox.getHeight());
        }    public void hide()
        {
          popup.setVisible(false);
        }    protected JList list = new JList();
        public JList getList()
        {
          return list;
        }    public MouseListener getMouseListener()
        {
          return this;
        }    public MouseMotionListener getMouseMotionListener()
        {
          return this;
        }    public KeyListener getKeyListener()
        {
          return this;
        }    public boolean isVisible()
        {
          return popup.isVisible();
        }    public void uninstallingUI()
        {
          popup.removePopupMenuListener(this);
        }    // end ComboPopup method implementations    // begin Event Listeners
        // MouseListener    public void mousePressed(MouseEvent e)
        {}    public void mouseReleased(MouseEvent e)
        {}    // something else registered for MousePressed
        public void mouseClicked(MouseEvent e)
        {
          /*if (!SwingUtilities.isLeftMouseButton(e))
          {
            return;
          }
          if (!comboBox.isEnabled())
          {
            return;
          }
          if (comboBox.isEditable())
          {
            comboBox.getEditor().getEditorComponent().requestFocus();
            //comboBox.getEditor().getEditorComponent().setFocusTraversalKeysEnabled(false);
          }
          else
          {
            comboBox.requestFocus();
            //comboBox.setFocusTraversalKeysEnabled(false);
          }*/
          togglePopup();
        }
      

  2.   

    (续上)
        protected boolean mouseInside = false;
        public void mouseEntered(MouseEvent e)
        {
          mouseInside = true;
        }    public void mouseExited(MouseEvent e)
        {
          mouseInside = false;
          //comboBox.getParent().getParent().requestFocus();
        }    // MouseMotionListener
        public void mouseDragged(MouseEvent e)
        {}    public void mouseMoved(MouseEvent e)
        {}    // KeyListener
        public void keyPressed(KeyEvent e)
        {}    public void keyTyped(KeyEvent e)
        {}    public void keyReleased(KeyEvent e)
        {
          if (e.getKeyCode() == KeyEvent.VK_SPACE ||
              e.getKeyCode() == KeyEvent.VK_ENTER)
          {
            togglePopup();
          }
        }    /**
         * Variables hideNext and mouseInside are used to
         * hide the popupMenu by clicking the mouse in the JComboBox
         * @param e PopupMenuEvent
         */
        public void popupMenuCanceled(PopupMenuEvent e)
        {}    protected boolean hideNext = false;
        public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
        {
          hideNext = mouseInside;
        }    public void popupMenuWillBecomeVisible(PopupMenuEvent e)
        {}    //
        // end Event Listeners
        //=================================================================    //===================================================================
        // begin Utility methods
        //    protected void togglePopup()
        {
          if (isVisible() || hideNext)
          {
            hide();
          }
          else
          {
            show();
          }
          hideNext = false;
        }    //
        // end Utility methods
        //=================================================================    // Note *** did not use JButton because Popup closes when pressed
        protected JLabel createUpdateButton(final int field, final int amount)
        {
          final JLabel label = new JLabel();
          final Border selectedBorder = new EtchedBorder();
          final Border unselectedBorder = new EmptyBorder(selectedBorder.
              getBorderInsets(new JLabel()));
          label.setBorder(unselectedBorder);
          label.setForeground(foreground);
          label.addMouseListener(new MouseAdapter()
          {
            public void mouseReleased(MouseEvent e)
            {
              calendar.add(field, amount);
              updatePopup();
            }        public void mouseEntered(MouseEvent e)
            {
              label.setBorder(selectedBorder);
            }        public void mouseExited(MouseEvent e)
            {
              label.setBorder(unselectedBorder);
            }
          });
          return label;
        }
      

  3.   

    (续上)
        protected void initializePopup()
        {
          JPanel header = new JPanel(); // used Box, but it wasn't Opaque
          header.setLayout(new BoxLayout(header, BoxLayout.X_AXIS));
          header.setBackground(background);
          header.setOpaque(true);      JLabel label;
          label = createUpdateButton(Calendar.YEAR, -1);
          label.setText("上一年");
          header.add(Box.createHorizontalStrut(12));
          header.add(label);
          header.add(Box.createHorizontalStrut(12));      label = createUpdateButton(Calendar.MONTH, -1);
          label.setText("上个月");
          //label.setToolTipText("上个月");
          //header.add(label);
          header.add(Box.createHorizontalStrut(12));
          header.add(label);
          header.add(Box.createHorizontalStrut(12));     // label.setText("  ");
         // header.add(label);      monthLabel = new JLabel("", JLabel.CENTER);
          monthLabel.setForeground(foreground);
          //header.add(Box.createHorizontalGlue());
          header.add(Box.createHorizontalStrut(12));
          header.add(monthLabel);
          header.add(Box.createHorizontalStrut(12));
          //header.add(Box.createHorizontalGlue());      //label.setText("  ");
          //header.add(label);      label = createUpdateButton(Calendar.MONTH, 1);
          label.setText("下个月");
          //label.setToolTipText("下个月");
          // header.add(label);
          header.add(Box.createHorizontalStrut(12));
          header.add(label);
          header.add(Box.createHorizontalStrut(12));      label = createUpdateButton(Calendar.YEAR, 1);
          label.setText("下一年");
          //label.setToolTipText("下一年");      header.add(Box.createHorizontalStrut(12));
          header.add(label);
          header.add(Box.createHorizontalStrut(12));      popup = new JPopupMenu();
          popup.setBorder(BorderFactory.createLineBorder(Color.black));
          popup.setLayout(new BorderLayout());
          popup.setBackground(background);
          popup.addPopupMenuListener(this);
          popup.add(BorderLayout.NORTH, header);
        }    // update the Popup when either the month or the year of the calendar has been changed
        protected void updatePopup()
        {
          monthLabel.setText(monthFormat.format(calendar.getTime()));
          if (days != null)
          {
            popup.remove(days);
          }
          days = new JPanel(new GridLayout(0, 7));
          days.setBackground(background);
          days.setOpaque(true);      Calendar setupCalendar = (Calendar) calendar.clone();
          setupCalendar.set(Calendar.DAY_OF_WEEK,
                            setupCalendar.getFirstDayOfWeek());
          for (int i = 0; i < 7; i++)
          {
            int dayInt = setupCalendar.get(Calendar.DAY_OF_WEEK);
            final JLabel label = new JLabel();
            label.setHorizontalAlignment(JLabel.CENTER);
            if (dayInt == Calendar.SUNDAY)
            {
              label.setText("日");
              //label.setToolTipText("星期日");
            }
            else if (dayInt == Calendar.MONDAY)
            {
              label.setText("一");
              //label.setToolTipText("星期一");
            }
            else if (dayInt == Calendar.TUESDAY)
            {
              label.setText("二");
              //label.setToolTipText("星期二");
            }
            else if (dayInt == Calendar.WEDNESDAY)
            {
              label.setText("三");
              //label.setToolTipText("星期三");
            }
            else if (dayInt == Calendar.THURSDAY)
            {
              label.setText("四");
              //label.setToolTipText("星期四");
            }
            else if (dayInt == Calendar.FRIDAY)
            {
              label.setText("五");
              //label.setToolTipText("星期五");
            }
            else if (dayInt == Calendar.SATURDAY)
            {
              label.setText("六");
              //label.setToolTipText("星期六");
            }
            days.add(label);
            setupCalendar.roll(Calendar.DAY_OF_WEEK, true);
          }      setupCalendar = (Calendar) calendar.clone();
          setupCalendar.set(Calendar.DAY_OF_MONTH, 1);
          int first = setupCalendar.get(Calendar.DAY_OF_WEEK);
          for (int i = 0; i < (first - 1); i++)
          {
            days.add(new JLabel(""));
          }
          for (int i = 1;
               i <= setupCalendar.getActualMaximum(Calendar.DAY_OF_MONTH); i++)
          {
            final int day = i;
            final JLabel label = new JLabel(String.valueOf(day));
            label.setHorizontalAlignment(JLabel.CENTER);
            label.setForeground(foreground);
            label.addMouseListener(new MouseListener()
            {
              public void mousePressed(MouseEvent e)
              {}          public void mouseClicked(MouseEvent e)
              {}          public void mouseReleased(MouseEvent e)
              {
                label.setOpaque(false);
                label.setBackground(background);
                label.setForeground(foreground);
                calendar.set(Calendar.DAY_OF_MONTH, day);
                comboBox.setSelectedItem(dateFormat.format(calendar.
                    getTime()));
                hide();
                // hide is called with setSelectedItem() ... removeAll()
                //comboBox.requestFocus();
                //comboBox.getParent().getParent().requestFocus();
               }          public void mouseEntered(MouseEvent e)
              {
                label.setOpaque(true);
                label.setBackground(selectedBackground);
                label.setForeground(selectedForeground);
              }          public void mouseExited(MouseEvent e)
              {
                label.setOpaque(false);
                label.setBackground(background);
                label.setForeground(foreground);
              }
            });        days.add(label);
          }
          popup.add(BorderLayout.CENTER, days);
          popup.pack();
        }
      }
    }
      

  4.   

    ...
    popup.setBackground(background);
    popup.addPopupMenuListener(this);
    popup.add(BorderLayout.NORTH, header);popup.setFocusable(false);   //加上这一行...
      

  5.   

    gtlang78()的做法不行啊,还有哪位大哥有办法????????
      

  6.   

    是不是需要设置一下FocusTraversalPolicy????
    偶不知道怎么用FocusTraversalPolicy这个类,哪位大哥能不能给各例子!
    多谢!
      

  7.   

    已调通你的代码,正在研究,,
    下面这些类com.birosoft.liquid.LiquidComboBoxUI
    jane.ui.lf.jane.JaneComboBoxUI..从哪得到的?Thx!
      

  8.   

    我将这个类用于我的软件系统,发现并没有出现你所说的问题!焦点等问题一切正常!我的JDK为1.4.2。另外由于我想使用这个控件,没有LiquidComboBoxUI等类界面会显得比较难看,因此如果你那有的话,请给我一份,我的mail:[email protected],Thx!