精华内容
下载资源
问答
  • [J2ME]触摸屏功能实现代码一

    千次阅读 2010-11-10 13:58:00
    { 其实J2ME做触摸开发也不是很难的,呵呵,有兴趣的朋友接着往下看吧。  在WTK目录下的/WTK22/wtklib/devices/...1.pointerDragged(int x, int y) 触摸屏拖拽事件 (暂时还没研究) 2.pointerP

     


    在WTK目录下的/WTK22/wtklib/devices/DefaultColorPhone/DefaultColorPhone.properties
    的文件中有一行touch_screen=false,把它改成true就可以了
    MIDP2.0对于触摸屏方法有3个
    1.pointerDragged(int x, int y) 触摸屏拖拽事件(暂时还没研究)
    2.pointerPressed(int x, int y) 触摸屏按压
    3.pointerReleased(int x, int y) 触摸屏释放
    pointerPressed(int x, int y)当用户按下触摸屏的时候会自动调用这个方法x,y就是当前压下的坐标
    pointerReleased(int x, int y)和pointerPressed(int x, int y)类似相应触摸屏释放事件
    这里,我只是以相应左右软键及菜单事件处理为例:

    protected void pointerPressed(int x, int y) {
    switch (status) {
    case Consts.S_MENU:
    int menuWidth = 90;
    int menuItemHeight = 17;
    int menuBarHeight = 16;
    int menuNum = 10;
    if (x < menuWidth
    && y > (screenHeight - (menuItemHeight * menuNum + menuBarHeight))) {
    int menuIndex = (y - (screenHeight - (menuItemHeight * menuNum + menuBarHeight)))
    / menuItemHeight;
    doMenuOK(menuIndex);
    }
    case Consts.S_DRAW_DIBIAO_LIST:
    case Consts.S_LOCAL_SEARCH_RESULT:
    case Consts.S_MAP_VIEW:
    // 左右软键40*20的区域
    if (x < 40 && y > (screenHeight - 20)) {
    doCommandLeft();
    }

    if (x > (screenWidth - 40) && y > (screenHeight - 20)) {
    doCommandRight();
    }
    break;
    }
    }


    触摸屏功能的实现大致来说要在三处添加代码:1.在Screen类中重写触摸功能;
    2.建立一个触摸屏对象,使要实现触摸功能的控件以对象的方式保存在Vector 中;
    3.在获取页面时,把要实现的触摸控件保存在Vector 中;

    以项目中的源码为例,这三个部分的代码如下:

    1.Screen类:
    (本源码最后两个方法为:字符占屏幕宽度及高度的计算方法)

    /**
     * Data:2010.02.25
     * Time:15:18:20
     
    */

    package  com.xuudoo.ewl;

    import
     java.util.Vector;

    import
     javax.microedition.lcdui.Canvas;
    import
     javax.microedition.lcdui.Command;
    import
     javax.microedition.lcdui.CommandListener;
    import
     javax.microedition.lcdui.Display;
    import
     javax.microedition.lcdui.Displayable;
    import
     javax.microedition.lcdui.Font;
    import
     javax.microedition.lcdui.Graphics;
    import
     javax.microedition.lcdui.Image;
    import
     javax.microedition.midlet.MIDlet;

    import
     com.xuudoo.booking.BizWindow;
    import
     com.xuudoo.booking.BookingMidlet;
    import
     com.xuudoo.booking.BusinessWindow;
    import
     com.xuudoo.booking.FirstPage;
    import
     com.xuudoo.booking.IOManager;
    import
     com.xuudoo.booking.UIManager;

    public   class  EWLScreen  extends  Canvas  //  FullCanvas

             implements  CommandListener  {

        
    public   static   final   int  SCREEN_WIDTH  =    360 ; // 屏宽

         public   static   final   int  SCREEN_HEIGHT  =    640 ; // 屏高
        
        
    public   static   final   int  KEY_CODE_LEFT_SOFT_KEY  =   - 6 ; // 左软键

         public   static   final   int  KEY_CODE_RIGHT_SOFT_KEY  =   - 7 ; // 右软键
        
        
    public   static  EWLScreen instance  =   new
     EWLScreen();
        
    public   static
     Display display;
        
    protected
     EWLWindow activeWindow;
        
    protected
     EWLWindow popupWindow;
        
        
    public   static  Image splashImg  =   null ; // 初始化图片

         private   static  String splashImgPath  =   " /LogoXD.png " ; // 初始化图片地址
         public   static  Image main_bg  =   null ; // 背景图片
         private   static  String main_bgPath  =   " /bg.png " ; // 背景图片地址
         public   static   boolean  connectAgain  =   false ; // 用cmnet联网失败后再连接
         public   static   boolean  connectPrompt  =   true ; // 第一此联网询问时是否连接网络
         public   static   boolean  phoneNoMoney  =   false ; // 手机欠费标志位
        
        
    public  EWLScreen() 
    {
            setFullScreenMode(
    true
    );
        }


        
    public   static   void  init(MIDlet midlet)  {
            display 
    =
     Display.getDisplay(midlet);
            instance.iniLogoPic();
        }


        
    public   int  getHeight()  {
            
    return
     SCREEN_HEIGHT;
        }


        
    public   int  getWidth()  {
            
    return
     SCREEN_WIDTH;
        }


        
    /**
         * 第一次登陆,画Logo登录 图片
         
    */

        
    public   void  iniLogoPic()  {
            
    // 图片资源

             try {
                splashImg 
    =
     Image.createImage(splashImgPath);
                main_bg 
    =
     Image.createImage(main_bgPath);
            }
    catch (Exception e)
            
    {
                
    if
    (BookingMidlet.DEBUG)
                    e.printStackTrace();
            }

        }

        
        
    // 调试时显示信息之用
         public   static  String prompt1  =   null ;
        
    public   static  String prompt2  =   null
    ;
        
    public   static  String prompt3  =   null
    ;
        
    protected   void  paint(Graphics g) 
    {
            
    // 登陆时的提示界面

             if (UIManager.state  ==  UIManager.STATE_LOGIN) {
                
    if (splashImg  !=   null
    )
    //
                    g.drawImage(splashImg, (EWLScreen.SCREEN_WIDTH - splashImg.getWidth()) / 2,
    //                         (EWLScreen.SCREEN_HEIGHT - splashImg.getHeight()) / 2, 20);

                    g.drawImage(splashImg,  0 , 0 20 );
                drawConnectPrompt(g);
    // 画提示信息

                String leftSoftStr = " 登陆 " ;
                
    if
    (connectAgain)
                    leftSoftStr
    = null
    ;
                
    this .drawSoftKeys(g, leftSoftStr,  " 退出 " 0xff0000 ); // 画提示界面左右软键

                 return ;
            }
    else {
    //
                if(main_bg != null)
    //                 g.drawImage(main_bg,0,0,20);

                 if  (activeWindow  !=   null ) {
                    activeWindow.paint(g);
                }

                
    if  (popupWindow  !=   null ) {
                    popupWindow.paint(g);
                }

            }

            
    // -----------------------调试信息-----------------------------
    //
                g.setColor(0xff0000);
    //
                if(prompt1 != null )
    //
                    g.drawString(prompt1, 10, 260, 0);
    //
                if(prompt2 != null )
    //
                    g.drawString(prompt2, 10, 280, 0);
    //
                if(prompt3 != null )
    //                 g.drawString(prompt3, 10, 240, 0);

        }


        
    /**
         * 画联网提示,并兼容原来系统 的字体和颜色
         
    */

        
    private   void  drawConnectPrompt(Graphics g) {
            
    int  nowColor  =
     g.getColor();
            Font nowFont 
    =
     g.getFont();
            g.setColor(
    0x000000
    );
            g.setFont(UIManager.my_smallFont);
            
            String httpConMode
    = ""
    ;
            String promptStr1 
    = ""
    ;
            String promptStr2 
    = ""
    ;
            
    if (BookingMidlet.useProxy)
    {
                promptStr1 
    = " 友情提示:请选用移动梦网 "
    ;
                promptStr2 
    = " 连接方式。 "
    ;
                httpConMode
    = " 移动梦网 "
    ;
            }
    else {
                promptStr1 
    = " 友情提示:请选用CMNET "
    ;
                promptStr2 
    = " 或WLAN连接方式。 "
    ;
                httpConMode
    = " CMNET或WLAN "
    ;
            }

            
            
    if (connectAgain) {
                promptStr1
    = " 友情提示:请重新登录 "
    ;
                
    if ( ! connectPrompt)
    {
                    promptStr2
    = " 并同意使用网络 "
    ;
                }
    else {
                    promptStr2
    = " 选用 " +
    httpConMode;
                    
    if
    (phoneNoMoney)
                        promptStr2
    = " 确认网络信号或手机话费 "
    ;
                }

            }

            
    int  promptStr_X =  (EWLScreen.SCREEN_WIDTH - getStringWidth(g.getFont(),promptStr1)) / 2 ;
            
    int  promptStr_Y =  EWLScreen.SCREEN_HEIGHT * 3 / 5
    ;
            g.drawString(promptStr1, promptStr_X, promptStr_Y, 
    0
    );
            g.drawString(promptStr2, promptStr_X, promptStr_Y
    + g.getFont().getHeight(),  0
    );
            g.setColor(nowColor);
            g.setFont(nowFont);
        }

        
    /**
         * 绘制左右软键
         *
         * 
    @param  lSoftKeyName 左软键名称 如果null则不绘制
         * 
    @param
     rSoftKeyName 右软键名称 如果null则不绘制
         * 
    @param
     color        绘制软键的颜色
         * 
         
    */

        
    private   void  drawSoftKeys(Graphics g, String lSoftKeyName,
                String rSoftKeyName, 
    int
     color)
        
    {
            
    if  (lSoftKeyName  !=   null
    )
            
    { //  左软键
                 int  x  =  FirstPage.LRSoft_LeftAndTopPosition[ 0 ][ 0 ] +  FirstPage.LRSoft_length_high[ 0 ] / 2 ;
                
    int  y  =  FirstPage.LRSoft_LeftAndTopPosition[ 0 ][ 1 ] +  FirstPage.LRSoft_length_high[ 1 ] / 2
    ;
    //             g.setClip(x, y, getStringWidth(g.getFont(), lSoftKeyName), g.getFont().getHeight());

                g.drawString( lSoftKeyName, x, y, Graphics.HCENTER | Graphics.BASELINE);
            }

            
    if  (rSoftKeyName  !=   null )
            
    { //  右软键
                 int  x  =  FirstPage.LRSoft_LeftAndTopPosition[ 1 ][ 0 ] +  FirstPage.LRSoft_length_high[ 0 ] / 2 ;
                
    int  y  =  FirstPage.LRSoft_LeftAndTopPosition[ 1 ][ 1 ] +  FirstPage.LRSoft_length_high[ 1 ] / 2
    ;
    //             g.setClip(x, y, getStringWidth(g.getFont(), rSoftKeyName), g.getFont().getHeight());

                g.drawString(rSoftKeyName, x, y, Graphics.HCENTER | Graphics.BASELINE);
            }

            
        }

        
        
        
    /**
         * 初始化提示界面时的交互处理
         * 
    @param  keyCode
         
    */

        
    private   void  stateLoginKeyPressed( int  keyCode) {
            
    int  gameCode  =   0
    ;
            
    try
    {
                gameCode 
    =   this
    .getGameAction(keyCode);
            }
    catch (Exception e) {
                System.out.println(
    " get gameaction key error: " +
    keyCode);
            }

            
    if (gameCode == Canvas.UP  ||  gameCode == Canvas.LEFT
                    
    ||  gameCode == Canvas.RIGHT  ||  gameCode ==
    Canvas.DOWN
                    
    ||  gameCode ==
    Canvas.FIRE)
            
    {
                ;
            }

            
    else   if  (keyCode  ==  EWLScreen.KEY_CODE_LEFT_SOFT_KEY
                    
    ||  keyCode  ==  EWLScreen.KEY_CODE_RIGHT_SOFT_KEY) 
    {
                gameCode 
    =
     keyCode;
            }

            
    else   if (keyCode == 21 || keyCode ==- 21 )
                gameCode 
    =
     EWLScreen.KEY_CODE_LEFT_SOFT_KEY;
            
    else   if (keyCode == 22 || keyCode ==- 22
    )
                gameCode 
    =
     EWLScreen.KEY_CODE_RIGHT_SOFT_KEY;
            
    else

                
    return ;
            
            
    switch  (gameCode) 
    {
                
    case
     Canvas.FIRE:
                
    case  EWLScreen.KEY_CODE_LEFT_SOFT_KEY: //
     左软键
                    
    // 向服务器验证身份,打开首页面

                    UIManager.state = UIManager.STATE_LOGIN_httpConnecting;
                    BizWindow bw 
    =   new
     BizWindow();
                    bw.commitUserAuth();
                    
    // 在用户向服务器发起请求返回成功后再显示首页面。

                     break ;
                
    case  EWLScreen.KEY_CODE_RIGHT_SOFT_KEY: //
     右软键
                    
    // 退出。

                    UIManager.state = UIManager.STATE_DEFAULE;
                    UIManager._flag 
    =   0
    ;
                    UIManager._instance.doLoop();
                    
    break
    ;
            }

        }

        
        
    protected   void  keyPressed( int  keyCode)  {
            
    // 处理初始化时的提示界面

             if (UIManager.state  ==  UIManager.STATE_LOGIN) {
                
    if ( ! connectAgain)
    {
                    stateLoginKeyPressed(keyCode);
                }
    else
    {
                    
    if (keyCode  ==   - 7   ||  keyCode  ==   - 22   ||  keyCode  ==   22
    )
                        UIManager._flag 
    =   0
    ;
                        UIManager._instance.doLoop();
                        
    return
    ;
                }

            }

            
    else   if (UIManager.state  ==  UIManager.STATE_LOGIN_httpConnecting) {
                
    // 只对返回键做处理

                 if (keyCode  ==   - 7   ||  keyCode  ==   - 22   ||  keyCode  ==   22 ) {
                    connectAgain 
    =   true
    ;
                    connectPrompt 
    =   true
    ;
                    UIManager.state
    =
    UIManager.STATE_LOGIN;
                    hidePopup();
                }

            }
    else   if (UIManager.state  ==  UIManager.STATE_DEFAULE) {
                
    try  
    {
                    
    if  (popupWindow  !=   null
    )
                        popupWindow.keyPressed(keyCode);
                    
    else   if  (activeWindow  !=   null
    )
                        activeWindow.keyPressed(keyCode);
                }
      catch  (Throwable e)  {
                    e.printStackTrace();
                }

            }

        }


        
    protected   void  keyReleased( int  keyCode)  {
            
    if (UIManager.state  ==  UIManager.STATE_LOGIN  ||

               UIManager.state 
    ==  UIManager.STATE_LOGIN_httpConnecting ) {
                
    return
    ;
            }

            
    try   {
                
    if  (popupWindow  !=   null
    )
                    popupWindow.keyReleased(keyCode);
                
    else   if  (activeWindow  !=   null
    )
                    activeWindow.keyReleased(keyCode);
            }
      catch  (Throwable e)  {
                e.printStackTrace();
            }

        }


        
    protected   void  keyRepeated( int  keyCode)  {
            
    if (UIManager.state  ==  UIManager.STATE_LOGIN  ||

               UIManager.state 
    ==  UIManager.STATE_LOGIN_httpConnecting ) {
                
    return
    ;
            }

            
    try   {
                
    if  (popupWindow  !=   null
    )
                    popupWindow.keyRepeated(keyCode);
                
    else   if  (activeWindow  !=   null
    )
                    activeWindow.keyRepeated(keyCode);
            }
      catch  (Throwable e)  {
                e.printStackTrace();
            }

        }


        
    /**
         * 笔触 点击
         * 
    @param  a_x: x 坐标
         * 
    @param
     a_y: y 坐标
         
    */

        
    protected   void  pointerPressed( int  a_x, int  a_y)
        
    {
            
    // 对九宫格界面处理

             if (UIManager._flag  ==   20 ) {
                
    boolean  clickFocus  =
     getFocusFromPointer( a_x, a_y);
                
    if (clickFocus)
    {
                    keyReleased(
    - 5
    );
                    
    return
    ;
                }
    else {
                    repaint();
                }

    //             return;
            }

            
    // 对左右软件处理
            String clickLRSoft  =  getFocusFromPointer_LRSoft( a_x, a_y);
            
    if ( ! clickLRSoft.equals( "" ))
    {
                
    if (clickLRSoft.equals( " LEFTSOFT " ))
    {
                    keyPressed(
    - 6
    );
                    keyReleased(
    - 6
    );
                }

                
    else   if (clickLRSoft.equals( " RIGHTSOFT " )) {
                    keyPressed(
    - 7
    );;
                    keyReleased(
    - 7
    );
                }

                
    return ;
            }

            
    // 对触摸屏对象处理
             if (UIManager._instance.i_clipArea  !=   null ) {
                
    boolean  browseClicpFocus  =
     browseClip(a_x, a_y);
                
    if (browseClicpFocus)
    {
                    keyPressed(
    - 5
    );;
                    keyReleased(
    - 5
    );
                }
    else {
                    repaint();
                }

            }

        }

        
        
    protected   void  pointerReleased( int  x,  int  y)
        
    {
            
    // 在pointerPressed中处理

        }

        
        
    /**
         * 笔触 拖拉
         * x : x 坐标
         * y : y 坐标
         
    */

        
    protected   void  pointerDragged( int  x, int  y)
        
    {
            
    // 暂未实现

        }

        
        
    /**
         * 列表界面的触摸屏判断
         * 
    @param  a_x
         * 
    @param
     a_y
         * 
    @return

         
    */

        
    protected   boolean  browseClip( int  a_x,  int  a_y) {
            
    boolean  clickAreaIsFocus  =   false
    ;
            Vector i_clipArea 
    =
     UIManager._instance.i_clipArea;
            
    if (i_clipArea == null
    )
                
    return   false
    ;
            ClipRegion a_clipRegion 
    =   null
    ;
            
    for  ( int  i  =   0 ; i  <  i_clipArea.size(); i ++
    {
                a_clipRegion 
    =
     (ClipRegion) i_clipArea.elementAt(i);
                
    boolean  findClipArea  =
     a_clipRegion.inClipRegion(a_x, a_y);
                
    if (findClipArea)
    { // 点击区域
                    clickAreaIsFocus  =  activeWindow.pointerPressSetFocus(a_x ,i);
                    
    break
    ;
                }

            }

            i_clipArea
    = null ;
            
    return
     clickAreaIsFocus;
        }

        
        
        
    /**
         * 通过x,y坐标,获得笔触的焦点值
         * 
    @param  a_x:笔触的x
         * 
    @param
     a_y:笔触的y
         * 
    @param
     focus_X:笔触所在九宫格的起始x
         * 
    @param
     focus_Y:笔触所在九宫格的起始y
         * 
    @return

         
    */

        
    protected   boolean  getFocusFromPointer( int  a_x,  int  a_y) {
            
    int  focus_X  =   0
    ;
            
    int  focus_Y  =   0
    ;
            
    boolean  clickAreaIsFocus  =   false
    ;
            
    for ( int  i = 0 ; i < 9 ; i ++
    )
            
    {
                focus_X 
    =  FirstPage.itemsPosition[i][ 0
    ];
                focus_Y 
    =  FirstPage.itemsPosition[i][ 1
    ];
                
                
    if (focus_X  <=  a_x  &&

                   focus_Y 
    <=  a_y  &&
                   focus_X 
    +  FirstPage.VSize  >=  a_x  &&
                   focus_Y 
    +  FirstPage.HSize  >=  a_y)
                
    { // 笔触所在的九宫格
                     if (i == FirstPage.currentItem)
                        clickAreaIsFocus 
    =   true
    ;
                    FirstPage.currentItem 
    =
     i;
                    
    break
    ;                
                }

            }

            
    return  clickAreaIsFocus;
            
        }

        
        
    /**
         * 通过x,y坐标,获得笔触的焦点值
         * 
    @param  a_x:笔触的x
         * 
    @param
     a_y:笔触的y
         * 
    @param
     focus_X:左、右软件的起始x
         * 
    @param
     focus_Y:左、右软件的起始y
         * 
    @return

         
    */

        
    protected  String getFocusFromPointer_LRSoft( int  a_x,  int  a_y) {
            
    int  focus_X  =   0
    ;
            
    int  focus_Y  =   0
    ;
            String pointSoftKey
    = ""
    ;
            
    for ( int  i = 0 ; i < 2 ; i ++
    )
            
    {
                focus_X 
    =  FirstPage.LRSoft_LeftAndTopPosition[i][ 0
    ];
                focus_Y 
    =  FirstPage.LRSoft_LeftAndTopPosition[i][ 1
    ];
                
                
    if (focus_X  <=  a_x  &&

                   focus_Y 
    <=  a_y  &&
                   focus_X 
    +  FirstPage.LRSoft_length_high[ 0 >=  a_x  &&
                   focus_Y 
    +  FirstPage.LRSoft_length_high[ 1 >=  a_y)
                
    { // 笔触所在的九宫格
                     if (i == 0 )
                        pointSoftKey
    = " LEFTSOFT "
    ;
                    
    else

                        pointSoftKey
    = " RIGHTSOFT " ;
                    
    break
    ;                
                }

            }

            
    return  pointSoftKey;
            
        }

        
    public   void  commandAction(Command c, Displayable d)  {
            
    try  
    {
                
    if  (d  ==   this
    )
                    
    if  (instance.popupWindow  !=   null
    )
                        instance.popupWindow.onCommand(c);
                    
    else   if  (instance.activeWindow  !=   null
    )
                        instance.activeWindow.onCommand(c);
            }
      catch  (Throwable e)  {
                e.printStackTrace();
            }

        }


        
    public   static  EWLWindow getTopWindow()  {
            
    if  (instance.popupWindow  !=   null
    )
                
    return
     instance.popupWindow;
            
    else

                
    return  instance.activeWindow;
        }


        
    public   static  EWLWindow getCurrent()  {
            
    return
     instance.activeWindow;
        }


        
    public   static   void  setCurrent(EWLWindow window)  {
            instance.activeWindow 
    =
     window;
            instance.repaint();
        }


        
    public   static  EWLWindow getPopup()  {
            
    return
     instance.popupWindow;
        }


        
    public   static   void  popup(EWLWindow window)  {
            instance.popupWindow 
    =
     window;
            instance.repaint();
        }


        
    public   static   void  hidePopup()  {
            
    if  (instance.popupWindow  instanceof
     BusinessWindow)
                IOManager._interrupt 
    =   true
    ;
            instance.popupWindow 
    =   null
    ;
            instance.repaint();
        }


        
    public   void  clearScreen()  {
            repaint();
            serviceRepaints();
        }


        
    /** *************************************************************************
         * 获取String屏幕宽度操作 开始 ***********************************************
         *************************************************************************
    */

        
    private   static   byte [] i_smallWidth  =   null ;
        
    private   static   byte [] i_mediumWidth  =   null
    ;
        
    private   static   byte [] i_largeWidth  =   null
    ;
        
    public   static   byte  getCharWidth(Font a_font,  char
     a_c)
        
    {
            initFontWidth();
            
    int  type  =
     a_font.getSize();
            
    byte
    [] widthType;
            
    if (type  ==
     Font.SIZE_SMALL)
                widthType 
    =
     i_smallWidth;
            
    else   if (type  ==
     Font.SIZE_MEDIUM)
                widthType 
    =
     i_mediumWidth;
            
    else   if (type  ==
     Font.SIZE_LARGE)
                widthType 
    =
     i_largeWidth;
            
    else

                widthType 
    =  i_smallWidth;
            
    if (a_c < 0   ||  a_c >= 128
    )
                
    return  widthType[ 128
    ];
            
    else

            
    {
                
    return
     widthType[a_c];
            }

        }

        
        
    /**
         * 获取字符的宽度
         * 
    @param  a_font
         * 
    @param
     a_str
         * 
    @return

         
    */

        
    public   static   int  getStringWidth(Font a_font, String a_str)
        
    {
            
    if (a_str  == null
    )
                
    return   0
    ;
            
    int  width  =   0
    ;
            
    char
     currChar;
            
    for ( int  i = 0 ;i < a_str.length();i ++
    )
            
    {
                currChar 
    =
     a_str.charAt(i);
                width 
    +=
     getCharWidth(a_font, currChar);
            }

            
    return  width;
        }

        
    private   static   void  initFontWidth()
        
    {
            
    if (i_smallWidth != null
    )
                
    return
    ;

            i_smallWidth 
    =   new   byte [ 129
    ];
            i_mediumWidth 
    =   new   byte [ 129
    ];
            i_largeWidth 
    =   new   byte [ 129
    ];

            Font i_fontSmall 
    =
     Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
            Font i_fontMedium 
    =
     Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
            Font i_fontLarge 
    =
     Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_LARGE);
            
    for ( int  i = 0 ;i < 128 ;i ++
    )
            
    {
                i_smallWidth[i] 
    =  ( byte )i_fontSmall.charWidth( (( char
    )i) );
                i_mediumWidth[i] 
    =  ( byte )i_fontMedium.charWidth( (( char
    )i) );
                i_largeWidth[i] 
    =  ( byte )i_fontLarge.charWidth( (( char
    )i) );
            }


            i_smallWidth[
    128 =  ( byte )i_fontSmall.charWidth(  ' '  );
            i_mediumWidth[
    128 =  ( byte )i_fontMedium.charWidth(  ' '
     );
            i_largeWidth[
    128 =  ( byte )i_fontLarge.charWidth(  ' '
     );
        }

        
    /** *************************************************************************
         * 获取String屏幕宽度操作结束************************************************
         *************************************************************************
    */

    }

    展开全文
  • 1:本程序在rockchip rk3026 android4的平台...3:本例使用的触摸屏分辨率为800x480,其它分辨率可修改kernel\drivers\input\touchscreen\touchit213.c里面的定义 #define REPORT_MAX_X 800 #define REPORT_MAX_Y 480
  • 相信大多数人对‘配方’并不陌生,因为有些非标自动化设备需要通过配方来上传和存储数据。...所有的功能都是通过按钮事件里的函数来实现的,这样就实现了西门子触摸屏的配方功能。配方命名函数如下:二、MCGS触摸...

    相信大多数人对‘配方’并不陌生,因为有些非标自动化设备需要通过配方来上传和存储数据。

    一、西门子触摸屏配方实现步骤

    1.通过调用函数来实现对配方的命名、创建、保存、加载等等。西门子配方画面如下:

    cc24f4461acda26b1a2bbbf300da9fae.png

    2.新建一个配方,添加数据记录,再添加元素,连接相应的变量。

    09e5aaeeee184521f76b31374e5aceb4.png

    3.新建画面,将需要的控件添加进去。所有的功能都是通过按钮事件里的函数来实现的,这样就实现了西门子触摸屏的配方功能。配方命名函数如下:

    d942b312a560cb88c8be71fd61b0f944.png

    二、MCGS触摸屏配方实现步骤

    MCGS昆仑通态触摸屏配方的实现方法和西门子触摸屏差不多,我做了一个简易的,如下图:

    1191c216b89ad94184d74c6741b8ed55.png

    1.新建变量

    2.添加用户策略,如下图:

    71f885af1beea4b7e2ed927e050633e0.png

    3.配方编辑属性如下图:

    74633ecb0e44ee5e579b5cb805c4495e.png

    4.在主画面按钮的操作属性里执行相对应的策略。如下图:

    766a30900dbd8bbdee9cffba6db96f95.png

    三、信捷触摸屏配方实现步骤

    看惯了用控件来实现配方功能,我们换一种思路,用脚本函数来实现。信捷触摸屏支持C脚本,配方画面如下:

    5177865b3ce914966cfcc0d9b6e2db72.png

    没有用任何触摸屏自带的控件,所有的功能都是通过C脚本来实现的,单击上升下降按钮就能对存储到触摸屏的配方数据进行查看。

    1.建立相应的变量,这一个配方的元素从‘配方名称’开始,到第14个的‘元素3’结束,一共104个单字,先通过编号对所有元素进行地址偏移,如下图:

    14a7da74a40a6782c6f4aab65b75f70a.png

    2.读取PFW290的值,存放到temp里,将temp1写入到PFW292里,就实现了配方地址的偏移。

    下载到PLC脚本如下图:

    dfc40aa1a50fcc1dc243be8b29661f72.png

    读取PFW300-PFW403即配方里的所有元素,写入到PLC对应的数据存储区。

    其实方法还有很多,我也只是介绍了一点皮毛,欢迎大家一起交流学习。

    展开全文
  • 触摸屏实现距离传感器的功能

    千次阅读 2014-01-23 20:10:06
    需求:某些客户为了节约成本吧,将距离传感器拿掉,相应的功能用TP触摸屏来模拟实现。流程图如下   移植原理:去掉手机上的感光Sensor,用TP来模拟实现感光sensor在通话时亮屏和灭屏的功能。 当然了TP本身是...

    需求:某些客户为了节约成本吧,将距离传感器拿掉,相应的功能用TP触摸屏来模拟实现。流程图如下
     

    移植原理:去掉手机上的感光Sensor,用TP来模拟实现感光sensor在通话时亮屏和灭屏的功能。
    当然了TP本身是需要支持相应的功能的。可以联系模组厂进行调试,导入firmware,然后才在代码中进行相应的修改。
    1. 首先在目录/sys/bus/i2c/devices下添加相应的I2C设备,在ProximitySensor.cpp中添加:
    //the below characters is the origin codes,modified to make the JNI work corretly
    #define ENALBE_PS_SENSOR  "/sys/bus/i2c/devices/i2c-2/2-0038/enable_ps_sensor"
     
    2. 在sensor.cpp中取代感光sensor
    修改原则是用模拟距离传感器的代码替换原先感光sensor的代码。
    在sensor列表中添加支持模拟距离传感器的模块代码,以敦太的ft5306为例。
    static const struct sensor_t sSensorList[] ={
    。。。 
     
    。。。};
    接下来是声明,替换感光sensor的相关部分。
     
     
     
    3. 加入编译选项,在Android.mk.3rdparty
         sensors.cpp  \
    4. 在tp驱动里加入代码
    先在代码里声明个宏开关吧
    #define TP_PROXIMITY_SENSOR
    在结构体中添加必要的成员变量
    struct pixcir_i2c_ts_data {
     struct i2c_client *client;
     struct input_dev *input;
     struct ts_event  event;
     //const struct pixcir_ts_platform_data *chip;
     bool exiting;
    #ifdef TP_PROXIMITY_SENSOR
     //struct mutex update_lock;
     //struct delayed_work dwork; /* for PS interrupt */
     struct input_dev *input_dev_ps;

     unsigned int enable;
     unsigned int control;

     /* control flag from HAL */
     unsigned int enable_ps_sensor;

     unsigned int ps_detection;  /* 0 = near-to-far; 1 = far-to-near */
     //unsigned int ps_data;   /* to store PS data */
    #endif
    };
    创建sysfs接口,用于hal层调用
    static DEVICE_ATTR(enable_ps_sensor, S_IWUGO | S_IRUGO,
           ft5306_show_enable_ps_sensor, ft5306_store_enable_ps_sensor);

    static struct attribute *ft5306_attributes[] = {
     &dev_attr_enable_ps_sensor.attr,
     NULL
    };
    当你想要实现的接口名字是enable_ps_sensor的时候,需要实现结构体struct attribute *dev_attrs[]
    其中成员变量的名字必须是&dev_attr_enable_ps_sensor.attr,然后再封装
    static const struct attribute_group ft5306_attr_group = {
     .attrs = ft5306_attributes,
    };
    最后就可以创建接口了,这个是在probe里面创建的哦
    #ifdef TP_PROXIMITY_SENSOR
     error = sysfs_create_group(&client->dev.kobj, &ft5306_attr_group); 
     if (error)
      input_unregister_device(ps_input);
    #endif
    这里只是建立了android到kernel的桥梁,真正实现对硬件操作的还是show和store两个函数。
    #ifdef TP_PROXIMITY_SENSOR
    static ssize_t ft5306_show_enable_ps_sensor(struct device *dev,
        struct device_attribute *attr, char *buf)
    {
     struct i2c_client *client = to_i2c_client(dev);
     struct pixcir_i2c_ts_data *data = i2c_get_clientdata(client);

     return sprintf(buf, "%d\n", data->enable_ps_sensor);
    }

    static ssize_t ft5306_store_enable_ps_sensor(struct device *dev,
        struct device_attribute *attr, const char *buf, size_t count)
    {
     struct i2c_client *client = to_i2c_client(dev);
     struct pixcir_i2c_ts_data *data = i2c_get_clientdata(client);
     
     unsigned long val = simple_strtoul(buf, NULL, 10);
      unsigned long flags;
     int err;
     char data_cmd[2]={0, 0};

     
     printk("%s: enable ps senosr ( %ld)\n", __func__, val);
     
     if ((val != 0) && (val != 1)) {
      printk("%s:store unvalid value=%ld\n", __func__, val);
      return count;
     }
     
     if(val == 1) {
      rgt_ps_mode = true;
      //turn on p sensor
      if (data->enable_ps_sensor==0) {
       data->enable_ps_sensor= 1;
       err = pixcir_i2c_write_data(0xB0, 0x01);

       if(err==0)
        printk("tp_ps: i2c write sucess, err:%d\n", err); 
       //}
       else
        printk("tp_ps: i2c write fail, err:%d\n", err);
      }
     } 
     else {
      //turn off p sensor - kk 25 Apr 2011 we can't turn off the entire sensor, the light sensor may be needed by HAL
      rgt_ps_mode=false;
      data->enable_ps_sensor = 0;
      err=pixcir_i2c_txdata(0xB0, 0x00);//out ps mode
      if(err==0)
      //{
       printk("tp_ps: i2c write sucess\n");
      //}
      else
       printk("tp_ps: i2c write fail\n");
     } 
     return count;
    }
    接下来在probe里各种添加了

    static int __devinit pixcir_i2c_ts_probe(struct i2c_client *client,
          const struct i2c_device_id *id)
    {
     //const struct pixcir_ts_platform_data *pdata = client->dev.platform_data;
     struct pixcir_i2c_ts_data *tsdata;
     struct input_dev *input;
     struct input_dev *ps_input;
     struct device *dev;
     struct i2c_dev *i2c_dev;
     int i, error;
     
     this_client = client;
     client->irq = pixcir_ts_config_pins(); //reset pin set to 0 or 1 and platform init
     
     for(i=0; i<MAX_FINGER_NUM*2; i++) {
      point_slot[i].active = 0;
     }

     tsdata = kzalloc(sizeof(*tsdata), GFP_KERNEL);
     input = input_allocate_device();
    #ifdef TP_PROXIMITY_SENSOR
     ps_input = input_allocate_device();
    #endif
     if (!tsdata || !input || !ps_input) {
      dev_err(&client->dev, "Failed to allocate driver data!\n");
      error = -ENOMEM;
      goto err_free_mem;
     }
    #ifdef TOUCH_VIRTUAL_KEYS
     pixcir_ts_virtual_keys_init();
    #endif

     tsdata->client = client;
     tsdata->input = input;
    #ifdef TP_PROXIMITY_SENSOR
     tsdata->input_dev_ps = ps_input;
    #endif
     //tsdata->chip = pdata;
     global_irq = client->irq;

     input->name = client->name;
     input->id.bustype = BUS_I2C;
     input->dev.parent = &client->dev;
    #ifdef TP_PROXIMITY_SENSOR
     ps_input->name = "FTPS";
     ps_input->id.bustype = BUS_I2C;
    #endif

     __set_bit(EV_KEY, input->evbit);
     __set_bit(EV_ABS, input->evbit);
     __set_bit(EV_SYN, input->evbit);
     __set_bit(BTN_TOUCH, input->keybit);
    #ifdef TP_PROXIMITY_SENSOR
     __set_bit(EV_ABS, ps_input->evbit);
    #endif
     __set_bit(ABS_MT_TOUCH_MAJOR, input->absbit);
     __set_bit(ABS_MT_POSITION_X, input->absbit);
     __set_bit(ABS_MT_POSITION_Y, input->absbit);
     __set_bit(ABS_MT_WIDTH_MAJOR, input->absbit);

     __set_bit(KEY_MENU,  input->keybit);
     __set_bit(KEY_BACK,  input->keybit);
     //__set_bit(KEY_HOME,  input->keybit);
     //__set_bit(KEY_SEARCH,  input->keybit);
     
     input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
     input_set_abs_params(input, ABS_MT_POSITION_X, 0, X_MAX, 0, 0);
     input_set_abs_params(input, ABS_MT_POSITION_Y, 0, Y_MAX, 0, 0);
     input_set_abs_params(input, ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0);
    #ifdef TP_PROXIMITY_SENSOR
     input_set_abs_params(ps_input, ABS_DISTANCE, 0, 1, 0, 0);
    #endif


     input_set_drvdata(input, tsdata);

     error = request_threaded_irq(client->irq, NULL, pixcir_ts_isr,
             IRQF_TRIGGER_FALLING,
             client->name, tsdata);
     if (error) {
      dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
      goto err_free_mem;
     }
     disable_irq_nosync(client->irq);

     error = input_register_device(input);
     if (error)
      goto err_free_irq;
     
    #ifdef TP_PROXIMITY_SENSOR
     error = input_register_device(ps_input);
     if (error)
      goto err_free_irq;
    #endif
     i2c_set_clientdata(client, tsdata);
     device_init_wakeup(&client->dev, 1);

     /*********************************Bee-0928-TOP****************************************/
     i2c_dev = get_free_i2c_dev(client->adapter);
     if (IS_ERR(i2c_dev)) {
      error = PTR_ERR(i2c_dev);
      return error;
     }

    //hong 找到了,上述说的就是在这里的。
    #ifdef TP_PROXIMITY_SENSOR
     error = sysfs_create_group(&client->dev.kobj, &ft5306_attr_group); 
     if (error)
      input_unregister_device(ps_input);
    #endif

     dev = device_create(i2c_dev_class, &client->adapter->dev, MKDEV(I2C_MAJOR,
       client->adapter->nr), NULL, "ft5206_ts%d", 0);
     if (IS_ERR(dev)) {
      error = PTR_ERR(dev);
      return error;
     }
     /*********************************Bee-0928-BOTTOM****************************************/

     pixcir_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
     pixcir_early_suspend.suspend = pixcir_ts_suspend;
     pixcir_early_suspend.resume = pixcir_ts_resume;
     register_early_suspend(&pixcir_early_suspend);

     if(pixcir_config_intmode()<0) {
    #ifdef PIXCIR_DEBUG
      printk("%s: I2C error\n",__func__);
    #endif
      goto err_free_irq;
     }
     pixcir_create_sysfs(client);

    #ifdef PIXCIR_DEBUG
     dev_err(&tsdata->client->dev, "insmod successfully!\n");
    #endif 
     enable_irq(client->irq);
     msleep(100);
     pixcir_i2c_write_data(0x80, 0x10);

    #if 0//def TP_PROXIMITY_SENSOR
     //struct ft5306_ps_data ps_data;
     int err;
     ps_data->enable = 0;
     ps_data->detection= 0;
     ps_data->enable_ps_sensor = 0;
     if(err = hwmsen_attach(ID_PROXIMITY, &tp_ps))
     {
      printk("tp_ps:attach fail = %d\n", err);
      //goto exit_create_attr_failed;
     }
     data->enable_ps_sensor = 0;
    #endif
     return 0;

    err_free_irq:
     free_irq(client->irq, tsdata);
     sprd_free_gpio_irq(pixcir_irq);
    err_free_mem:
     input_free_device(input);
     kfree(tsdata);
     return error;
    }


    中断read数据,打电话时模拟距离控制屏的休眠和唤醒
    static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
    {
     struct pixcir_i2c_ts_data *tsdata = dev_id;
     int ret;
     
     disable_irq_nosync(irq);

     ret = ft5x0x_read_data(tsdata); 
     if (ret == 0) { 
      ft5x0x_report_value(tsdata);
     }

     enable_irq(irq);
     
     return IRQ_HANDLED;
    }

    static int ft5x0x_read_data(struct pixcir_i2c_ts_data *data)
    {
    // struct pixcir_i2c_ts_data *data = i2c_get_clientdata(this_client);
     struct ts_event *event = &data->event;
    // u8 buf[14] = {0};
     u8 buf[32] = {0};
     int ret = -1;
     int touch_point = 0;
    //add detect function by liuhui 20120530. start
    #ifdef TP_PROXIMITY_SENSOR
     int err;
     u8 buf_ps[2] = {0};

     if(rgt_ps_mode == true)
     {
      err=pixcir_i2c_rxdata(&buf_ps, 2);
      if(err==1)
       printk("tp_ps: i2c read sucess\n");
      else
       printk("tp_ps: i2c read fail, err = %d\n", err);
      printk("tp_ps:ps data:%d\n", buf_ps[1]);
      if(buf_ps[1]==0xc0)//close
      {
       data->ps_detection = 1;
       input_report_abs(data->input_dev_ps, ABS_DISTANCE, 1);
       input_sync(data->input_dev_ps);
       return 0;
      }
      else if(buf_ps[1]==0xe0)//far away
      {
       data->ps_detection = 0;
       input_report_abs(data->input_dev_ps, ABS_DISTANCE, 0);
       input_sync(data->input_dev_ps);
       //return 0;
      }
     }
    #endif
    。。。

    suspend休眠
    static void pixcir_ts_suspend(struct early_suspend *handler)
    {
     if(rgt_ps_mode==true)
      return -1;
     disable_irq_nosync(global_irq);
        pixcir_ts_pwroff();
    }

    resume唤醒
    static void pixcir_ts_resume(struct early_suspend *handler)

     int ret = 0; 
     unsigned char reg_val[8] = {0};
     struct i2c_client *client = this_client;
     if(rgt_ps_mode==true)
      return -1;
     pixcir_ts_pwron();
     pixcir_reset();
     
     msleep(50);
     pixcir_i2c_write_data(0x80, 0x12);
     enable_irq(global_irq);

    到此,整个移植也算结束了。
    5.关于bug
        这个在调试的过程中还得和模组厂的FAE们,一起掌控TP的灵敏度,这个要多次反复的实验才行。
        做了很多专项测试,依照上面的代码来看,当打电话的时候离开人脸,有时会出现唤不醒屏幕的问题,手动唤醒后,GOD,TP居然失效了,
    这是难以接受的。这就是模拟的缺陷了,经过很多调试才避免了这种TP失效的发生,当然了偶尔还是出现自动唤不醒的情况。具体的优化,在
    下一章中会详细讲到,ps 解决这个bug,我搞了两天。。。
        事情到此结束了?有兴趣的话,可以考虑下为什么在pixcir_ts_resume中加入rgt_ps_mode==true的判断,当时偶也是很迷惑的。
        最终,还是有别的隐性bug的,但目前就优化到这里。可能在你看来还是有很多问题,不妨给点建议。

    ps:第一次在csdn上些东西,排版好难整啊。。

    展开全文
  • STM32 触摸屏触摸功能

    千次阅读 2019-10-16 22:36:21
    要用到触摸屏首先就要对触摸屏的原理有一定的了解,我想这个是前提,也不用太多说的。就是当触笔触到屏上时,对应的位置就会产生相应大小的电压,输入到芯片,AD转换后得到一个数据。而触摸校准就是将接受到的原始...

     要用到触摸屏首先就要对触摸屏的原理有一定的了解,我想这个是前提,也不用太多说的。就是当触笔触到屏上时,对应的位置就会产生相应大小的电压,输入到芯片,AD转换后得到一个数据。而触摸校准就是将接受到的原始模数转换值转换成屏幕像素坐标。

    再就是了解触摸芯片,知道他的工作方式,以及跟STM32的连线。触摸实验中,我的实验板是用SPI口来实现数据的传输的,即SPI与xpt2046相连。

    触摸屏控制芯片ADS7843中文资料

      ADS7843是一个内置12位模数转换、低导通电阻模拟开关的串行接口芯片。供电电压2.7~5 V,参考电压VREF为1 V~+VCC,转换电压的输入范围为0~ VREF,最高转换速率为125 kHz。

    ADS7843引脚图及引脚功能说明了:

     

    ADS7843的引脚配置如图3所示。表1为引脚功能说明,图4为典型应用。

     

    ADS7843典型应用电路

    ADS7843之所以能实现对触摸屏的控制,是因为其内部结构很容易实现电极电压的切换,并能进行快速A/D转换。图5所示为其内部结构,A2~A0和SER/为控制寄存器中的控制位,用来进行开关切换和参考电压的选择。

    ADS7843之所以能实现对触摸屏的控制,是因为其内部结构很容易实现电极电压的切换,并能进行快速A/D转换。图5所示为其内部结构,A2~A0和SER/为控制寄存器中的控制位,用来进行开关切换和参考电压的选择。

     

    我们传统的鼠标是一种相对定位系统,只和前一次鼠标的位置坐标有关。而触摸屏则是一种绝对坐标系统,要选哪就直接点哪,与相对定位系统有着本质的区别。绝对坐标系统的特点是每一次定位坐标与上一次定位坐标没有关系,每次触摸的数据通过校准转为屏幕上的坐标,不管在什么情况下,触摸屏这套坐标在同一点的输出数据是稳定的。不过由于技术原理的原因,并不能保证同一点触摸每一次采样数据相同,不能保证绝对坐标定位,点不准,这就是触摸屏最怕出现的问题:漂移。对于性能质量好的触摸屏来说,漂移的情况出现并不是很严重。

    所以很多应用触摸屏的系统启动后,进入应用程序前,先要执行校准程序。  通常应用程序中使用的LCD 坐标是以像素为单位的。比如说:左上角的坐标是一组非 0 的数值,比如(20,20),而右下角的坐标为(220,300)。这些点的坐标都是以像素为单位的,而从触摸屏中读出的是点的物理坐标,其坐标轴的方向、XY 值的比例因子、偏移量都与 LCD 坐标不同,所以,可以在程序中使用一个函数(我们采用 Convert_Pos 函数)中把物理坐标首先转换为像素坐标,然后再赋给 POS 结构,达到坐标转换的目的。

    校正思路:在了解了校正原理之后,我们可以得出下面的一个从物理坐标到像素坐标的转换关系式:

                                                    LCDx=xfac*Px+xoff;

                                                    LCDy=yfac*Py+yoff;

    其中(LCDx,LCDy)是在 LCD 上的像素坐标,(Px,Py)是从触摸屏读到的物理坐标。xfac,yfac 分别是 X 轴方向和 Y 轴方向的比例因子,而 xoff 和 yoff 则是这两个方向的偏移量。

    这样我们只要事先在屏幕上面显示 4 个点(这四个点的坐标是已知的),分别按这四个点就可以从触摸屏读到 4 个物理坐标,这样就可以通过待定系数法求出 xfac、yfac、xoff、yoff 这四个参数。我们保存好这四个参数,在以后的使用中,我们把所有得到的物理坐标都按照这个关系式来计算,得到的就是准确的屏幕坐标。达到了触摸屏校准的目的。

    以下是自己的校准程序(在正点原子上做了一些改变,没有用到中断):

    //触摸屏校准代码
    //得到四个校准参数

    void Touch_Adjust(void)
    {        
     u16 pos_temp[4][2];//坐标缓存值
     u8  cnt=0; 
     u16 d1,d2;
     u32 tem1,tem2;
     float fac;    
     cnt=0;    
     TextColor=Blue;
     BackColor =White;      //TextColor = 0x0000, BackColor = 0xFFFF;
     LCD_Clear(White);//清屏  
    // POINT_COLOR=RED;//红色
    // LCD_Clear(WHITE);//清屏
     Drow_Touch_Point(20,20);//画点1
     delay_ms(1000);
    // Pen_Point.Key_Sta=Key_Up;//消除触发信号
    // Pen_Point.xfac=0;//xfac用来标记是否校准过,所以校准之前必须清掉!以免错误 
     while(1)
     {
      if(Read_ADS2(&x,&y))//按键按下了
      {
       //if(Read_TP_Once())//得到单次按键值
      // {            
        pos_temp[cnt][0]=x;
        pos_temp[cnt][1]=y;
        cnt++;
        delay_ms(100);
      // }   
       switch(cnt)
       {     
        case 1:
         LCD_Clear(White);//清屏
         delay_ms(1000);
         Drow_Touch_Point(20,300);//画点2
         break;
        case 2:
         LCD_Clear(White);//清屏
         delay_ms(1000);
         Drow_Touch_Point(220,20);//画点3
         break;
        case 3:
         LCD_Clear(White);//清屏
         delay_ms(1000);
         Drow_Touch_Point(220,300);//画点4
         break;
        case 4:  //全部四个点已经得到
               //对边相等
         tem1=abs(pos_temp[0][0]-pos_temp[1][0]);//x1-x2
         tem2=abs(pos_temp[0][1]-pos_temp[1][1]);//y1-y2
         tem1*=tem1;
         tem2*=tem2;
         d1=sqrt(tem1+tem2);//得到1,2的距离
         
         tem1=abs(pos_temp[2][0]-pos_temp[3][0]);//x3-x4
         tem2=abs(pos_temp[2][1]-pos_temp[3][1]);//y3-y4
         tem1*=tem1;
         tem2*=tem2;
         d2=sqrt(tem1+tem2);//得到3,4的距离
         fac=(float)d1/d2;
         if(fac<0.95||fac>1.05||d1==0||d2==0)//不合格
         {
          cnt=0;
          LCD_Clear(White);//清屏
          Drow_Touch_Point(20,20);
          continue;
         }
         tem1=abs(pos_temp[0][0]-pos_temp[2][0]);//x1-x3
         tem2=abs(pos_temp[0][1]-pos_temp[2][1]);//y1-y3
         tem1*=tem1;
         tem2*=tem2;
         d1=sqrt(tem1+tem2);//得到1,3的距离
         
         tem1=abs(pos_temp[1][0]-pos_temp[3][0]);//x2-x4
         tem2=abs(pos_temp[1][1]-pos_temp[3][1]);//y2-y4
         tem1*=tem1;
         tem2*=tem2;
         d2=sqrt(tem1+tem2);//得到2,4的距离
         fac=(float)d1/d2;
         if(fac<0.95||fac>1.05)//不合格
         {
          cnt=0;
          LCD_Clear(White);//清屏
          Drow_Touch_Point(20,20);
          continue;
         }//正确了
              
         //对角线相等
         tem1=abs(pos_temp[1][0]-pos_temp[2][0]);//x1-x3
         tem2=abs(pos_temp[1][1]-pos_temp[2][1]);//y1-y3
         tem1*=tem1;
         tem2*=tem2;
         d1=sqrt(tem1+tem2);//得到1,4的距离
     
         tem1=abs(pos_temp[0][0]-pos_temp[3][0]);//x2-x4
         tem2=abs(pos_temp[0][1]-pos_temp[3][1]);//y2-y4
         tem1*=tem1;
         tem2*=tem2;
         d2=sqrt(tem1+tem2);//得到2,3的距离
         fac=(float)d1/d2;
         if(fac<0.95||fac>1.05)//不合格
         {
          cnt=0;
          LCD_Clear(White);//清屏
          Drow_Touch_Point(20,20);
          continue;
         }//正确了
         //计算结果
         x1=pos_temp[0][0];
         x2=pos_temp[1][0];
         x3=pos_temp[2][0];
         x4=pos_temp[3][0];
         y1=pos_temp[0][1];
         y2=pos_temp[1][1];
         y3=pos_temp[2][1];
         y4=pos_temp[3][1];
         TextColor=Blue;
         LCD_Clear(White);//清屏
         ili9320_PutChars(120,120,"Touch Screen Adjust OK!",23,TextColor,BackColor);//校正完成
         delay_ms(1000);
         LCD_Clear(Blue);//清屏  
         return;//校正完成    
       }
      }
     }

    我的算法,跟正点原子不同,他的我没有理解。

    以下是带清屏的程序:

     while (1)
        {
      if(Read_ADS2(&X,&Y))
         {
       zuobiaox=20+(s32)(X-x1)*200/(x3-x1);
         zuobiaoy=20+(s32)(Y-y1)*280/(y2-y1);
       if(zuobiaox>0&&zuobiaox<20&&zuobiaoy>0&&zuobiaoy<40)
       {
        LCD_Clear(Blue);//清屏
        LCD_DrawRectFill(0, 0, 20, 40,Yellow);
        ili9320_PutChars(0,0,"RST",3,Red,Yellow); 
       }          
       else if(zuobiaox>0&&zuobiaox<240&&zuobiaoy>0&&zuobiaoy<320)
         lcd_fill_circle(zuobiaox,zuobiaoy, Red);
         }
     }

    ----------------------
        |  +  (x1,y1)    + | (x2,y2)
        |                    |
        |  +   (x3,y3)     + | (x4,y4)
        ----------------------

    触摸屏校准


    上图理解为触摸屏,应为实际应用中触摸屏边角出电压相对不稳定,所以放弃一部分,四个点分别为(20,20)(20,300)(220,20)(220,300),对应的AD值分别设为(x1,y1)(x2,y2)(x3,y3)(x4,y4).
          首先:在LCD上绘制四个对应的“+”用来取较准点;

    其次:点四个“+”,得到各点的AD值,由于其中的电阻是线性的,可以根据x轴上两点的x的AD值如x1,x3以及对应LCD坐标值求出x轴上x的AD值与LCD坐标值对应的关系,是一条直线的方程,再根据此方程由AD值求LCD坐标值即可;y轴上也是一样的道理。
          最后:计算  (注:触摸屏电压最小点,为LCD显示坐标最大点,(X,Y)为触摸电压)

    zuobiaox=20+(s32)(X-x1)*200/(x3-x1);


    zuobiaoy=20+(s32)(Y-y1)*280/(y2-y1);


    -------------------------

    →_→在校准函数中,不断扫描TP_Scan()函数,如果这时候你触摸了一下屏幕,PEN所对应STM32的引脚将会从高电平跳变为低电平,详情看上文第二讲的注意→_→。即Ttp_dev.sta=1100,0000(根据上图第一个方框得出)。不满足校准函数中的if((tp_dev.sta&0xc0)==TP_CATH_PRES),故不会进行下面的画点。如果之前并没有按下触摸屏,这时同样是不满足上面if的。如果之前按下后松下了,这时Ttp_dev.sta=0111,1111,这时满足校准函数中的if((tp_dev.sta&0xc0)==TP_CATH_PRES),然后在校准函数中标记下触摸已经被处理了(清除tp_dev.sta),清除第一个点,画第二个点,清除第二个点,画第三个点,清除第三个点,画第四个点,清除第四个点。也就是,触摸屏幕有两个状态:按下和松开。当按下时,程序执行的是将按下的AD值坐标存到两个数组中即上图中的TP_Read_XY2(&tp_dev.x[0],&tp_dev.y[0]);当松开时,清除原来的点,并画一个新点。这样触摸4次。

    在校准函数中,由于之前重复触摸了4下屏幕,触摸的4个点的AD值被存入到了pos_temp[4][2]数组中,然后算出(x1,y1),
    (x2,y2)之间的距离d1和(x3,y3),(x4,y4)之间的距离d2,把这两个水平距离相除得到一个比值fac1;再计算出(x1,y1),(x3,y3)之间的距离d3和(x2,y2),(x4,y4)之间的距离d4,把这两竖直方向的距离相除,得到一个比值fac2.如果0.95<fac1<1.05且0.95<fac2<1.05则认为校准成功。否则显示触摸的AD值,不断校正。如果校准成功,就计算AD值与实际坐标之间的校准参数,并将这些校准参数存到EEPROM(断点可保存数据)中。每次重新上电系统初始化后再读出来。

    xfac、yfac:每个AD点对应的像素点数目。(液晶理论宽度-40)/(x2-x1) 即液晶理论宽度点阵值/AD测量值

    xoff、yoff:测量误差值。[液晶理论宽度点阵值 - 每AD值对应多少点阵*(AD测量值)]/2 = 测量误差值(理论值为 20 点阵,实际是有误差的)
    ————————————————
     

    展开全文
  • Smart 700 IE V3 触摸屏的数据记录功能实现 在做数据记录之前,我们要知道,该触摸屏不带存储卡,但是,数据记录可存储到U盘上。 一、从项目里面找到“数据记录” 二、添加新的 “数据记录”,给各项内容选择合适的...
  • stm32f4实现s6d1121+xtp2046触摸屏功能

    千次阅读 2013-09-23 14:34:24
    经过折腾液晶成功后,接下来实现触摸屏功能! 原理什么的就不多说,工程也是别人的。直接针对这块屏,说下接线! 这份是s6d1121的引脚图,其中以D_开头的引脚是用来实现触摸功能的! 其中,D_BUSY在实体屏上标记...
  • 触摸屏锁屏(Touch Lock)功能实现

    千次阅读 2009-08-01 12:47:00
    触摸屏锁屏(Touch Lock)功能实现--作者:赖玉平(Auly)aulyp@163.com 1、关闭TOUCH 对应...一直等到请求解锁命令后才重新将中断打开,恢复触摸屏功能。 应用程序通知底层驱动的流程为:在MDD中有个线程,在等待锁屏
  • 触摸屏是成熟的技术,基本、也是常用的是4/5线电阻触摸屏。很多标准屏支持多种尺寸,可以选择多种解码模拟解决方案。电阻触摸屏支持多种输入方法,比如手指、触摸笔、手套和指甲等等。电容触摸屏比较适合手指的输入...
  • 3/24触屏键盘的功能实现 键盘的显示 按钮结构体的建立 是采用建立一个结构体,里面包含了该按键的x,y,坐标,长度high,宽度width,以及改按键完成的时间handle,还有按钮的名字title; typedef struct Event { int...
  • 在双屏异显产品中,有时候主副屏都带有触摸屏,并且要求主副屏触摸各自操作互不干扰。 Android 现有框架中已经支持副输入设备的逻辑,只是默认将所有的外部热插拔设备统一指定为副输入设备,这种逻辑我们如果是一个...
  • Slip.js 是一个很小的 JavaScript 库,用于实现触摸屏的互动 Swipe 和对元素重新排序列表(Reordering)。Slip.js没有任何的依赖,你可以通过自定义 DOM 事件实现重新排序交互。 您可能感兴趣的相关文章 ...
  • 触摸屏按压状态返回”与普通的“基本触控”的主要区别在于,它除了可以实现基本触控的功能(按键效果,页面切换)外,还可以判断触摸的状态。一次触摸操作一共包含3个状态:按下,持续按压,抬起。这三个阶段结合...
  • microPython中实现Modbus通信支持各类触摸屏功能码有0x01\0x02\0x03\0x04\0x05\0x06等功能码
  • 触摸屏驱动——platform机制剖析 /*  *硬件平台:韦东山嵌入式Linxu开发板(S3C2440.v3)  *软件平台:运行于VMware Workstation 12 Player下UbuntuLTS16.04_x64 系统  *参考资料:《嵌入式Linux应用...
  • 触摸屏是成熟的技术,最基本、也是最常用的是4/5线电阻触摸屏。很多标准屏支持多种尺寸,可以选择多种解码模拟解决方案。电阻触摸屏支持多种输入方法,比如手指、触摸笔、手套和指甲等等。电容触摸屏比较适合手指的...
  • 本驱动实现了FreescaleImx515平台下的AK4182A 触摸屏采样功能。通过在WINDOWS CE平台上按照WINDOWS CE TOUCH DDSI 接口标准完成了所有的12 bit精度的数据采样功能。 该驱动实现了一个标准的WINDOWS CE 触摸屏驱动,...
  • 简单的说,有一块触摸屏,安装到电脑上,我们想在这块触摸屏上运行虚拟键盘软件,当键盘用,目前触摸屏驱动和虚拟键盘程序都是现成的,问题是怎么能让这个虚拟键盘程序运行或者说只显示在触摸屏上,可不可以把虚拟...
  • 触摸屏技术消除了对键盘或传统鼠标的需求,而是可通过代表特定任务的图标实现简单、直接的交互。在工业应用中,触摸屏的这个特性有助于现场操作人员把精力集中在应用上,并且大多数操作者都能正确地使用触摸屏,而...
  • Tabletpro 虚拟鼠标触控板 可以实现触摸屏多点触控事件,里面还有各种参数可以设置满足自己的开放需求。
  • 同时,我在开发超声程序的时候,也遇到类似的问题,在之前多屏幕管理一文中,提到超声会有一个触摸屏,QDialog弹出情况下,触摸屏也无法点击了。 目前我们采用的解决方案是,实现一个自定义的对话框LDialog,它具有...
  • 触摸屏代码分析——实现滑动功能

    千次阅读 2012-07-09 18:33:22
    前面提到过,我们可以通过定时器来实现滑动的功能。我们再来啰嗦一遍原理:设置定时器,在定时器处理函数中开启AD转换,可以得到坐标的实时值。先来看代码: #include #include #include #include #...
  • *@ Gesture (上文)触摸屏手势识别 */ public class MySurfaceViewAnimation extends SurfaceView implements Callback, Runnable, OnGestureListener, OnTouchListener { private Thread th = new Thread(this...
  • 如何实现用户触摸屏幕就隐藏弹出的键盘功能
  • 目的:记录在屏幕上滑动的轨迹,实现在图片上涂鸦的功能 开发工具:Android Studio3.3.2 实现过程: 第一步:新建drawBoard.java用于自定义view 将图片放到drawable文件夹下,用BitmapFactory.decodeResource...
  • 触摸屏与PLC联合使用时,触摸屏的主要功能是:  ①显示PLC输入,输出端13或辅助继电器的开关状态。  ②用触摸按键强制PLC输入,输出端口或辅助继电器的开/关。  ③显示PLC中定时器、计数器和数据寄存器的内容...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,565
精华内容 626
关键字:

触摸屏功能实现