有关输入焦点与光标不同步的问题?(如果您对JAVA SWING感兴趣) (100分)

  • 主题发起人 主题发起人 zhuny
  • 开始时间 开始时间
Z

zhuny

Unregistered / Unconfirmed
GUEST, unregistred user!
本人封装了一个日期时间编辑和显示格式的TextField(extends JTextField)!
并实现foucusListener接口,在lostFocus方法中对编辑结果做有效性校验,不合法 弹出Dialog提示,通过requestFocus返回焦点进行修改。
系统环境:WIN2K FAMILY SERVER,jdk1.3.0_02 or JB5
测试情况:输入日期后(输入的为非法日期),通过鼠标点击下一控件转移焦点,
如果通过鼠标转移焦点到其他非JTable控件,弹出错误提示DIALOG,确认后焦点返回原输入框。
如果鼠标点击对象为JTable中的某个CELL,弹出错误提示DIALOG,确认后,令人痛心的情况发
生:输入焦点在JTable中,而光标却在日期编辑框中闪烁,而且你再想将输入焦点放入编
辑框已经不可能。
听说焦点问题是SWING 的要害~
有哪位在相关问题上有一个very good solution
有哪位对JTable封装有好的主意,不要建议我用JB 的 jBdbTable哟~
听说在jdk1.4提供了java.awt.KeyboardFocusManager,AWT 被赋予一种全新的焦点模型。
我正准备试试。
[?][?]
 
虽然我对于Swing很感兴趣,但是我不想花时间去测试你所说的问题,那要写相当多的代码
如果可能的话,请你将一个能够反映问题的代码公开出来,这样比较省事一些,在这里我只
是提出一个建议,一般的建议是你可以使用Toolkit.getDefaultToolkit().getSystemEventQueue()
获取EventQueue() 对象,判断你的TextField输入是否合法,如果非法的话,直接删除gainedFocus
事件(本质和Delphi下面的消息截获一样),不要去弹什么对话框,那非常招人讨厌的。
当然,我的想法也有问题,如果一直出错的话,你的DataTextField可能应永远会占用焦点。[:)]
 
sorry,由于近来忙,没时间修改后再贴,可能下面的代码需要去掉某些(如MainFrame..)引用才能独立使用,
有空就帮俺试试!
import javax.swing.*;
import javax.swing.text.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;
public class UniDTextField extends JTextField implements FocusListener
{
// private MainFrame mMainFrame;
private String mTag="";
//日期分隔符
private char mSparator='-';
/**constructs a date field ,add the sparator is '-'*/
public UniDTextField()
{
super();
setDocument(new DTextDoc(this,mSparator));
setBorder(BorderFactory.createLoweredBevelBorder());
setFont(new Font("宋体",0,13));
addFocusListener(this);
}
/**constructs a date field the specified sparator
* @param main 主窗口对象引用
* @param tag 控制标示
* @param sp 日期分隔符,如'/'、'-'
*/
public UniDTextField( String tag, char sp)
{ super(12);
mTag = tag;
// mMainFrame = main;
mSparator = sp;
setDocument(new DTextDoc(this,mSparator));
setBorder(BorderFactory.createLoweredBevelBorder());
setFont(new Font("宋体",0,13));
addFocusListener(this);
}
/**初始化日期输入框
* @param date 日期格式的字串,如("yyyy-mm-dd"、"yyyymmdd")
* 没有返回值
*/
public void init(String date){
setText(date);
}
/**参考接口ComponentUnit中的方法说明*/
public void setStatus(int pStatus ){
if (mTag.equals("1")) {
setBackground(new Color(255, 255, 173));
setEditable(true);
}
if (mTag.equals("2")) {
setBackground(Color.white);
setEditable(true);
}
if (mTag.equals("3")) {
setBackground(Color.lightGray);
setEditable(false);

}
}
/**参考接口ComponentUnit中的方法说明*/
public void clearField(){}
public void focusGained(FocusEvent e){}
//失去焦点时,对输入的日期进行合法性验证
public void focusLost(FocusEvent e)
{ removeFocusListener(this);
if(!DTextDoc.isLegalDate(getText()))
{
Toolkit.getDefaultToolkit().beep();
JOptionPane.showMessageDialog(this,"不合法的日期,please input again.");
requestFocus();
}
addFocusListener(this);
}
}
class DTextDoc extends PlainDocument
{ private char sparator = '-';
private JTextComponent textComponent;
private int newOffset;
private AttributeSet mAttributeSet=null;
public DTextDoc(JTextComponent tc,char sp) {
textComponent = tc;
sparator = sp;
String strCurrentDate=getCurrentDate();
try{insertString(0, strCurrentDate, null);}catch(Exception ex){
Toolkit.getDefaultToolkit().beep();
return;
}
}
public void insertString(int offset, String s,AttributeSet attributeSet) throws BadLocationException
{ String strY="",strM="",strD="";
if (mAttributeSet==null) mAttributeSet = attributeSet;
if (s.length()==1)
{
try {Integer.parseInt(s);}catch(Exception ex)
{ Toolkit.getDefaultToolkit().beep();
return;
}
newOffset = offset;
if(offset==4||offset==7){
newOffset++;
textComponent.setCaretPosition(newOffset);
}
super.remove(newOffset, 1);
super.insertString(newOffset, s, attributeSet);
}
else
if(s.length()==10||s.length()==8){
if (!isLegalDate(s))
{
Toolkit.getDefaultToolkit().beep();
return;
}
if (s.length()==10)
{ try{
strY=s.substring(0,4);
strM=s.substring(5,7);
strD=s.substring(8);
}catch(Exception e){
Toolkit.getDefaultToolkit().beep();
return ;
}
}
else
if(s.length()==8)
{ try{
strY=s.substring(0,4);
strM=s.substring(4,6);
strD=s.substring(6);
}catch(Exception e){
Toolkit.getDefaultToolkit().beep();
return ;
}
}
super.remove(0,getLength());
super.insertString(0, strY +sparator + strM + sparator + strD, attributeSet);
} else
{ Toolkit.getDefaultToolkit().beep();
return;
}
}
public void remove(int offset, int length) throws BadLocationException
{
if(offset==4||offset==7)
{ textComponent.setCaretPosition(offset);
return;
}
textComponent.setCaretPosition(offset);
super.remove(offset,1);
super.insertString(offset, "0", mAttributeSet);
textComponent.setCaretPosition(offset);
}
/**判断日期的合法性
* @param strDate 日期格式的字符串,如("yyyy-mm-dd"、"yyyymmdd")
* 返回值 如果合法返回true,否则返回false
*/
public static boolean isLegalDate(String strDate)
{
int intY,intM,intD;
int[]standardDays={31,28,31,30,31,30,31,31,30,31,30,31};
int[]leapyearDays={31,29,31,30,31,30,31,31,30,31,30,31};
if (strDate.trim().length()==10)
{ strDate=strDate.trim();
try{
intY=Integer.parseInt(strDate.substring(0,4));
intM=Integer.parseInt(strDate.substring(5,7));
intD=Integer.parseInt(strDate.substring(8));
}catch(Exception e){return false;}
}
else
if(strDate.trim().length()==8)
{ strDate=strDate.trim();
try{
intY=Integer.parseInt(strDate.substring(0,4));
intM=Integer.parseInt(strDate.substring(4,6));
intD=Integer.parseInt(strDate.substring(6));
}catch(Exception e){return false;}
} else
return false;
if (intM>12||intM<1||intY<1||intD<1)return false;
if ((intY%4==0&amp;&amp;intY%100!=0)||intY%400==0)return (intD<=leapyearDays[intM-1]);
return (intD<=standardDays[intM-1]);
}
/**获取当前系统日期
* 返回值 为带分隔符的日期格式的字符串,如"yyyy-mm-dd"
*/
private String getCurrentDate()
{
GregorianCalendar Day=new GregorianCalendar();
int yyyy,mm,dd;
String MM,DD;
yyyy=Day.get(Calendar.YEAR);
mm=Day.get(Calendar.MONTH)+1;
dd=Day.get(Calendar.DATE);
if (mm<10)MM="0"+mm;else
MM=Integer.toString(mm);
if (dd<10)DD="0"+dd;else
DD=Integer.toString(dd);
return yyyy + ""+sparator + MM + sparator + DD;
}
}
 
你有没有试试,不用JOptionPane直接requestFocus() ?
这串代码长了点,觉得眼晕 *_*
public void focusLost(FocusEvent e)
{ removeFocusListener(this);
if(!DTextDoc.isLegalDate(getText()))
{
// Toolkit.getDefaultToolkit().beep();
// JOptionPane.showMessageDialog(this,"不合法的日期,please input again.");
requestFocus();
}
addFocusListener(this);
}
 
THANKS!
如果 不要求requestFocus() ,问题不存在。
如果 requestFocus() ,鼠标不转移到jTable,问题也存在,但至少还可以降焦点点回到光标位置。
问题不一定出在JOptionPane弹出的Dialog。
所以目前还是选择放弃requestFocus()。
而且弹出Dialog,是必须的,因为我们是采用纯applet(swing 、java web start) + servlet+ejb + db的体系。
也就是说尽可能接近原来C/S模式的界面效果。
 
接受答案了.
 
后退
顶部