贴出我写得第一个轻量级组件-单行文本编辑器

ghostvalley 2004-07-09 07:08:50
//轻量级组建为java.awt.Component或java.awt.Container的子类
public class KTextField extends java.awt.Component
{
//text
private StringBuffer m_text; //文本
//caret position
private int m_cpos = 0; //光标列位置,m_cpos∈[0,N]
//selection
private int m_csel_end = -1; //选择尾,-1代表未选择

private boolean m_isEditable = true; //是否可编辑

private boolean m_cursor_sparkling_light = true; //光标闪烁

private int m_view_x = 20; //视图左界,右界为m_view_x+this.getWidth()
public KTextField()
{
this("");
}
public KTextField(String text0)
{
m_text = new StringBuffer(text0);
this.addMouseListener(new java.awt.event.MouseAdapter()
{
public void mousePressed(java.awt.event.MouseEvent e)
{
requestFocus();
this_mousePressed(e.getX()+1+m_view_x);
}
public void mouseEntered(java.awt.event.MouseEvent e)
{

setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.TEXT_CURSOR));
}
public void mouseExited(java.awt.event.MouseEvent e)
{

setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR));
}
});
this.addMouseMotionListener(new java.awt.event.MouseMotionAdapter()
{
public void mouseDragged(java.awt.event.MouseEvent e)
{
int x = e.getX()+1+m_view_x;
this_mouseDragged(x);
}
});
this.addKeyListener(new java.awt.event.KeyAdapter()
{
public void keyTyped(java.awt.event.KeyEvent e)
{
char c = e.getKeyChar();
if(Character.isDefined(c) && Character.getType(c)!=Character.CONTROL){
this_keyTyped(c);
}
}
public void keyPressed(java.awt.event.KeyEvent e)
{
//光标移动
switch(e.getKeyCode()){
case java.awt.event.KeyEvent.VK_LEFT:
this_keyLeft(e);
break;
case java.awt.event.KeyEvent.VK_RIGHT:
this_keyRight(e);
break;
case java.awt.event.KeyEvent.VK_HOME:
this_keyHome(e);
break;
case java.awt.event.KeyEvent.VK_END:
this_keyEnd(e);
break;
//删除键
case java.awt.event.KeyEvent.VK_BACK_SPACE:
this_keyBackspace();
break;
case java.awt.event.KeyEvent.VK_DELETE:
this_keyDelete();
break;
//修改字体
case java.awt.event.KeyEvent.VK_UP:
setFont(new java.awt.Font(getFont().getName(),getFont().getStyle(),getFont().getSize()+1));
repaint();
break;
case java.awt.event.KeyEvent.VK_DOWN:
setFont(new java.awt.Font(getFont().getName(),getFont().getStyle(),getFont().getSize()-1));
repaint();
break;
}
}
});

new Thread(){ //用于光标闪烁
public void run()
{
while(true){
repaint();
m_cursor_sparkling_light = !m_cursor_sparkling_light;
try {
sleep(200);
}
catch (InterruptedException ex) {
}
}
}
}.start();
}

public String getText()
{
return m_text.toString();
}
public void setText(String text)
{
m_text.delete(0,m_text.length());
m_text.append(text);
m_cpos = 0;
m_csel_end = -1;
onTextChanged();
onCaretChanged();
onSelChanged();
repaint();
}
//光标位置
public int getCaretPosition()
{
return m_cpos;
}
public void setCaretPosition(int cpos)
{
if(cpos<0 && cpos>m_text.length()){
throw new RuntimeException("Exception: Caret position out of range!");
}
m_cpos = cpos;
onCaretChanged();
repaint();
}
//文本选择
public void select(int start,int end)
{
m_cpos = start;
m_csel_end = end;
onCaretChanged();
onSelChanged();
repaint();
}
public void selectAll()
{
select(0,m_text.length());
}
public int getSelectionStart()
{
if(m_csel_end != -1){
return m_cpos;
}else{
return -1;
}
}
public int getSelectionEnd()
{
return m_csel_end;
}
public String getSelectedText()
{
if(m_csel_end != -1){
int csel_start,csel_end;
if(m_cpos<m_csel_end){
csel_start = m_cpos;
csel_end = m_csel_end;
}else{
csel_start = m_csel_end;
csel_end = m_cpos;
}
return m_text.substring(csel_start,csel_end);
}else{
return null;
}
}
public boolean isEditable()
{
return m_isEditable;
}
public void setEditable(boolean b)
{
m_isEditable = b;
}
public void setEnabled(boolean b)
{
this.setEditable(b);
super.setEnabled(b);
}
/**
* TODO:...通知所有的监听者文本改变事件
*/
protected void onTextChanged()
{

}
/**
* TODO:...通知所有的监听者光标位置改变事件
*/
protected void onCaretChanged()
{
}
/**
* TODO:...通知所有的监听者选择改变事件
*/
protected void onSelChanged()
{
}
private java.awt.Image m_offImage = null;
public void invalidate()
{
super.invalidate();
m_offImage = null;
}
public void update(java.awt.Graphics g)
{
paint(g);
}
...全文
153 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
ghostvalley 2004-07-09
  • 打赏
  • 举报
回复
已经有很好的轮子了,为何还要造个椭圆的??
----------------------------
想看看能不能使用方的而胜过圆的
onefox 2004-07-09
  • 打赏
  • 举报
回复
已经有很好的轮子了,为何还要造个椭圆的??
centralplains 2004-07-09
  • 打赏
  • 举报
回复
怎么字体和边框会有明显的闪动?
ghostvalley 2004-07-09
  • 打赏
  • 举报
回复
上面是测试程序,这个组件的用法基本与java.awt.TextField相同
多行文便编辑器组件的源代码在:
http://community.csdn.net/Expert/topic/3161/3161119.xml?temp=.1555445
ghostvalley 2004-07-09
  • 打赏
  • 举报
回复
public class MyApp extends java.awt.Frame
{
public static void main(String[] args) throws Exception
{
MyApp myApp1 = new MyApp();
}
private KTextField m_textField1 = new KTextField("欢迎使用轻量级组件编写的文本编辑器。");
private KTextField m_textField2 = new KTextField("这个演示了修改光标的方法,你可以使用鼠标点击或键盘的光标键来修改光标");
private KTextField m_textField3 = new KTextField("这个演示了选择区域的方法,你可以使用鼠标拖动或光标键+SHIFT来修改选择区域");
private KTextField m_textField4 = new KTextField("这个演示了不可编辑的文本组件");


public MyApp() throws Exception
{
addWindowListener(new java.awt.event.WindowAdapter(){
public void windowClosing(java.awt.event.WindowEvent e)
{
dispose();
}
public void windowClosed(java.awt.event.WindowEvent e)
{
System.exit(0);
}
});
setSize(250,200);
// setResizable(false);
setLayout(new java.awt.GridLayout(0,1,5,10));

add(m_textField1);
add(m_textField2);
m_textField2.setCaretPosition(6);
add(m_textField3);
m_textField3.select(4,14);
add(m_textField4);
m_textField4.setEditable(false);
add(new java.awt.TextField("这是AWT提供的文本编辑组件,用于对照。"));
// pack();
setLocation((java.awt.Toolkit.getDefaultToolkit().getScreenSize().width-this.getSize().width)/2,(java.awt.Toolkit.getDefaultToolkit().getScreenSize().height-this.getSize().height)/2);
setVisible(true);
m_textField1.setFont(new java.awt.Font(this.getFont().getName(),this.getFont().getStyle(),this.getFont().getSize()+2));
m_textField4.setFont(new java.awt.Font(this.getFont().getName(),this.getFont().getStyle(),this.getFont().getSize()+5));
m_textField2.requestFocus();
}
}
ghostvalley 2004-07-09
  • 打赏
  • 举报
回复
public class MyApp extends java.awt.Frame
{
public static void main(String[] args) throws Exception
{
MyApp myApp1 = new MyApp();
}
private KTextField m_textField1 = new KTextField("欢迎使用轻量级组件编写的文本编辑器。");
private KTextField m_textField2 = new KTextField("这个演示了修改光标的方法,你可以使用鼠标点击或键盘的光标键来修改光标");
private KTextField m_textField3 = new KTextField("这个演示了选择区域的方法,你可以使用鼠标拖动或光标键+SHIFT来修改选择区域");
private KTextField m_textField4 = new KTextField("这个演示了不可编辑的文本组件");


public MyApp() throws Exception
{
addWindowListener(new java.awt.event.WindowAdapter(){
public void windowClosing(java.awt.event.WindowEvent e)
{
dispose();
}
public void windowClosed(java.awt.event.WindowEvent e)
{
System.exit(0);
}
});
setSize(250,200);
// setResizable(false);
setLayout(new java.awt.GridLayout(0,1,5,10));

add(m_textField1);
add(m_textField2);
m_textField2.setCaretPosition(6);
add(m_textField3);
m_textField3.select(4,14);
add(m_textField4);
m_textField4.setEditable(false);
add(new java.awt.TextField("这是AWT提供的文本编辑组件,用于对照。"));
// pack();
setLocation((java.awt.Toolkit.getDefaultToolkit().getScreenSize().width-this.getSize().width)/2,(java.awt.Toolkit.getDefaultToolkit().getScreenSize().height-this.getSize().height)/2);
setVisible(true);
m_textField1.setFont(new java.awt.Font(this.getFont().getName(),this.getFont().getStyle(),this.getFont().getSize()+2));
m_textField4.setFont(new java.awt.Font(this.getFont().getName(),this.getFont().getStyle(),this.getFont().getSize()+5));
m_textField2.requestFocus();
}
}
rayjava 2004-07-09
  • 打赏
  • 举报
回复
鼓励鼓励..
ghostvalley 2004-07-09
  • 打赏
  • 举报
回复
贴完了
ghostvalley 2004-07-09
  • 打赏
  • 举报
回复
private void this_keyEnd(java.awt.event.KeyEvent e)
{
if((e.getModifiers()&java.awt.event.KeyEvent.SHIFT_MASK) != 0){ //for selection
m_csel_end = m_cpos<m_text.length() ? m_text.length() : -1;
}else{
m_csel_end = -1;
m_cpos = m_text.length();
}
onCaretChanged();
onSelChanged();
repaint();
}
private int find_cpos(int x) //查找像素x所在的光标区,使用对分搜索方法
{
int cpos = 0;
int N = m_text.length();
if(N > 0){
java.awt.FontMetrics fm = this.getFontMetrics(this.getFont());
if(x <= fm.stringWidth(m_text.substring(0,1))/2-1){ //x在0区右界,注意这个0区的右界要归到0区
cpos = 0;
}else if(x >= (fm.stringWidth(m_text.substring(0,N-1))+fm.stringWidth(m_text.substring(0,N)))/2){ //x在N区左界
cpos = N;
}else{
boolean suitable = false;
int L = 1,H = N-1; //上界、下界
while(! suitable){ //使用对分搜索寻找区域
cpos = (L+H)/2; //中点
if(x>=(fm.stringWidth(m_text.substring(0,cpos-1))+fm.stringWidth(m_text.substring(0,cpos)))/2 && x<(fm.stringWidth(m_text.substring(0,cpos))+fm.stringWidth(m_text.substring(0,cpos+1)))/2){ //x在cpos所在的区
suitable = true;
}else if(x >= (fm.stringWidth(m_text.substring(0,cpos))+fm.stringWidth(m_text.substring(0,cpos+1)))/2){
L = cpos+1;
}else{
H = cpos-1;
}
}
}
}
return cpos;
}
private void this_mousePressed(int x)
{
m_csel_end = -1;
int cpos = find_cpos(x);
if(m_cpos != cpos){
m_cpos = cpos;
}
onCaretChanged();
repaint();
}
private void this_mouseDragged(int x) {

int m_csel_end1 = find_cpos(x);
if(m_csel_end1 != m_csel_end){
m_csel_end = m_csel_end1;
if(m_csel_end==m_cpos){
m_csel_end = -1;
}
onSelChanged();
repaint();
}
}
private void this_keyTyped(char c)
{
if(m_isEditable){
if(m_csel_end != -1){
int csel_start,csel_end;
if(m_cpos<m_csel_end){
csel_start = m_cpos;
csel_end = m_csel_end;
}else{
csel_start = m_csel_end;
csel_end = m_cpos;
}
m_text.delete(csel_start,csel_end);
m_csel_end = -1;
m_cpos = csel_start;
}
m_text.insert(m_cpos,c);
m_cpos++;
onTextChanged();
onSelChanged();
onCaretChanged();
repaint();
}
}
private void this_keyBackspace()
{
if(m_isEditable){
if(m_csel_end != -1){
int csel_start,csel_end;
if(m_cpos<m_csel_end){
csel_start = m_cpos;
csel_end = m_csel_end;
}else{
csel_start = m_csel_end;
csel_end = m_cpos;
}
m_text.delete(csel_start,csel_end);
m_csel_end = -1;
m_cpos = csel_start;
}else{
if(m_cpos>0){
m_text.deleteCharAt(m_cpos-1);
m_cpos--;
}
}
onSelChanged();
onTextChanged();
onCaretChanged();
repaint();
}
}
private void this_keyDelete()
{
if(m_isEditable){
if(m_csel_end != -1){
int csel_start,csel_end;
if(m_cpos<m_csel_end){
csel_start = m_cpos;
csel_end = m_csel_end;
}else{
csel_start = m_csel_end;
csel_end = m_cpos;
}
m_text.delete(csel_start,csel_end);
m_csel_end = -1;
m_cpos = csel_start;
}else{
if(m_cpos<m_text.length()){
m_text.deleteCharAt(m_cpos);
}
}
onSelChanged();
onCaretChanged();
onTextChanged();
repaint();
}
}
public java.awt.Dimension getPreferredSize()
{
return new java.awt.Dimension(this.getFontMetrics(this.getFont()).stringWidth(m_text.toString()),this.getFontMetrics(this.getFont()).getHeight());
}
public boolean isFocusTraversable()
{
return true;
}
}
ghostvalley 2004-07-09
  • 打赏
  • 举报
回复

public void paint(java.awt.Graphics g)
{
if(m_offImage == null){
m_offImage = this.createImage(this.getWidth(),this.getHeight());
}
java.awt.Graphics gOff = m_offImage.getGraphics();
gOff.setColor(java.awt.Color.white);
gOff.fillRect(0,0,this.getWidth(),this.getHeight());

java.awt.FontMetrics fm = gOff.getFontMetrics();
//rectangle 外框
gOff.setColor(java.awt.Color.blue);
gOff.drawRect(0,0,this.getWidth()-1,this.getHeight()-1);
gOff.drawRect(0,0,this.getWidth()-1,this.getHeight()-1);

gOff.setClip(1,1,this.getWidth()-2,this.getHeight()-2);

//调整视图左界,使目标区位置在视图区
int W = this.getWidth()-4; //视图宽度
int view_left_bound = m_view_x, view_right_bound = m_view_x+W; //视图界
int zone0_left_bound = 0, zone0_right_bound = m_text.length()>0 ? fm.stringWidth(m_text.substring(0,1))/2 : 0; //0区界
int zoneN_left_bound = m_text.length()>0 ? (fm.stringWidth(m_text.substring(0,m_text.length()-1))+fm.stringWidth(m_text.substring(0,m_text.length())))/2 : 0,
zoneN_right_bound = m_text.length()>0 ? fm.stringWidth(m_text.substring(0,m_text.length())) : 0; //N区界

int cpos = (m_csel_end==-1 ? m_cpos : m_csel_end); //目标区位置

if(cpos==0){ //光标在0区
if(zone0_left_bound<view_left_bound){
m_view_x = zone0_left_bound;
}
if(zone0_right_bound>view_right_bound){
m_view_x = zone0_right_bound-W;
}
}else if(cpos==m_text.length()){ //光标在N区
if(zoneN_left_bound<view_left_bound){
m_view_x = zoneN_left_bound;
}
if(zoneN_right_bound>view_right_bound){
m_view_x = zoneN_right_bound-W;
}
}else{ //光标在其他区
int zone_cpos_left_bound = (fm.stringWidth(m_text.substring(0,cpos-1))+fm.stringWidth(m_text.substring(0,cpos)))/2,
zone_cpos_right_bound = (fm.stringWidth(m_text.substring(0,cpos))+fm.stringWidth(m_text.substring(0,cpos+1)))/2; //cpos区界

if(zone_cpos_left_bound<view_left_bound){
m_view_x = zone_cpos_left_bound;
}
if(zone_cpos_right_bound>view_right_bound){
m_view_x = zone_cpos_right_bound-W;
}
}
//设置视图
gOff.translate(1-m_view_x,1);
//draw text 画文本
gOff.setColor(java.awt.Color.black);
gOff.drawString(m_text.toString(),0,fm.getMaxAscent());

//draw selection 画选择
if(m_csel_end != -1){
int csel_start,csel_end;
if(m_cpos<m_csel_end){
csel_start = m_cpos;
csel_end = m_csel_end;
}else{
csel_start = m_csel_end;
csel_end = m_cpos;
}
int selstartx = fm.stringWidth(m_text.substring(0,csel_start));
int selendx = fm.stringWidth(m_text.substring(0,csel_end));
gOff.setColor(java.awt.Color.blue.darker());
gOff.fillRect(selstartx,0,selendx-selstartx+1,fm.getHeight());
gOff.setColor(java.awt.Color.white);
gOff.drawString(m_text.substring(csel_start,csel_end),selstartx,fm.getMaxAscent());
}
//draw caret
if(this.hasFocus() && m_csel_end==-1){
if(m_cursor_sparkling_light){
int cur_pos = fm.stringWidth(m_text.substring(0,m_cpos));
gOff.setColor(java.awt.Color.red);
gOff.drawLine(cur_pos,1,cur_pos,fm.getHeight()-1);
gOff.drawLine(cur_pos-1,1,cur_pos+1,1);
gOff.drawLine(cur_pos-1,fm.getHeight()-1,cur_pos+1,fm.getHeight()-1);
}
}

g.drawImage(m_offImage,0,0,null);
gOff.dispose();
}
private void this_keyLeft(java.awt.event.KeyEvent e)
{
if((e.getModifiers()&java.awt.event.KeyEvent.SHIFT_MASK) != 0){ //for selection method
if(m_csel_end==-1){ //no selection
m_csel_end = m_cpos>0? m_cpos-1 : -1;
}else{ //selection
m_csel_end = (m_csel_end>0 ? m_csel_end-1 : 0);
if(m_csel_end==m_cpos){
m_csel_end = -1;
}
}
}else{ //for movement
if(m_csel_end != -1){
m_csel_end = -1;
}
if(m_cpos>0){
m_cpos--;
}
}
onSelChanged();
onCaretChanged();
repaint();
}
private void this_keyRight(java.awt.event.KeyEvent e)
{
if((e.getModifiers()&java.awt.event.KeyEvent.SHIFT_MASK) != 0){ //for selection
if(m_csel_end==-1){ //have not selection
m_csel_end = m_cpos<m_text.length()? m_cpos+1 : -1;
}else{
m_csel_end = (m_csel_end<m_text.length() ? m_csel_end+1 : m_text.length());
if(m_csel_end==m_cpos){
m_csel_end = -1;
}
}
}else{
m_csel_end = -1;
if(m_cpos<m_text.length()){
m_cpos++;
}
}
onCaretChanged();
onSelChanged();
repaint();
}
private void this_keyHome(java.awt.event.KeyEvent e)
{
if((e.getModifiers()&java.awt.event.KeyEvent.SHIFT_MASK) != 0){ //for selection
m_csel_end = m_cpos>0 ? 0 : -1;
}else{
m_csel_end = -1;
m_cpos = 0;
}
onCaretChanged();
onSelChanged();
repaint();
}

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧