如鹏网 大学生计算机学习社区

CowNew开源团队

http://www.cownew.com 邮件请联系 about521 at 163.com

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  363 随笔 :: 2 文章 :: 808 评论 :: 0 Trackbacks

#

     摘要: 下面的例子中第一个进度条是一个“确定模式”的滚动条,进度中显示了当前的工作完成百分比,第二个进度条可以通过按钮切换“不确定模式”与“确定模式”: package com.cownew.Char19; import java.awt.Rectangle; import javax.swing.JButton; impor...  阅读全文
posted @ 2007-05-30 20:18 CowNew开源团队 阅读(2838) | 评论 (3)编辑 收藏

    王开源的事情已经过去一段时间了,看过太多对这件事情的评论,这些评论或者是口出污言秽语的谩骂或者是狂热的非理性的力挺(在这件事的初期属于后者)。很多人对开源的评论也使得我这个投身于开源一年多的新人感到过迷茫。这件事过去好久,我一直在思索一个问题:开源在目前中国的意义究竟是什么,开源在中国这种大环境下究竟应该如何发展。
    开源在国外现在是火的一塌糊涂,Linux、Eclipse、Hibernate、Spring、Python、Ruby、MySQL等等或大或小的开源产品的发展大大推动了软件开发这个行业的高速发展,apache、sourceforge等开源社区中也是百花齐放,开源产品的开发者、推动者、推广者也得到了各自想得到的回报,更不用说使用这些开源产品进行开发的用户得到的开发效率的提升。反观国内开源的发展则相对滞后很多:违背Linux开源协议进行商业化Linux开发的厂家被开源社区骂的狗血喷头;屈指可数的几个开源爱好者组织的开源团队在个人的意志与信念的坚守下苦苦支撑着,很多因为种种原因中途夭折;商业公司对开源社区的几次推广行动也胎死腹中,比如CSDN的开源社区、Apusic的Operamasks;更有甚者打着开源的旗号却从事着根本与开源不搭边的事情。国内大部分人对开源更是有着很深的误解:“你凭什么叫人家开源,不就是想看看Windows的代码吗?”、“人家商业公司做出来的产品是你们几个技术疯子做出来的东西能比的吗?”、“把别人写好的东西拿来抄一抄改一改我的任务就完成了,钱就到手了,开源真好”、“我做的项目用了很多开源的东西,很牛吧!”。
    我认为开源对于整个软件行业有如下几个作用:使用开源产品搭建出的产品有更好的安全性和可控性;开源的产品能得到开发社区的广泛支持,从而使得产品能够成熟的更快;使用开源产品搭建出的产品有更好的安全性和可控性;开发、学习开源产品能够提升开发人员的技术水平。
    对于第一个作用这里不做过多解释,相信大部分人都能理解。
    开源产品是在全世界所有技术牛人的手下开发出来的,并且有千万双眼睛盯着它,众多的使用者可以完善它,这使得开源产品的成熟速度也十分惊人,Linux、Eclipse的成熟就是最典型的证明。各种开源产品层出不穷,相似功能的产品就有几十种甚至上百种,一个开源产品如果想要在这些产品中脱颖而出,不仅需要强大的技术做支撑,更需要非常强的商业化推广,否则做出来的产品只能成为少数技术人员把玩的玩物。如果没有IBM对Eclipse的巨额投入,Eclipse会发展成现在的规模吗?这些开源项目的后面通常都是有一个非常强大的开源基金会在做支撑。遗憾的是,目前国内还没有一家公司能够进行对开源社区如此大的投入,因此国内大部分的开源团队都是在自己开发着自己的开源产品,放到网站上供他人下载,然后梦想着自己的开源产品能够有一天会像Hibernate、Struts一样成为风靡全球的产品,但是如果没有强大的商业推广的话这肯定是一场白日梦。
    鉴于此,我认为目前国内的开源产品商业化的可能性是非常小的,因此开源的对于广大开发人员的意义更多的在于使用和学习,而且我们使用开源产品快速的搭建出满足需求的产品,这本身也是对开源的学习过程。这里提到的“学习”包含下面几个含义:学习开源产品的使用;学习开源产品的实现原理;学习模仿开源产品;学习开源社区的运营。
    (1)学习开源产品的使用:成熟的开源产品是非常优秀的,如果能够学会它们的使用,这对于开源人员来说就是一种很大的收获,因为通过使用这些产品就能认识到这些产品的功能、特性以及优缺点。
    (2)学习开源产品的实现原理:开源产品的代码都是开放的,我们可以深入产品的内部学习其实现原理,从而提高自身的开发水平。不得不承认的是国内开发人员的技术水平还是非常低的,通过学习开源产品的代码,就可以提高整体的技术水平,从这个层面来讲哪怕是非开源的源代码开放产品(比如Borland的VCL)对我们也是同样有帮助的。值得高兴的是,国内很多开发人员已经开始尝试着深入开源产品的内部去探寻这些产品的实现原理,并把它们的学习成果与更多人分享。开源对开发人员的提升也是显而易见的,最明显的就是微软开发社区中开发人员的普遍技术水平是低于Java等开源社区中开发人员的普遍技术水平的(注意,这里说的是“普遍技术水平”,请微软社区中的高人不要动怒)。中国计算机业的发展必须依靠核心技术,而提高技术水平是拥有核心技术的大前提!
    (3)学习模仿开源产品:弄懂了开源产品的实现原理以后就可以尝试模仿它们开发自己的产品,这和“重复造轮子”是没有关系的,模仿是学习他人技术的最佳途径。因此大家应该多多的“造轮子”,越多越好,哪怕造完就扔掉也是可以的。
    (4)学习开源社区的运营:国外很多开源人员都有在开源社区中开发的经验,因此他们对于开源这种协同开发方式就有更多的经验,因此我们可以加入他们的开发团队,可以帮他们做文档、界面的本地化,更可以参与产品功能的完善,从而学习他们的协作方式,更可以和他们做朋友,了解更多“外面的世界”。国内很多朋友都参与了开源产品的文档中文化、产品的推广等工作,这都是有深远意义的。我们CowNew开源团队参与JodeEclipse、DWPL等国外项目就是基于这一点考虑的。
     相信经过一段时间学习之后,我们的开发人员将有能力开发出世界级的产品,如果我们的民族企业能够得到长远的发展,并且在商业上帮助国产开源真正走向强大,从而使得中国的开源社区也能跻身“世界开源之林”!
    上边是我一点愚蠢的看法,仅供各位看管参考。希望开源能够在中国发展、壮大,希望中国早日成为软件强国!
   
posted @ 2007-05-20 18:08 CowNew开源团队 阅读(2100) | 评论 (11)编辑 收藏

今天要使用mysql做一个功能的实验,但是发现写进去的中文变成了乱码,可是数据库的编码都改成gbk了,而且jdbc连接字符串和my.ini的default-character-set配置项也改成了gbk,但是连接的时候还是乱码,通过mysql的原生客户端连接则不会出现这种情况。最终的解决方法是将所有的字符集都改成utf-8。
用gbk、gb2312 之类的时候都可能会出现问题,而utf-8作为一个标准的多语言字符集则解决乱码的终极方案。所以推荐大家在其他遇到中文的情况下也使用utf-8。
posted @ 2007-05-19 11:59 CowNew开源团队 阅读(592) | 评论 (0)编辑 收藏

Eclipse的插件机制是个非常好的东西,架构也非常灵活。我们开发的插件有时候需要提供一些扩展机制,允许他人扩展,但是如果是提供的标准的Eclipse扩展点的话无疑加大了开发扩展功能的难度,开发人员必须熟悉Eclipse插件开发才可以。在最近做的几个IDE中,为了避免这个问题,我都采用了最原始的插件扩展方式,也就是扩展功能的开发人员把扩展插件的jar包或者.class文件放到某个目录下即可,这些扩展功能也只需实现某个接口即可,由我的插件来进行加载。这样在扩展功能开发人员看来,写扩展功能就是写一个实现了某个接口的Java类,无需了解Eclipse插件开发的知识了,当然这带来的缺点就是灵活性降低了。
posted @ 2007-05-19 00:32 CowNew开源团队 阅读(520) | 评论 (0)编辑 收藏

   做系统设计的时候有时会碰到一些无法在父类(或者接口)中抽取通用行为的特性,遇到这种情况就可以采用StringConfigure模式,这个模式我取的名字,不知道是否已经有先人做了总结,如果哪位朋友知道这种模式的正确名称,希望不吝赐教。
   以JDBC中取得数据库连接为例,我们可以抽象出数据库的一些公共行为,比如连接数据库都要求提供用户名和密码,因此在JDBC中提供设定连接的用户名和密码的方法。但是另外的一些行为则不一定是所有数据库都具备的,比如对于网络型数据库才需要指定网络地址,而文件型数据库则不需要,再比如在MySQL中需要指定字符集,而其他数据库则不一定需要。如果为了照顾这些特性,为JDBC提供setHostIP、setDBFilePath、setCharSet等方法的话无疑会使得接口变得复杂,会出现很多用不到的方法,并且这些方法也无法覆盖所有未来可能出现的情况,比如某个数据库又增加了允许用户定制连接超时的方法,那么JDBC也要为他提供相应的setTimeOut方法。为了解决这个问题,JDBC提出了连接字符串的概念,这样各个数据库的JDBC驱动只要规定好连接字符串的格式即可,用户把所有的配置信息写到连接字符串中,如果用户修改为其他数据库的话只需修改连接字符串即可,不用修改其他的调用。
   使用StringConfigure模式的好处是使得系统中的个性化配置在一个参数中完成,这样保证系统的不同模块的行为的一致性,缺点是配置字符串的格式要由各个实现模块来规定,各个不同实现模块的格式不一致,造成了一定的学习成本,而且无法在开发期发现配置字符串的问题。
   这里再来讲一个StringConfigure模式的应用的例子。现在我们要开发一套对IC卡读写器的类库,应用开发人员只要调用不同的IC卡读写子类即可实现操作不同的IC卡读写器。各种不同的IC卡读写器有两个共同的抽象行为:读卡和写卡,即readCard和writeCard,但是各个不同的读卡器还有自己的特性,比如有的读卡器需要指定采用ISO格式还是IBM格式来读写磁卡,有的读卡器需要指定读写操作的分隔符,这些特性不是各个读写器共有的,因此我们采用StringConfigure模式进行设计,开发如下的接口:
interface IICCarder
{
  public void writeCard(String data);
  public String readCard();
  public void configure(String configStr);
}

   比如需要指定读写格式的读写器就可以如下实现:
class SomeCarder implements IICarder
{
    private FormatEnum format;
    public void writeCard(String data)
    {
       if(format==FormatEnum.IBM)
       {
             .........
       }
       else...........
    }
    public String readCard()
    {.............
    }
    public void configure(String configStr)
    {
        if(configStr.equls("IBM"))
        {
           format=FormatEnum.IBM
        }
        else if(configStr.equls("ISO"))
        {
           format=FormatEnum.ISO
        }
    }
}

开发人员使用的时候只要如下调用
IICarder c = new SomeCarder();
c.configure("IBM");
print c.readCard();
如果采用配置文件的话更可以把配置参数写到配置文件中,这样就可以避免修改代码。

posted @ 2007-05-19 00:22 CowNew开源团队 阅读(1125) | 评论 (2)编辑 收藏

CowNew 成为JodeEclipse的管理员,今后JodeEclipse以后将会由CowNew来进行维护,对于JodeEclipse有哪些需求,可以在这里提出。预计近期为jode eclipse增加调试和批量反编译的功能。有兴趣的朋友也可以加入开发队伍。

JodeEclipse的网站:http://sourceforge.net/projects/jodeeclipse
posted @ 2007-05-17 19:16 CowNew开源团队 阅读(373) | 评论 (2)编辑 收藏

最近在和technoetic的Steve Bate接触,已经达成初步的合作意向,technoetic将会接收jode eclipse的管理权,以后将会由CowNew来进行jode eclipse的bug修复和新功能添加,预计近期为jode eclipse增加调试和批量反编译的功能。此外计划为cownewstudio增加生成DDL的功能。有兴趣的队友可以来领任务。
posted @ 2007-05-14 22:26 CowNew开源团队 阅读(313) | 评论 (1)编辑 收藏

Jodeclipse 是Jode的Eclipse插件,是一个非常好的反编译插件,不过Jodeclipse 在eclipse3.2上有bug,每次反编译的时候都会报一个错误,虽然不影响反编译结果,但是非常影响使用。因此我从Jodeclipse 的CVS上CheckOut出了代码,做了修复,编译以后的二进制包从此处下载:
http://www.blogjava.net/Files/huanzhugege/net.sourceforge.jode_1.0.5.rar

安装方法:
直接解压到eclipse的plugins目录下。

已经将修改后的代码提交给jodeclipse的管理员。
开源万岁!!!
posted @ 2007-05-13 17:05 CowNew开源团队 阅读(8684) | 评论 (16)编辑 收藏

 

下面的代码就演示了为JTextArea、JList增加滚动条的代码:

package com.cownew.Char19;

import javax.swing.SwingUtilities;

import java.awt.BorderLayout;

import javax.swing.DefaultListModel;

import javax.swing.JPanel;

import javax.swing.JFrame;

import javax.swing.JTextArea;

import javax.swing.ListModel;

import java.awt.Rectangle;

import javax.swing.JList;

import javax.swing.JScrollPane;

public class ScrollPaneTest1 extends JFrame

{

private JPanel jContentPane = null;

private JTextArea jTextArea = null;

private JList jList = null;

private JScrollPane jScrollPane = null;

private JScrollPane jScrollPane1 = null;

private JList jList1 = null;

private JTextArea jTextArea1 = null;

private JTextArea getJTextArea()

{

if (jTextArea == null)

{

jTextArea = new JTextArea();

jTextArea.setBounds(new Rectangle(12, 7, 95, 71));

}

return jTextArea;

}

private JList getJList()

{

if (jList == null)

{

jList = new JList();

jList.setBounds(new Rectangle(8, 92, 106, 71));

DefaultListModel listModel = new DefaultListModel();

listModel.addElement("22222");

listModel.addElement("33333333");

listModel.addElement("55555555555555");

listModel.addElement("8888888888");

listModel.addElement("88888888");

listModel.addElement("999999999");

jList.setModel(listModel);

}

return jList;

}

private JScrollPane getJScrollPane()

{

if (jScrollPane == null)

{

jScrollPane = new JScrollPane();

jScrollPane.setBounds(new Rectangle(143, 7, 122, 75));

jScrollPane.setViewportView(getJTextArea1());

}

return jScrollPane;

}

private JScrollPane getJScrollPane1()

{

if (jScrollPane1 == null)

{

jScrollPane1 = new JScrollPane();

jScrollPane1.setBounds(new Rectangle(142, 96, 128, 68));

jScrollPane1.setViewportView(getJList1());

}

return jScrollPane1;

}

private JList getJList1()

{

if (jList1 == null)

{

jList1 = new JList();

DefaultListModel listModel = new DefaultListModel();

listModel.addElement("22222");

listModel.addElement("33333333");

listModel.addElement("8888888888888888888888888888");

listModel.addElement("8888888888");

listModel.addElement("88888888");

listModel.addElement("999999999");

jList1.setModel(listModel);

}

return jList1;

}

private JTextArea getJTextArea1()

{

if (jTextArea1 == null)

{

jTextArea1 = new JTextArea();

}

return jTextArea1;

}

public static void main(String[] args)

{

SwingUtilities.invokeLater(new Runnable() {

public void run()

{

ScrollPaneTest1 thisClass = new ScrollPaneTest1();

thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

thisClass.setVisible(true);

}

});

}

public ScrollPaneTest1()

{

super();

initialize();

}

private void initialize()

{

this.setSize(300, 200);

this.setContentPane(getJContentPane());

this.setTitle("JFrame");

}

private JPanel getJContentPane()

{

if (jContentPane == null)

{

jContentPane = new JPanel();

jContentPane.setLayout(null);

jContentPane.add(getJTextArea(), null);

jContentPane.add(getJList(), null);

jContentPane.add(getJScrollPane(), null);

jContentPane.add(getJScrollPane1(), null);

}

return jContentPane;

}

}

运行效果图:

图 17.9

JScrollPane还能为组合界面增加滚动条:

package com.cownew.Char19;

import java.awt.Dimension;

import java.awt.Rectangle;

import javax.swing.JButton;

import javax.swing.JCheckBox;

import javax.swing.JFrame;

import javax.swing.JPanel;

import javax.swing.JScrollPane;

import javax.swing.JSlider;

import javax.swing.JTextField;

import javax.swing.SwingUtilities;

public class ScrollPaneTest2 extends JFrame

{

private JPanel jContentPane = null;

private JScrollPane jScrollPane = null;

private JPanel jPanel = null;

private JButton jButton = null;

private JButton jButton1 = null;

private JCheckBox jCheckBox = null;

private JTextField jTextField = null;

private JSlider jSlider = null;

private JScrollPane getJScrollPane()

{

if (jScrollPane == null)

{

jScrollPane = new JScrollPane();

jScrollPane.setBounds(new Rectangle(28, 17, 142, 114));

jScrollPane.setViewportView(getJPanel());

}

return jScrollPane;

}

private JPanel getJPanel()

{

if (jPanel == null)

{

jPanel = new JPanel();

jPanel.setLayout(null);

jPanel.add(getJButton(), null);

jPanel.add(getJButton1(), null);

jPanel.add(getJCheckBox(), null);

jPanel.add(getJTextField(), null);

jPanel.add(getJSlider(), null);

jPanel.setPreferredSize(new Dimension(300,200));

}

return jPanel;

}

private JButton getJButton()

{

if (jButton == null)

{

jButton = new JButton();

jButton.setBounds(new Rectangle(6, 10, 74, 28));

}

return jButton;

}

private JButton getJButton1()

{

if (jButton1 == null)

{

jButton1 = new JButton();

jButton1.setBounds(new Rectangle(102, 9, 82, 30));

}

return jButton1;

}

private JCheckBox getJCheckBox()

{

if (jCheckBox == null)

{

jCheckBox = new JCheckBox();

jCheckBox.setBounds(new Rectangle(17, 56, 93, 21));

jCheckBox.setText("aaaaabbb");

}

return jCheckBox;

}

private JTextField getJTextField()

{

if (jTextField == null)

{

jTextField = new JTextField();

jTextField.setBounds(new Rectangle(126, 57, 99, 22));

}

return jTextField;

}

private JSlider getJSlider()

{

if (jSlider == null)

{

jSlider = new JSlider();

jSlider.setBounds(new Rectangle(20, 111, 205, 25));

}

return jSlider;

}

public static void main(String[] args)

{

SwingUtilities.invokeLater(new Runnable() {

public void run()

{

ScrollPaneTest2 thisClass = new ScrollPaneTest2();

thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

thisClass.setVisible(true);

}

});

}

public ScrollPaneTest2()

{

super();

initialize();

}

private void initialize()

{

this.setSize(221, 177);

this.setContentPane(getJContentPane());

this.setTitle("JFrame");

}

private JPanel getJContentPane()

{

if (jContentPane == null)

{

jContentPane = new JPanel();

jContentPane.setLayout(null);

jContentPane.add(getJScrollPane(), null);

}

return jContentPane;

}

}

运行效果图:

图 17.10

对于这种组合界面必须为界面设定一个最佳尺寸(PreferredSize),这样JScrollPane才知道如何显示滚动条:jPanel.setPreferredSize(new Dimension(300,200))。

JScrollPane中的ViewPort是一种特殊的对象,通过它就可以查看基层组件,滚动条其实就是沿着组件移动“视点”,这样就可以查看隐藏的部分。

posted @ 2007-04-29 12:32 CowNew开源团队 阅读(5913) | 评论 (0)编辑 收藏

 

首先演示一个NumberFormatter的例子,在这个例子中要求用户输入一个数字,单击按钮后将用户输入的数字乘2以后重新赋值给输入框。用户输入的数字必须大于0,小于100。

package com.cownew.Char19;

import java.awt.Font;

import java.awt.Rectangle;

import java.math.BigDecimal;

import javax.swing.JButton;

import javax.swing.JDialog;

import javax.swing.JFormattedTextField;

import javax.swing.JOptionPane;

import javax.swing.JPanel;

import javax.swing.text.NumberFormatter;

import javax.swing.JTextField;

public class NumberFormaterDialog1 extends JDialog

{

private JPanel jContentPane = null;

private JFormattedTextField numTxtField = null;

private JButton jButton = null;

private JTextField jTextField = null;

private JFormattedTextField getNumTxtField()

{

if (numTxtField == null)

{

NumberFormatter numFormater = new NumberFormatter();

numFormater.setMaximum(new BigDecimal(100));

numFormater.setMinimum(new BigDecimal(0));

numTxtField = new JFormattedTextField(numFormater);

numTxtField.setBounds(new Rectangle(56, 38, 154, 24));

}

return numTxtField;

}

private JButton getJButton()

{

if (jButton == null)

{

jButton = new JButton();

jButton.setBounds(new Rectangle(78, 80, 81, 36));

jButton.setFont(new Font("Dialog", Font.PLAIN, 18));

jButton.setText("计算");

jButton.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent e)

{

BigDecimal oldValue = (BigDecimal) getNumTxtField()

.getValue();

if (oldValue != null)

{

getNumTxtField().setValue(

oldValue.multiply(new BigDecimal(2)));

}

else

{

JOptionPane.showMessageDialog(

NumberFormaterDialog1.this,"值非法");

}

}

});

}

return jButton;

}

private JTextField getJTextField()

{

if (jTextField == null)

{

jTextField = new JTextField();

jTextField.setBounds(new Rectangle(176, 83, 76, 22));

}

return jTextField;

}

public static void main(String[] args)

{

NumberFormaterDialog1 dlg = new NumberFormaterDialog1();

dlg.show();

}

public NumberFormaterDialog1()

{

super();

initialize();

}

private void initialize()

{

this.setSize(300, 200);

this.setContentPane(getJContentPane());

this.setTitle("JFrame");

}

private JPanel getJContentPane()

{

if (jContentPane == null)

{

jContentPane = new JPanel();

jContentPane.setLayout(null);

jContentPane.add(getNumTxtField(), null);

jContentPane.add(getJButton(), null);

jContentPane.add(getJTextField(), null);

}

return jContentPane;

}

}

当我们输入-3这个无效值的时候是允许输入的,但是当鼠标焦点移动到另外的控件的时候,“-3”就会消失。这个行为可以通过NumberFormatter 的setAllowsInvalid方法来改变:

图 17.5

图 17.6

如果输入“10”这个合法的数字,单击“计算”按钮即可算出正确的值:

图 17.7

图 17.8

案例系统中的com.cownew.ctk.ui.swing.JNumberTextField就是为了方便使用而从JFormattedTextField派生的一个数字输入控件。

DateFormatter的使用也是类似的,也允许设置最大最小值,实际上只要从InternationalFormatter派生的类,并且数据类型实现了Comparable接口都可以设置极值。

MaskFormatter允许开发人员使用掩码指定更加复杂的校验规则。掩码是一串特殊的字符串,每个字符的含义如下表所示:

字符

说明

#

匹配任何数字字符

'

转义符,用来将格式字符当成普通字符用

U

任意大写字母

L

任意小写字母

A

任意数字或者字母

?

任何字母

*

任何字符

H

任何十六进制字符 (0-9, a-f or A-F).

实例化时指定其掩码即可:

MaskFormatter formatter = new MaskFormatter("0x***");

formatter.setValidCharacters("0123456789abcdefABCDEF");

还允许为掩码设定占位符,这样可用性更好:

MaskFormatter formatter = new MaskFormatter("###-####");

formatter.setPlaceholderCharacter('_');

formatter.getDisplayValue(tf, "123");

posted @ 2007-04-26 09:29 CowNew开源团队 阅读(1597) | 评论 (0)编辑 收藏

仅列出标题
共30页: First 上一页 11 12 13 14 15 16 17 18 19 下一页 Last