春风博客

春天里,百花香...

导航

<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

统计

公告

MAIL: junglesong@gmail.com
MSN: junglesong_5@hotmail.com

Locations of visitors to this page

常用链接

留言簿(11)

随笔分类(224)

随笔档案(126)

个人软件下载

我的其它博客

我的邻居们

最新随笔

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜

#

在C# WinForm程序中创建控件数组及相应的事件处理

     摘要: 控件数组是VB提供的一个优秀的设计解决方案,它能很方便快捷的处理大批同类控件的响应和时间处理,但不知为什么在C#中这个优秀特性没有传承下来,甚为可惜,本文将要探讨就是如何在C# WinForm程序实现它.

总结起来,在C#中创建控件数组很简单,首先在类中创建一个控件类型的数组,然后初始化它,具体初始化是动态创建还是链接到已有控件可以根据情况自行选择,然后为数组元素添加事件,最后实现事件即可,在事件实现中即可以通过转化sender来得到相应控件.
  阅读全文

posted @ 2007-08-04 08:18 sitinspring 阅读(7943) | 评论 (2)编辑 收藏

"个人事务备忘录" 下载及介绍

     摘要: "个人事务备忘录"使用C#编成,用于进行个人每天的事务管理,它分三个页面,"某日事务"页面用于添加,删除和转移事务;"日历"页面用于以日历形式列举每天需要做的和已经做完的事务;"事务详细"页面用于查询具体事务.  阅读全文

posted @ 2007-08-03 15:41 sitinspring 阅读(1560) | 评论 (0)编辑 收藏

"文件批量命名器"下载及介绍

     摘要: C#做的小工具"文件批量命名器"下载及介绍   阅读全文

posted @ 2007-07-31 16:41 sitinspring 阅读(775) | 评论 (0)编辑 收藏

"目录文件比较器"下载及介绍

     摘要: 小工具"目录文件比较器"下载及介绍  阅读全文

posted @ 2007-07-27 10:52 sitinspring 阅读(977) | 评论 (3)编辑 收藏

更适合Swing程序的MVC方案

MVC有MVC1和MVC2的区别,它们的区别在于MVC1中用Model来通知View进行改变,而MVC2中使用Controller来通知View.在桌面程序中一般采用MVC1,而Web程序多采用MVC2,这是因为web程序中,Model无法知道View的原因.

在Swing程序中,我们通常采用让View实现Observer接口,让Model继承Observable类来实现MVC1,而让Controller把它们创建及连接起来,具体代码如下:
public class XXXControl {
    
private XXXModel model = null;
    
private XXXView view = null;

    
public XXXControl() {
        model 
= new XXXModel();
        view 
= new XXXView();
        model.addObserver(view);
     }


.
.
.
}

而Model进过处理后得到了结果,它采用Observable的notifyObservers()方法来通知View进行改变,而View的public void update(Observable o, Object arg)方法将相应这一改变,它通过解析Observable类型的对象o得到处理结果,再进行具体的表现层改变.

粗看起来MVC各司其职,很完美,但还有不和谐的隐患:
1.View必须知道解析Model,造成了二者的耦合.
2.View非得实现Observer接口,Model非得继承Observable类,这个处理不是必要的.
3.这种模式只适合即时处理,即相应很快的处理,对于耗时过程并不适合.
4.由于Model中数据众多,很多时候我们还需要建立一个常量类来区分各种情况和决定View更新的地方,进一步加重了类之间的耦合程度.

综上,我觉得对于稍大的Swing程序,MVC2+线程回调方式更适合,它的主要处理是:
1.依然由Controller创建View和Model,它们担负的职责也和原来一样,但是View不实现Observer接口,Model不继承Observable类,它们该怎么样还是怎么样,而让Controller来充当它们之间的中介者.
2.如果是即时处理,可以在Controller中添加事件处理时就直接写来.如果是耗时处理,可以将View和Model的引用(或Model中元素的引用)传递给一个线程处理类,具体的运算和界面反应在线程处理类中完成.
下面是一个调用例子:
new FetchTablesThread(model.getDataSource(), view,schema).start();

下面是线程类的例子:
public class FetchTablesThread extends BaseThread {
    
private static Logger logger = Logger.getLogger(FetchTablesThread.class);

    
private String schema;

    
public FetchTablesThread(DataSource dataSource, SqlWindowView view,
            String schema) 
{
        
super(dataSource, view);
        
this.schema = schema;
    }


    
public void run() {
        OutputPanel outputPanel 
= view.getTabbedPanel().getInputOutputPanel().getOutputPanel();

        
try {
            
if (dataSource.getDbtype().equals("mysql")) {
                
// Specail Process for MySql
                new FetchTables4MySqlThread(dataSource, view, schema).start();
            }
 else {
                
// Ordinary Process for other DB
                List tables = dataSource.getTablesInSchema(schema);

                
if (tables.size() > 0{
                    
// Find tables under schema
                    view.getCatalogTablesPanel().getMultiTable().refreshTable(
                            tables);

                    outputPanel.showText(
true);
                    String text 
= "Find " + tables.size()
                            
+ " tables under schema:" + schema
                            
+ " successfully!";
                    outputPanel.appendOutputText(text);
                    logger.info(text);
                }
 else {
                    
// Can't find tables under schema
                    outputPanel.showText(true);
                    String text 
= "Can't find any table under schema:" + schema;
                    outputPanel.appendOutputText(text);
                    logger.info(text);
                }

            }

        }
 catch (Exception ex) {
            outputPanel.showText(
true);
            String text 
= "Can't find any table under schema:" + schema+" and errorMsg="+ex.getMessage();
            outputPanel.appendOutputText(text);
            logger.info(text);            
        }

    }

}

这样做有两个好处一是使程序结构松散化,适于修改,二是相对传统的MVC2,Controller中事件处理的代码也容易变得简单而清晰,可维护性更佳.

综上,我认为MVC2+线程回调方式是一种值得推荐的Swing桌面程序写法.

关于线程回调方式,您可以参考:
http://www.blogjava.net/sitinspring/archive/2007/06/28/126809.html

关于MVC,您可以参考:
http://junglesong.yculblog.com/post.2665424.html

posted @ 2007-07-19 14:47 sitinspring 阅读(2289) | 评论 (5)编辑 收藏

利用MouseAdapter来实现自排序的表格

     摘要: 本文参考了http://www.java2s.com/Code/Java/Swing-JFC/TableSortTest.htm的做法。主要处理是取得用户点击的列,得到按此列排序的新数组,删除原有元素,再把新数组加入进表格;如果已经排序,则进行逆序处理。处理完毕后,用户点击表头即可实现排序和逆序。

  阅读全文

posted @ 2007-07-09 15:58 sitinspring 阅读(1641) | 评论 (2)编辑 收藏

使用回调和线程处理一个耗时响应过程

现在程序中有许多涉及长耗时响应过程的处理,比如访问WebService,远程调用,复杂处理等,如果我们使用直接顺序执行的方式进行处理有可能导致界面停顿,响应停止,无谓等待等缺陷,这是不应该的。

一个耗时响应过程应该采用回调和线程来处理,具体就是把原来的顺序执行修改为异步方式,并让被调用者调用调用者以获得执行结果。在附件的例子中,Viewer就是调用者,它代表界面,而LongTimeResponse是被调用者,它内部用线程启动一个耗时过程,执行完毕再通知调用者。

Viewer类代码如下:

public class Viewer{
    
private int count;
    
    
public Viewer(int count){
        
this.count=count;
    }

    
    
public void printNewCount(int newCount){
        System.out.println(
"New Count="+newCount);
    }


    
public int getCount() {
        
return count;
    }


    
public void setCount(int count) {
        
this.count = count;
    }

}


LongTimeResponse类代码如下,可以看出,它之所以能回调调用者,是因为其内部有调用者的引用viewer,在其构造函数中viewer被赋上了值:

package com.sitinspring;

public class LongTimeResponse implements Runnable{
    
private Viewer viewer;
    
private int count;
    
    
public LongTimeResponse(Viewer viewer){
        
this.viewer=viewer;
        
this.count=viewer.getCount();
        
        caculateNewCount();
    }

    
    
private void caculateNewCount(){
        Thread thread
=new Thread(this);
        thread.start();
    }

    
    
public void run(){
        
try{
            Thread.sleep(
10000);    
        }

        
catch(Exception ex){
            ex.printStackTrace();
        }

        
        viewer.printNewCount(count
*count*count);
    }

}

 

调用过程如下:

        Viewer viewer=new Viewer(10);
        LongTimeResponse longTimeResponse
=new LongTimeResponse(viewer);        
        viewer.printNewCount(
123);


执行起来可以看出,程序先输出了
New Count=123
过了十秒,才输出:
New Count=1000

这说明,程序是异步执行的,耗时过程没有影响到主干程序的运行,而耗时过程完成后,才把返回结果通知了调用者,主干程序没有受到耗时过程的影响,因此也就不会导致界面停顿,响应停止,无谓等待等缺陷。

以上就是使用回调和线程处理一个耗时响应的整个过程。

这里可下载整个程序:
http://www.blogjava.net/Files/sitinspring/Callback20070628133516.zip

例程2:
http://www.blogjava.net/Files/sitinspring/MVCThreadCallback.rar

posted @ 2007-06-28 13:49 sitinspring 阅读(2659) | 评论 (6)编辑 收藏

一个感观(LookAndFeel)菜单类及其用法

1.类代码如下
package com.junglesong.mvc.common.menu;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

/**
 * 程序风格菜单
 * @author junglesong@gmail.com
 *
 */
public class StyleMenu extends JMenu {
  // 程序的主框架
  final JFrame mainFrame;
 
  /**
   * 构造函数
   * @param text:菜单条文字
   * @param frame:程序的主框架
   */
  public StyleMenu(String text,JFrame frame) {
    super(text);
    mainFrame=frame;
    addSubMenuItems();
  }

  /**
   * 添加下级菜单项
   *
   */
  private void addSubMenuItems() {
    // 取得系统当前可用感观数组
    UIManager.LookAndFeelInfo[] arr = UIManager
        .getInstalledLookAndFeels();

    ButtonGroup buttongroup = new ButtonGroup();
    for (int i = 0; i < arr.length; i++) {
      JRadioButtonMenuItem styleMitem = new JRadioButtonMenuItem(
          arr[i].getName(), i == 0);
      final String className = arr[i].getClassName();
     
      // 添加下级菜单项的事件相应
      styleMitem.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          try {
            UIManager.setLookAndFeel(className);
            SwingUtilities.updateComponentTreeUI(mainFrame);
          } catch (Exception ex) {
            System.out.println("Can't Change Lookandfeel Style to "
                + className);
          }
        }
      });
      buttongroup.add(styleMitem);
      this.add(styleMitem);
    }
  }
}


2.用法如下

  JMenuBar menubar = new JMenuBar();
  mainFrame.setJMenuBar(menubar);
  ......
  menubar.add(Box.createHorizontalGlue());

  JMenu styleMenu = new StyleMenu("Syle", mainFrame);
  menubar.add(styleMenu);
  ......


例图:

posted @ 2007-06-28 08:47 sitinspring 阅读(1891) | 评论 (2)编辑 收藏

我的Maven2之旅:十一.打包一个web工程.

     摘要: 打包一个web工程  阅读全文

posted @ 2007-06-25 23:04 sitinspring 阅读(7401) | 评论 (3)编辑 收藏

一个用于桌面文件整理的JS脚本

我在工作过程中一般习惯把一些如代码段,文,下载文件档和图片等临时文件放在桌面上,这样能更方便一些,但是时间一长就容易积聚很多文件,密密麻麻的,删了吧又怕以后某时能用到,再找或者重做一个都很花时间,何况有些是不可恢复的.

为了解决这个问题,本人用微软的JS(非JavaScript,虽然语法很像)制作了一个脚本放在桌面上,感觉桌面文件过多时就可以选上拖曳到这个脚本上,它会按日期把选上的文件自动存放到一个备份目录里,这样找起来就方便了,也不会丢失重要信息,如果实在没用再删除备份中的目录或文件就可以了.

下面就是这个文件的代码,如果需要使用的话拷贝这段进入写字板,在另存为**.js的文件,放在桌面上即可使用,其中backupRoot清修改成你需要备份桌面文件的目录.

或者从这里下载:
http://www.blogjava.net/Files/sitinspring/deskSweep.rar

var backupRoot="E:\\Backup\\";// The folder you backup files
var target = backupRoot+getCurrTime()+"\\";// subfolder under backupRoot

var fso = WScript.CreateObject("Scripting.FileSystemObject"); 
if(!fso.FolderExists(target))
    fso.CreateFolder(target); 
}
 

var args = WScript.Arguments; // Command arguments
var movedNum=0;

for(var i=0;i<args.length;i++)
    storeFile(args(i),target);
}
 

WScript.Echo(movedNum.toString()
+" Files have been backup to folder:"+target); 

function storeFile(file,storeDir){
    
try{
        
if(fso.FileExists(file)) 
            fso.MoveFile(file,storeDir); 
        }
 
        
else if(fso.FolderExists(file)) 
            fso.CopyFolder(file
+"*",storeDir); 
            fso.DeleteFolder(file);            
        }
 
        
        movedNum
++;
    }

    
catch(e){
       WScript.Echo(file
+" can't be backup to folder:"+target);     
    }

}


function getCurrTime()
    
var d, s = "";                                // 声明变量。
    d = new Date();                         // 创建 Date 对象。
    s += d.getYear()+ "-";               // 获取年份。
    s += (d.getMonth() + 1+ "-";   // 获取月份。
    s += d.getDate() ;                        // 获取日。
  
    
return(s);                                        // 返回日期。
}
 

posted @ 2007-06-21 23:43 sitinspring 阅读(1777) | 评论 (8)编辑 收藏

仅列出标题
共13页: First 上一页 5 6 7 8 9 10 11 12 13 下一页 
sitinspring(http://www.blogjava.net)原创,转载请注明出处.