Bean binding Swing example(Swing數據綁定示例)

                  接觸Swing有一段時間,搜索到JSR295項目,苦于沒有中文資料,所以翻譯了國外的一片文章,英文不好,有語法錯誤請指正。

                 

              We'll compare getting and setting bean properties in JBoss Seam with Swing, and show how easy it is in Seam, how painful it is in Swing, and how Beans Binding can save Swing from its misery. We'll end with some discussion of how easy it is to fit Beans Binding into your applications, and future explorations, and how this pattern relates to the Action pattern we discussed earlier.
              The ubiquitous Person bean will be the backing bean in our examples:

          1public class Person {
          2  private String firstName;
          3  public String getFirstName() return firstName; }
          4  public void setFirstName(String firstName) this.firstName = firstName; }
          5
          6  // also a lastName property, and a int yearOfBirth property,
          7  // with getters and setters
          8}

              We want to create user interface elements which can get and set properties of this bean.
              JBoss Seam is great. Set up the component by adding a @Name annotation:

          1@Name("person"public class Person {
              and then you can use it in your JSF pages:
          1Please enter your first name: 
          2  <h:inputText value="#{person.firstName}"/>
              and Seam handles it.
              In a Swing application, the code would like like this:    
           1JTextField text = new JTextField();
           2
           3Person person = new Person();
           4
           5// Note the anonymous inner class, a common
           6// pattern for a listener
           7DocumentListener textListener = new DocumentListener() {
           8  void changedUpdate(DocumentEvent e) {
           9    person.setFirstName(firstNameField.getText()); }

          10  void insertUpdate(DocumentEvent e)  {
          11    person.setFirstName(firstNameField.getText()); }

          12  void  removeUpdate(DocumentEvent e) {
          13    person.setFirstName(firstNameField.getText()); }

          14}
          ;
          15
          16// Call this before displaying
          17void initComponents() {
          18  firstNameField.getDocument().addDocumentListener(textListener);
          19}
              That's painful, and that idiom must be used for every single binding. Why is Swing so much more painful than a Web-based interface with JBoss Seam? Why does Swing require implementing and binding a listener (usually an anonymous inner class) for every single property? The reason is that JBoss Seam is, in essence, a sophisticated properties binding system. To be as easy as Seam, Swing needs something similar.
              Swing has languished since its introduction with Java 1.2 in December of 1998. One of the reasons for Swing's doldrums was this need to write tedious listener code to bind front-end components to beans. Beans binding solves this problem. Straight to the code. I'll replace DocumentListener with a beans binding like this:
           1final Property textProperty = BeanProperty.create("text");
           2
           3// Now do a simple binding of the UI elements to the
           4// Person bean for firstName and lastName properties
           5Binding binding =
           6    Bindings.
           7    createAutoBinding(AutoBinding.UpdateStrategy.READ, // one-way binding
           8              firstNameField, // source of value
           9              textProperty, // the property to get
          10              person, // the "backing bean"
          11              BeanProperty.create("firstName"// property to set
          12              );
          13binding.bind();
              The code is shorter and clearer.
              Note that Property objects are immutable, so you don't need to keep on creating them. The text property can be used to get the text property of any bean (ie, any bean with a getText() method).
              Beans binding gets even better. You can use Expression Language (EL) to create properties:
          1binding =
          2    Bindings.
          3    createAutoBinding(AutoBinding.UpdateStrategy.READ,
          4              person,
          5              ELProperty.create("${firstName} ${lastName}"),
          6              fullName,
          7              textProperty
          8              );
              Note that this is full EL, so dot notation can be used to traverse objects. If every Person had a Pet, we could use:
          1ELProperty.create("${pet.name} the ${pet.species}")
              to bind a property to display a helpful string about the pet.
              All Swing components are beans, with change listeners, so Beans Binding "just works" on them. Even better, NetBeans 6 comes with great support for beans binding. Right click on the component you want to use as the target and you can bind it to a source without writing any code.
              Unfortunately, in NetBeans, only Swing components can be targets. That's great if you want to link a slider to a text field, so the user could slide from 0 to 100, and the text field will show the corresponding number. However, the most common real-world use for beans binding will be not linking UI components to other UI components, but rather, linking UI components to "backing beans". NetBeans 6 doesn't have a point-and-click way of doing that.
              But it's easy to do by hand. To use your data bean as a target, just use it. To use it as a source, you'll need to add one more thing: a support for PropertyChangeListeners. Let's say some UI component is bound to the Person's firstName. The UI component changes. Under the hood, the Beans Binding works by registering itself as a PropertyChangeListener. Swing components fire PropertyChangeEvents when properties change, so the whole thing happens invisibly when the source is a Swing component.
              When the source is a bean written for the application, you'll need to add your own support for PropertyChangeListeners. This is easy to do, using the PropertyChangeSupport class. Look at the source code of our Person.java class. The essential change is the addition of the addPropertyChangeListener() and removePropertyChangeListener() methods. The beans binding framework uses introspection to look for classes with those two methods. If both of those methods are found, beans binding registers the binding as a PropertyChangeListener, so it will be aware of changes to the property. Implementing these two methods is trivial; see the source code.
              Now the Person can be both the source and target for bindings, so our application looks like this:
              
              In this example, I'm using a GridLayout. It's ugly. In any real application, I would use NetBeans Matisse, to create beautiful resizable platform-independent interfaces. However, I wanted to keep this code short and simple to focus on the beans binding, without cluttering the example with layout concerns.
              The savings in lines of code is not great, but the savings in readability, clarity, and verifiability is great.
              Now we move on to some more advanced features: adding a validator for that year-of-birth field. Our validation rule is simple: the year of birth can't be in the future.
              First write the validator: YearValidator.java. This class extends the Validator abstract class, which has one method:
          1public abstract Validator.Result validate(Object argument)
              If validation succeeds, return null. Otherwise return a result with a descriptive message.
              Attaching this validator to the binding requires a twist. It's natural to think of the UI element as the "source" of the data and the bean as the "target" of the data. However, validation occurs on the write-back from the target to the source. Therefore, to use a validator, we must reverse the arguments in the binding, and set the mode to READ_WRITE, as follows:
           1binding =
           2    Bindings.
           3    createAutoBinding(AutoBinding.UpdateStrategy.READ_WRITE, // two-way binding
           4
           5              person,
           6              BeanProperty.create("yearOfBirth"), // property to set
           7
           8              yearOfBirthField, // source of value
           9              textProperty, // the property to get
          10
          11              "yearOfBirth");
          12// note that the converter and validators must be installed
          13// before calling bind()
          14binding.setConverter(new PositiveIntegerConverter());
          15binding.setValidator(new YearValidator());
          16// this allows us to get sync failure notifications,
          17// so they can be displayed
          18binding.addBindingListener(this);
          19binding.bind();
              The source and target arguments are reversed. NetBeans 6's Matisse makes it easy to turn any Swing component into a target, making this type of use point-and-click easy.
              The call to binding.bind() happens after the validator and converter are added. And note that we use binding.addBindingListener(this); to add a BindingListener. The PersonFrame class, which is also the JFrame, has been modified to implement the methods of the BindingListener interface. The method we need to catch validation errors is the
          1public void syncFailed(Binding binding, Binding.SyncFailure failure)
          method. This is what it looks like:

              Now we have seen how to use beans binding to easily link UI elements with data beans. We've seen how to use EL to create new properties as combinations of or operations on old properties. We've seen how to use a converter and a validator. That's only the beginning of the beans binding framework.
              The main advanced features of the beans binding framework is the ability to bind to collection-style components, such as JTable, JList and JComboBox. I won't say more about the collection components in this article. In a future article, I'll build a demo of using those components with beans binding. The advantages of using beans binding for simple component are evident. With JTable components, the advantages are even greater. I will also discuss design considerations. How do you build a desktop application to interact with a shared server? The obvious solution, with built-in support in NetBeans, is to bind front-end JTables to database tables. This method should not be used in real-world desktop applications, however. I'll explore the alternatives to figure out the right way to do this.
              Finally, beans binding is called a "framework". The word "framework" brings to mind heavy-weight containers, extending or implementing special classes, threads, a server, tricky XML configuration files, etc. None of these things are present in beans binding. Beans binding works with plain old classes which follow the bean patterns, including, conveniently, all the Swing UI components. The beans binding framework requires only including a small JAR file and creating properties. No server, no configuration, no changes to your existing body of code or deployment practices. It's easy to use, too. I hope after seeing this article, you'll try out the beans binding framework in your project.
              In a previous post, we discussed the conventional wisdom for adding functionality to Buttons. The traditional way is to write a ActionListener and bind it to the JButton with addActionListener(). We showed that this approach is cumbersome, and usually wrong, and the right way is to add an AbstractAction to the JButton. Writing listeners on input components is also cumbersome. Beans binding could be thought of as the correct alternative to change listeners on input UI components, just like AbstractActions are the correct alternative to actionPerformed listeners on command UI elements.
              I expect that EL and the beans binding framework (JSR 295) will find their way into a future Java release, but there's no reason to wait to start using it.
              Download the full sourcecode for this article: example.zip

          posted on 2009-07-17 15:17 舒阜東 閱讀(1571) 評論(2)  編輯  收藏

          評論

          # re: Bean binding Swing example(Swing數據綁定示例) 2011-07-07 12:59 規范多個好多個

          低功耗

            回復  更多評論   

          # re: Bean binding Swing example(Swing數據綁定示例) 2011-07-07 13:00 規范多個好多個

          @規范多個好多個
            回復  更多評論   


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          導航

          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          統計

          常用鏈接

          留言簿

          隨筆檔案

          文章檔案

          51CTO下載(IT技術資料免費下載平臺)

          搜索

          最新評論

          主站蜘蛛池模板: 岱山县| 黔江区| 靖边县| 应城市| 邹城市| 赣州市| 马关县| 普陀区| 天门市| 镇康县| 渭源县| 文化| 石嘴山市| 绍兴县| 偃师市| 博爱县| 繁昌县| 武穴市| 和龙市| 鄂托克前旗| 保山市| 象州县| 安溪县| 沙雅县| 禹城市| 崇礼县| 肇庆市| 赤城县| 全南县| 北辰区| 泰和县| 玛沁县| 乌兰察布市| 灵璧县| 三亚市| 延安市| 宁夏| 安平县| 泗水县| 肇庆市| 醴陵市|