随笔-10  评论-11  文章-20  trackbacks-0
  2011年4月17日
使用w3m上网方法:
   
   第一步,需要安装一个名为w3m的软件工具,打开终端,输入如下命令

  sudo apt-get install w3m w3m-img -y

  第二步,安装好w3m之后,在终端里面启动w3m,打开一个网址,比如w3m www.baidu.com 。现在是不是看到了只有在浏览器下面才能看到的百度首页呢?

  如果您的终端不显示中文请。安装zhcon。安装命令:

  sudo apt-get install zhcon -y

  好了,下面给出w3m的相关帮助文件。

  与vim常用命令vim常用命令集相似,h,j,k,l 可以分别用来做移动键,分别是左,下,上,右。如果你熟习vim操作的话这会是很方便的功能。 < 和 > 用来左右滚屏。

  按q就会提示你退出!

  在需要输入的文本框内按回车,下面就会出现TEXT: ,这时你可以输入你要搜索的文字。再按回车就是返回给文本框。这时再把光标移到”百度搜索”的那个按键,回车,就可以开始搜索了!

  使用 U 来重新输入需要打开的网址。

  B 返回前一个页面。

  多标签操作!

  可以使用 T 按键来打开一个新标签。

  在多个标签内切换呢? 使用 { 和 }就可以了!

  使用 ESC-t 的话会打开标签的菜单让你选择,功能类似系统中的alt-tab功能。

  C-q用于关于当前标签页。

  书签

  C-a 添加书签

  C-b 查看书签

  查找

  / 向后查找当前页面

  ? 向前查找当前页面

  n 查找下一个已查找过的关键字

  N 向前查找已查找过的关键字

  帮助

  H 以上的选项在这里都可以看到!
posted @ 2011-09-23 17:00 Soap MacTavish 阅读(10352) | 评论 (1)编辑 收藏
   在使用SWT构建应用程序时,理解系统底层读取和调度平台GUI事件的线程模型是非常重要的,UI线程的实现方式会影响到在应用程序中使用 Java 线程时必须遵守的规则。

 

本地事件调度

        对于任何的GUI应用程序,不管所使用的是哪一种编程语言和UI工具包,背后的运行机制都是操作系统探测GUI事件并把它们放到应用程序的事件队列中去。这种机制在不同的操作系统平台中大同小异。当用户点击鼠标、键入字符、或者使窗口获得焦点,操作系统就会生成应用程序的GUI事件,例如鼠标点击、键盘输入、或窗口重绘事件。操作系统决定哪一个窗口和应用程序应该接收用户触发的每一个事件并把它放入应用程序的事件队列中。

 

        任何基于窗口的GUI应用程序的底层实现结构都是一个事件循环(event loop),应用程序初始化并运行一个循环(loop),用于从事件队列中读取GUI事件,并作出相应的反应。处理事件的工作必须迅速完成,以保证GUI应用程序能够对用户作出快速反应。

 

        UI事件触发的耗时较长的操作应该在一个单独的线程中执行,这样才能让事件循环主线程能够快速返回,获取应用程序事件队列中的下一个事件。但是,在非UI线程中访问图形界面部件和平台API 必须通过锁和串行化的机制(locking and serialization)来实现。违反这个规则的应用程序会引起系统调用失败,更严重的是锁住整个GUI系统,使GUI失去反应。

 

SWT UI 线程

        SWT 遵循系统平台所直接支持的这种线程模型,应用程序在它的主线程中运行事件循环(event loop),并在主线程中直接调度线程。UI线程就是Display 对象被创建的线程,所有其他的图形部件都必须在这个UI线程中创建。

        既然所有的处理事件的代码是在应用程序的UI线程中触发的,那么处理事件的程序代码就能够不需要任何特殊方法自由访问和调用图形部件。不过,在处理长耗时的事件操作时,需要使用多线程来实现应用程序的功能。

 

注:在非UI线程中调用任何必须在UI线程调用的程序,SWT将会触发一个 SWTException 异常。

 

SWT 应用程序的主线程,包括事件循环,其代码结构如下:

Java代码 复制代码 收藏代码
  1. public static void main (String [] args) {   
  2.    Display display = new Display ();   
  3.    Shell shell = new Shell (display);   
  4.    shell.open ();   
  5.    // start the event loop. We stop when the user has done   
  6.    // something to dispose our window.   
  7.    while (!shell.isDisposed ()) {   
  8.       if (!display.readAndDispatch ())   
  9.          display.sleep ();   
  10.    }   
  11.    display.dispose ();   
  12. }  

        创建图形部件和打开shell 窗口之后,程序读取和分发来自操作系统事件队列的事件,直到shell 窗口被销毁。如果在队列中不存在有效事件,display 进入睡眠状态,把运行机会交给其他程序。

 

        SWT 提供了在后台主线程中调用图形部件代码的访问方法。

 

运行非UI线程

         在非UI 线程中不能直接调用UI 代码,必须提供一个 Runnable对象,在Runable中调用UI代码。Display 类中的syncExec(Runnable) 和 asyncExec(Runnable) 方法用于在事件循环运行期间,在UI 线程中运行这些Runnable对象。

  • syncExec(Runnable)  当非UI 线程中的程序代码依赖于UI 代码的返回值,或者为了确保在返回到主线程之前Runnable 必须执行完成时,应该使用这个方法。SWT 将会阻塞调用线程,直到在应用程序的UI 线程中运行的这个Runnable运行结束为止。例如,一个后台线程需要基于一个窗口的当前尺寸进行某种计算,就会需要同步地运行获取窗口尺寸的代码,然后继续其后面的计算。
  • asyncExec(Runnable)  当程序需要执行一些UI 操作,但在继续执行之前不依赖这些操作必须完成的时候,应该使用这个方法。例如,后台主线程更新进度条,或者重绘一个窗口,它可以异步地发出更新或重绘的请求,并接着继续后面的处理,在这种情况下,后台主线线程的运行时间和Runnable的运行没有必然的关系。
下面的代码片段演示了使用这两个方法的方式:
Java代码 复制代码 收藏代码
  1. // do time-intensive computations   
  2. ...   
  3. // now update the UI. We don't depend on the result,   
  4. // so use async.   
  5. display.asyncExec (new Runnable () {   
  6.    public void run () {   
  7.       if (!myWindow.isDisposed())   
  8.          myWindow.redraw ();   
  9.    }   
  10. });   
  11. // now do more computations   
  12. ...  
        在使用asyncExec 的时候,在runnable 中检查图形部件是否被销毁是一个好的习惯做法,在调用asyncExec和Runnable执行期间主线程中有可能会发生其他的事情,不能保证runnable执行时图形部件当前处于什么状态。

工作台(Workbench)和多线程

        实现SWT应用程序的多线程规则非常明确,你可以控制事件循环的初始化,在应用程序中使用多线程解决复杂问题。

 

        向工作台添加插件时的工作机制要父子一些,下面是使用平台(workbench platform)UI 类的一些“规约”(Rules of engagement),随着eclipse 的不断发布,可能会出现一些例外:

  • 通常,任何添加到平台中的工作台(workbench) UI 扩展都是在工作台的UI 主线程中执行的,除非是明确地把它们添加线程中或者是后台作业(background job)中,例如后台作业进度条。
  • 如果从工作台接收到一个事件,不能保证它是在UI线程中执行的,查阅定义了监听器或事件的类的java文档,如果没有特别说明使用线程,这个类就是一个UI 相关类,可以在工作台主线程中获得和运行。
  • 同样,除非是文档明确说明,平台UI库不能视作是线程安全的。请注意,大部分平台UI类是在触发事件的调用线程中运行监听器的,平台和JFace API调用并不检查是在UI 线程中执行的,这意味着如果在非UI 线程中调用一个能够触发事件的方法,可能会引入问题。从非UI 线程中调用SWT的API,SWT会抛出 SWTException 异常。通常,除非文档中明确规定,避免在别的线程中调用平台UI 代码。
  • 如果你的插件使用多线程或工作台作业(workbench job),必须使用 Display 类的asyncExec(Runnable) 或 syncExec(Runnable) 方法,类调用任何的工作台(workbench)、JFace或SWT 的应用程序接口(API),除非是API明确说明是可以直接调用的。
  • 如果在插件中使用 JFace的IRunnableContext 接口 调用进度监视器(progress monitor),以运行一个操作,IRunnableContext 提供了一个参数来确定是不是在一个新的线程中运行操作。
附:
参考:http://help.eclipse.org/helios/index.jsp?topic=/org.eclipse.platform.doc.isv/guide/swt_threading.htm
posted @ 2011-04-17 21:58 Soap MacTavish 阅读(1476) | 评论 (0)编辑 收藏
一.概述
如果你是SWT/Jface的初学者,那么本片所描述的问题很可能是你已经碰到或者将要碰到的。
这是关于多线程开辟的问题,比较常见。

二.问题:
当你在GUI主线程开辟一个新线程,进行其它操作,并且需要更新UI控件,意外发
生了:
Exception in thread "Thread-1" java.lang.NullPointerException。

三。解决方案
使用:Display#asyncExec(Runnable)或者Display#syncExec(Runnable)。
把你的UI更新操作另开一个线程,比如:
Display.getCurrent().asyncExec(new Runnable() {
    public void run() {
        button.setText("update");
    }
};


如果其它数据处理操作耗时不长,可以把这部分代码放入到与UI更新同一个线程,
Display.getCurrent().asyncExec(new Runnable() {
    public void run() {
        //Do business action
        button.setText("update");
    }
};

如果其它数据处理耗时长,那么为了不让UI响应迟钝,应该把逻辑操作和UI更新分开:
Thread t = new Thread(new Runnable() {
    public void run() {
        //Do business action
        Display.getCurrent().asyncExec(new Runnable() {
            public void run() {
                button.setText("update");
            }
        };
       
    }

}
posted @ 2011-04-17 21:57 Soap MacTavish 阅读(406) | 评论 (0)编辑 收藏

要在后台线程里对前台界面组件进行访问.

解决方法是使用Display对象,Display对象主要负责管理事件循环和控制UI线程和其它线程之间的通信.
Display.getDefault().asyncExec(new Runnable(){
    public void run(){
    //对前台界面进行操作
    }
});
  1. package com.tr069im.ui;  
  2.  
  3. import org.eclipse.swt.SWT;  
  4. import org.eclipse.swt.layout.GridData;  
  5. import org.eclipse.swt.widgets.Button;  
  6. import org.eclipse.swt.widgets.Display;  
  7. import org.eclipse.swt.widgets.MessageBox;  
  8. import org.eclipse.swt.widgets.ProgressBar;  
  9. import org.eclipse.swt.widgets.Shell;  
  10.  
  11. /**  
  12.  * 此类通过实现SWT滚动条,说明多线程问题 .解决了后台线程访问前台界面的问题   
  13.  * @author llwbrothers  
  14.  */ 
  15. public class Login implements Runnable {  
  16.     private static Shell shell;  
  17.     private String loginResponse = "right";  
  18.     private static boolean flag = false;  
  19.  
  20.     public Login() {  
  21.  
  22.     }  
  23.  
  24.     public static void main(String[] args) {  
  25.           
  26.         final Display display = Display.getDefault();  
  27.         shell = new Shell(SWT.MIN);  
  28.         shell.setSize(290520);  
  29.         shell.setLocation(3005);  
  30.         shell.setText("SWT多线程");  
  31.  
  32.         // 添加平滑的进度条  
  33.         final ProgressBar pb1 = new ProgressBar(shell, SWT.HORIZONTAL  
  34.                 | SWT.SMOOTH);  
  35.         pb1.setBounds(7228216020);  
  36.         pb1.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));  
  37.         // 显示进度条的最小值  
  38.         pb1.setMinimum(0);  
  39.         // 设置进度条的最大值  
  40.         pb1.setMaximum(30);  
  41.  
  42.         // 登录按钮  
  43.         final Button btnLogin = new Button(shell, SWT.FLAT | SWT.PUSH);  
  44.         btnLogin.setBounds(8036311136);  
  45.         btnLogin.setText("取消");  
  46.  
  47.         shell.open();  
  48.         // 异步线程处理其他数据  
  49.         display.asyncExec(new Runnable() {  
  50.             public void run() {  
  51.                 Login pl = new Login();  
  52.                 Thread t = new Thread(pl);  
  53.                 t.start();  
  54.             }  
  55.         });  
  56.         // 添加线程,在线程中处理长时间的任务,并最终反映在平滑进度条上  
  57.         Runnable runnable = new Runnable() {  
  58.             public void run() {  
  59.                 for (int i = 0; i < 30; i++) {  
  60.                     try {  
  61.                         Thread.sleep(100);  
  62.                     } catch (InterruptedException e) {  
  63.                     }  
  64.                     display.asyncExec(new Runnable() {  
  65.                         public void run() {  
  66.                             if (pb1.isDisposed())  
  67.                                 return;  
  68.                             // 进度条递增  
  69.                             pb1.setSelection(pb1.getSelection() + 1);  
  70.                         }  
  71.                     });  
  72.                     if (flag) { // 作为标志,使滚动条起作用  
  73.                         break;  
  74.                     }  
  75.                     if (i == 29) {  
  76.                         open();  
  77.                     }  
  78.                 }  
  79.             }  
  80.         };// 启动这个线程  
  81.         new Thread(runnable).start();  
  82.  
  83.         while (!shell.isDisposed()) { // 如果主窗体没有关闭  
  84.             if (!display.readAndDispatch()) { // 如果display不忙  
  85.                 display.sleep(); // 休眠  
  86.             }  
  87.         }  
  88.         display.dispose(); // 销毁display  
  89.     }  
  90.  
  91.     public void run() {  
  92.         try {  
  93.             // 收到验证信息后进行  
  94.             if (loginResponse.equals("right")) {  
  95.                 // 后台线程访问前台界面  
  96.                 Display.getDefault().asyncExec(new Runnable() {  
  97.                     public void run() {  
  98.                         flag = true;  
  99.                         Shell shell = new Shell(SWT.MIN);  
  100.                         MessageBox messageBox = new MessageBox(shell,  
  101.                                 SWT.ICON_WARNING);  
  102.                         messageBox.setMessage("用户名或密码错误!");  
  103.                         messageBox.open();  
  104.                     }  
  105.                 });  
  106.  
  107.             } else {      
  108.             }  
  109.         } catch (Exception ee) {  
  110.         }  
  111.     }  
  112.  
  113.     public static void open() {  
  114.         Display.getDefault().asyncExec(new Runnable() {  
  115.             public void run() {  
  116.                 // 进度条进行完之后,执行的程序  
  117.             }  
  118.         });  
  119.     }  
  120. }  
posted @ 2011-04-17 21:57 Soap MacTavish 阅读(1446) | 评论 (0)编辑 收藏