春天里,百花香...
#
摘要: 控件数组是VB提供的一个优秀的设计解决方案,它能很方便快捷的处理大批同类控件的响应和时间处理,但不知为什么在C#中这个优秀特性没有传承下来,甚为可惜,本文将要探讨就是如何在C# WinForm程序实现它.
总结起来,在C#中创建控件数组很简单,首先在类中创建一个控件类型的数组,然后初始化它,具体初始化是动态创建还是链接到已有控件可以根据情况自行选择,然后为数组元素添加事件,最后实现事件即可,在事件实现中即可以通过转化sender来得到相应控件.
阅读全文
摘要: "个人事务备忘录"使用C#编成,用于进行个人每天的事务管理,它分三个页面,"某日事务"页面用于添加,删除和转移事务;"日历"页面用于以日历形式列举每天需要做的和已经做完的事务;"事务详细"页面用于查询具体事务.
阅读全文
摘要: C#做的小工具"文件批量命名器"下载及介绍
阅读全文
摘要: 小工具"目录文件比较器"下载及介绍
阅读全文
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
摘要: 本文参考了http://www.java2s.com/Code/Java/Swing-JFC/TableSortTest.htm的做法。主要处理是取得用户点击的列,得到按此列排序的新数组,删除原有元素,再把新数组加入进表格;如果已经排序,则进行逆序处理。处理完毕后,用户点击表头即可实现排序和逆序。
阅读全文
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);
......
例图:
我在工作过程中一般习惯把一些如代码段,文,下载文件档和图片等临时文件放在桌面上,这样能更方便一些,但是时间一长就容易积聚很多文件,密密麻麻的,删了吧又怕以后某时能用到,再找或者重做一个都很花时间,何况有些是不可恢复的.
为了解决这个问题,本人用微软的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); // 返回日期。
}
sitinspring(http://www.blogjava.net)原创,转载请注明出处.