{"id":572,"date":"2021-02-23T01:16:18","date_gmt":"2021-02-23T01:16:18","guid":{"rendered":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/?page_id=572"},"modified":"2021-04-14T18:29:37","modified_gmt":"2021-04-14T18:29:37","slug":"java-beans","status":"publish","type":"page","link":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/","title":{"rendered":"Java Beans"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a6d48268f5b7\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a6d48268f5b7\"  aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#What_are_JavaBeans\" >What are JavaBeans?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#Use_of_Components_in_an_IDE\" >Use of Components in an IDE<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#JavaBean_Components\" >JavaBean Components<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#An_Example_Java_Bean\" >An Example Java Bean<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#Properties\" >Properties<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#Simple_Property_Naming_Patterns\" >Simple Property Naming Patterns<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#Property_Name_Capitalization\" >Property Name Capitalization<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#Get_Methods_for_boolean_Type_Properties\" >Get Methods for&nbsp;boolean&nbsp;Type Properties<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#Simple_Indexed_Properties\" >Simple &amp; Indexed Properties<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#Simple_Properties\" >Simple Properties<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#Simple_Property_Naming_Patterns-2\" >Simple Property Naming Patterns<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#Indexed_Properties\" >Indexed Properties<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#Indexed_Property_Naming_Patterns\" >Indexed Property Naming Patterns<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#Example_A_SimpleScatterPlot_Bean\" >Example: A SimpleScatterPlot Bean<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#Bound_Properties\" >Bound Properties<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#Bound_Property_Requirements\" >Bound Property Requirements<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#The_PropertyChangeListener_Interface\" >The&nbsp;PropertyChangeListener&nbsp;Interface<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#The_PropertyChangeSupport_Class\" >The&nbsp;PropertyChangeSupport&nbsp;Class<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-19\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#Example_A_New_BarChart_Bean\" >Example: A New BarChart Bean<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-20\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#Constrained_Properties\" >Constrained Properties<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-21\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#Constrained_Property_Requirements\" >Constrained Property Requirements<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-22\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#The_VetoableChangeListener_Interface\" >The&nbsp;VetoableChangeListener&nbsp;Interface<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-23\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#The_VetoableChangeSupport_Class\" >The&nbsp;VetoableChangeSupport&nbsp;Class<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-24\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#Example_A_BarChart_with_a_Constrained_Property\" >Example: A&nbsp;BarChart with a Constrained Property<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-25\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#PropertyChangeSupport_VetoableChangeSupport\" >PropertyChangeSupport &amp; VetoableChangeSupport<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-26\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/java-beans\/#Simplified_Example_of_a_Bound_and_Constrained_Property\" >Simplified Example of a Bound and Constrained Property<\/a><\/li><\/ul><\/nav><\/div>\n\n<p class=\"wp-block-paragraph\">Have you ever used an IDE to create a form?&nbsp; Used Visual Basic to create a GUI application?&nbsp; If so, you&#8217;ll be familiar with the idea of visual components and combining them to produce a GUI interface for users.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the Microsoft world, such visual components are implemented using OLE, COM, or ActiveX controls, depending on Microsoft&#8217;s product name of the day.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">JavaBeans is Java&#8217;s response to such visual objects, although the use of &#8220;beans&#8221; has become ubiquitous far beyond merely visual objects.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"What_are_JavaBeans\"><\/span>What are JavaBeans?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Software Components have been the &#8220;holy grail&#8221; of software development for some time. The idea is to take a page out of the hardware designers&#8217; book, and come up with a set of components (&#8220;Software ICs&#8221;, to use a term coined by&nbsp;<a href=\"https:\/\/en.wikipedia.org\/wiki\/Brad_Cox\" target=\"_blank\" rel=\"noreferrer noopener\">Brad Cox<\/a>) (IC = Integrated Circuit) which can be plugged in, where appropriate, to build complex systems from more manageable, smaller, pieces.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The grand vision of reusable Software Components has not yet come to pass. However, there are some outstanding successes in the field &#8212; notably Microsoft&#8217;s Visual Basic (VB). VB has been incredibly successful (despite many professional programmers&#8217; disparagement of the BASIC language), and has spawned a veritable cottage industry of reusable VB components, or to use Microsoft&#8217;s term: VBXs. In fact, VBXs have been changed into more general components called OCXs, and absorbed into a more generalized component model called COM (or ActiveX, or DNA, or whatever Microsoft&#8217;s latest&nbsp;<em>nom du jour<\/em>&nbsp;(name of the day) might be).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Not to be outdone, JavaSoft decided that the lure of shareable, reusable software components was too great to pass up, and so they decided to come up with their own component model, which they call JavaBeans.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Use_of_Components_in_an_IDE\"><\/span>Use of Components in an IDE<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">One of the really powerful ideas that VB had was that you could develop a component inside the VB IDE (Interactive Development Environment) using primarily point and click operations, with a bit of typing here and there. In this way, you can build a component, and incorporate it into a large application. What is even more powerful an idea is that third parties can do the same thing, and then sell the components for use in other people&#8217;s applications. With VB, it is literally true that you can build a relatively complex application by buying the appropriate set of components, plugging them into your application, and setting various properties and interactions among the components.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Note that most VB components are visual components. They are typically used in a GUI to present results or accept inputs and respond with visual changes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">JavaBeans also focusses on primarily visual components. However, it was a requirement that JavaBeans be usable in a number of different IDEs, most of them not from JavaSoft\/Sun. Consequently, it was important that JavaSoft come up with a mechanism that was very easily usable within a number of different visual environments.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">All of the major Java IDEs support JavaBeans:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Eclipse<\/li><li>NetBeans<\/li><li>etc.<\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"JavaBean_Components\"><\/span>JavaBean Components<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">A JavaBean exports&nbsp;<em>properties<\/em>,&nbsp;<em>events<\/em>, and&nbsp;<em>methods<\/em>.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>A&nbsp;<em><strong>property<\/strong><\/em>&nbsp;represents a piece of the bean&#8217;s internal state. Properties affect a Bean&#8217;s appearance and behavior. They may be changed at design time. A builder tool can examine a Bean&#8217;s properties and expose them for manipulation within the tool environment (typically an IDE).<\/li><li>A bean may generate&nbsp;<em><strong>events<\/strong><\/em>. Events are used to communicate with other Beans. A Bean that wishes to receive events (a listener Bean) registers its interest with the Bean that fires that event (a source Bean). A builder tool can examine a Bean and determine which events the Bean can fire (send), and which it can handle (receive).<\/li><li>A Bean makes available (exports) a set of public&nbsp;<em><strong>methods<\/strong><\/em>. A Bean&#8217;s methods can be called from other Beans, or from other environments. By default, all of a Bean&#8217;s public methods are exported.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">All these are important for an IDE to &#8220;understand&#8221; at design time, as well as for the bean to work correctly at run time.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"An_Example_Java_Bean\"><\/span>An Example Java Bean<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s a simple JavaBean &#8212; a bar chart. (It more properly might be called a &#8216;temperature gauge&#8217;.)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is the source code for the bar chart bean:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage javaBeans_0;\n\nimport java.awt.Color;\nimport java.awt.Dimension;\nimport java.awt.Graphics;\n\nimport javax.swing.BorderFactory;\nimport javax.swing.JPanel;\n\n\/**\n * A BarChart JavaBean class.\n *\n * @author Bryan J. Higgs, 12 March, 2000\n *\/\npublic class BarChart extends JPanel\n{\n\n  \/**\n   * Constructs a BarChart instance\n   *\/\n  public BarChart()\n  {\n    setPreferredSize(new Dimension(m_barWidth, m_barHeight));\n    setBorder(BorderFactory.createLineBorder(m_borderColor, m_borderWidth));\n  }\n\n  \/**\n   * Sets the percent for bar display.\n   *\/\n  public void setPercent(int percent)\n  {\n    if (percent &lt;= 100 &amp;&amp; percent &gt;= 0)\n    {\n      m_percent = percent;\n      repaint();\n    }\n  }\n\n  \/**\n   * Gets the percent for bar display.\n   *\/\n  public int getPercent()\n  {\n    return m_percent;\n  }\n\n  \/**\n   * Paints the BarChart using the specified Graphics.\n   *\/\n  public void paintComponent(Graphics g)\n  {\n    super.paintComponent(g);\n    System.out.println(&quot;Painting for new value of &quot; + m_percent);\n    System.out.println(&quot;Width: &quot; + getWidth() + &quot; Height: &quot; + getHeight());\n\n    \/\/ Paint the background color for the bar\n    setBackground(m_floodColor);\n\n    \/\/ Paint the part of the bar that represents the percentage\n    g.setColor(m_fillColor);\n    int y = (getHeight() * (100 - m_percent) \/ 100);\n    int width = getWidth();\n    int height = getHeight() * m_percent \/ 100;\n    System.out.println(&quot;Filling Rectangle at &#x5B;&quot; + 0 + &quot;, &quot; + y + &quot;] Width: &quot; + \n                       width + &quot; Height: &quot; + height);\n    System.out.println(&quot;m_barWidth = &quot; + m_barWidth);\n    g.fillRect(0, y, width, height);\n  }\n\n  \/\/\/\/ Private data \/\/\/\/\n  private int m_percent = 0;\n  private Color m_floodColor = Color.blue;\n  private Color m_fillColor = Color.red;\n  private Color m_borderColor = Color.black;\n  private int m_barWidth = 25;\n  private int m_barHeight = 150;\n  private int m_borderWidth = 2;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">and here is the source for the Java application that displays it:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage javaBeans_0;\n\nimport java.awt.FlowLayout;\nimport java.awt.event.ActionEvent;\nimport java.awt.event.ActionListener;\n\nimport javax.swing.JButton;\nimport javax.swing.JFrame;\nimport javax.swing.JPanel;\n\n\/**\n * BarChartFrame -- a class to display a BarChart Bean.\n *\n * @author Bryan J. Higgs, 12 March, 2000\n *\/\npublic class BarChartFrame extends JFrame\n{\n\n  \/**\n   * Main entry point\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    BarChartFrame frame = new BarChartFrame();\n    frame.setDefaultLookAndFeelDecorated(true);\n    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);\n    frame.setVisible(true);\n  }\n\n  \/**\n   * Constructs a BarChartFrame\n   *\/\n  public BarChartFrame()\n  {\n    setSize(300, 200);\n    setTitle(&quot;Bar Chart&quot;);\n    JPanel contentPane = (JPanel) getContentPane();\n    contentPane.setLayout(new FlowLayout(FlowLayout.CENTER));\n    \n    \/\/ Add the up button, and handle its action event\n    contentPane.add(m_buttonUp);\n    m_buttonUp.addActionListener(\n            new ActionListener()\n    {\n      public void actionPerformed(ActionEvent ev)\n      {\n        m_barChart.setPercent(m_barChart.getPercent() + 10);\n      }\n    }\n    );\n    \n    \/\/ Add the BarChart\n    contentPane.add(m_barChart);\n    \/\/ Add the down button, and handle its action event\n    contentPane.add(m_buttonDown);\n    m_buttonDown.addActionListener(\n            new ActionListener()\n    {\n      public void actionPerformed(ActionEvent ev)\n      {\n        m_barChart.setPercent(m_barChart.getPercent() - 10);\n      }\n    }\n    );\n  }\n\n  \/\/\/\/ Private data \/\/\/\/\n  private BarChart m_barChart = new BarChart();\n  private JButton m_buttonUp = new JButton(&quot;+10%&quot;);\n  private JButton m_buttonDown = new JButton(&quot;-10%&quot;);\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">When the application is run, it produces:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"616\" height=\"418\" src=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/03\/BarChart1.png\" alt=\"\" class=\"wp-image-576\" srcset=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/03\/BarChart1.png 616w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/03\/BarChart1-300x204.png 300w\" sizes=\"auto, (max-width: 616px) 100vw, 616px\" \/><\/figure><\/div>\n\n\n\n<div style=\"height:12px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">When the &#8220;+10%&#8221; button is clicked a couple of times, it will display:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"612\" height=\"418\" src=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/03\/BarChart2.png\" alt=\"\" class=\"wp-image-577\" srcset=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/03\/BarChart2.png 612w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/03\/BarChart2-300x205.png 300w\" sizes=\"auto, (max-width: 612px) 100vw, 612px\" \/><\/figure><\/div>\n\n\n\n<div style=\"height:17px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">So what makes the BarChart class a JavaBean?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Remember that a JavaBean exports&nbsp;<em>properties<\/em>,&nbsp;<em>events<\/em>, and&nbsp;<em>methods<\/em>. It exports properties through public&nbsp;<em>set<\/em>&nbsp;and&nbsp;<em>get<\/em>&nbsp;methods. In this case, there is a single exported property,&nbsp;<strong>percent<\/strong>, which is exported via the methods&nbsp;<strong>setPercent()<\/strong>&nbsp;and&nbsp;<strong>getPercent()<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Another requirement for a JavaBean is that it&nbsp;<em><strong>implement the<\/strong><\/em><strong> java.io.Serializable<\/strong> interface. While the above <strong>BarChart<\/strong> class does not implement Serializable explicitly, it does implement it&nbsp;<em>implicitly<\/em>, by virtue of extending (via <strong>JPanel<\/strong>) class <strong>java.awt.Component<\/strong>, which implements Serializable. All GUI classes extending from <strong>Component<\/strong> are JavaBeans.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Properties\"><\/span>Properties<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Properties are attributes of a bean that are changeable at&nbsp;<em>design time<\/em>&nbsp;(in the IDE), as well as at&nbsp;<em>run time<\/em>. A JavaBean-enabled IDE discovers a bean&#8217;s properties through a process called&nbsp;<em><strong>introspection<\/strong><\/em>. (We&#8217;ll talk more about introspection later.) It will:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Determine a bean&#8217;s properties<\/li><li>Determine each property&#8217;s&#8217; read\/write attributes<\/li><li>Determine each property&#8217;s type<\/li><li>Locate an appropriate&nbsp;<em>property editor<\/em>&nbsp;for each property type<\/li><li>Display the bean&#8217;s properties (usually in a properties window, common called a&nbsp;<em>property sheet<\/em>)<\/li><li>Allow the user to change the bean&#8217;s properties (at design time)<\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Simple_Property_Naming_Patterns\"><\/span>Simple Property Naming Patterns<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Naming patterns are used by the introspection process to determine the properties of a bean. The naming pattern for properties is very simple. Any pair of methods with the signatures:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public <\/strong><em><strong>Type<\/strong><\/em><strong> get<\/strong><em><strong>PropertyName<\/strong><\/em><strong>()<\/strong><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public void set<\/strong><em><strong>PropertyName<\/strong><\/em><strong>(<\/strong><em><strong>Type<\/strong><\/em><strong> t)<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">exports a&nbsp;<em><strong>read\/write<\/strong><\/em>&nbsp;property&nbsp;<em><strong>PropertyName<\/strong><\/em>, of type&nbsp;<em><strong>Type<\/strong><\/em>. For example, in the above BarChart class, there are methods:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public int getPercent()<\/strong><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public void setPercent(int pct)<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">which export a&nbsp;<em><strong>read\/write<\/strong><\/em>&nbsp;property&nbsp;<strong>percent<\/strong>, of type&nbsp;<strong>int<\/strong>, for that bean.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you have a&nbsp;<strong>get<\/strong>&nbsp;method&nbsp;<em>without a corresponding<\/em>&nbsp;<strong>set<\/strong>&nbsp;<em>method<\/em>, then the property is&nbsp;<em><strong>read-only<\/strong><\/em>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Property_Name_Capitalization\"><\/span>Property Name Capitalization<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Note that a pair of get\/set methods:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public int getPercent()<\/strong><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public void setPercent(int pct)<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">define a property&nbsp;<strong>percent<\/strong>&nbsp;(with a&nbsp;<em>lowercase first character<\/em>)<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Get_Methods_for_boolean_Type_Properties\"><\/span>Get Methods for&nbsp;boolean&nbsp;Type Properties<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">To make code read more naturally, a boolean property&#8217;s get method can have the following signature:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public boolean is<\/strong><em><strong>PropertyName<\/strong><\/em><strong>()<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">while the set method signature remains the same. For example:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public boolean isRunning()<\/strong><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public void setRunning(boolean b)<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">would export a&nbsp;<em><strong>read\/write<\/strong><\/em>&nbsp;property&nbsp;<strong>running<\/strong>, of type&nbsp;<strong>boolean<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Simple_Indexed_Properties\"><\/span>Simple &amp; Indexed Properties<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Simple_Properties\"><\/span>Simple Properties<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">A&nbsp;<em>simple property<\/em>&nbsp;is one that takes a single value. The&nbsp;percent&nbsp;property in the&nbsp;BarChart&nbsp;bean is a simple property.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Simple_Property_Naming_Patterns-2\"><\/span>Simple Property Naming Patterns<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The naming pattern for simple properties is any pair of methods with the signatures:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public <\/strong><em><strong>Type<\/strong><\/em><strong> get<\/strong><em><strong>PropertyName<\/strong><\/em><strong>()<\/strong><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public void set<\/strong><em><strong>PropertyName<\/strong><\/em><strong>(<\/strong><em><strong>Type<\/strong><\/em><strong> t)<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">which exports a&nbsp;<em><strong>read\/write<\/strong><\/em>&nbsp;simple property&nbsp;<em><strong>PropertyName<\/strong><\/em>, of type&nbsp;<em><strong>Type<\/strong><\/em>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A&nbsp;<strong>get<\/strong>&nbsp;method&nbsp;<em>without a corresponding<\/em>&nbsp;<strong>set<\/strong>&nbsp;<em>method<\/em>&nbsp;exports a&nbsp;<em><strong>read-only<\/strong><\/em>&nbsp;property.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Indexed_Properties\"><\/span>Indexed Properties<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">An indexed property is one whose value is an array.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Indexed_Property_Naming_Patterns\"><\/span>Indexed Property Naming Patterns<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The naming pattern for indexed properties is any pair of methods with the signatures:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public <\/strong><em><strong>Type<\/strong><\/em><strong>[] get<\/strong><em><strong>PropertyName<\/strong><\/em><strong>()<\/strong><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public void set<\/strong><em><strong>PropertyName<\/strong><\/em><strong>(<\/strong><em><strong>Type<\/strong><\/em><strong>[] t)<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">which exports a&nbsp;<em><strong>read\/write<\/strong><\/em>&nbsp;indexed property&nbsp;<em><strong>PropertyName<\/strong><\/em>, of type&nbsp;<em><strong>Type<\/strong><\/em><strong>[]<\/strong>. For example, a Bean that implements a graphical chart, might have methods:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public double[] getValues()<\/strong><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public void setValues(double[] values)<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">which export a&nbsp;<em><strong>read\/write<\/strong><\/em>&nbsp;indexed property&nbsp;<strong>values<\/strong>, of type&nbsp;<strong>double[]<\/strong>. The values could be the values being graphed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A&nbsp;<strong>get<\/strong>&nbsp;method&nbsp;<em>without a corresponding<\/em>&nbsp;<strong>set<\/strong>&nbsp;<em>method&nbsp;<\/em>exports a&nbsp;<em><strong>read-only<\/strong><\/em>&nbsp;indexed property.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Individual elements in the indexed property array may be got and set, using methods with the following signatures:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public <\/strong><em><strong>Type<\/strong><\/em><strong> get<\/strong><em><strong>PropertyName<\/strong><\/em><strong>(int index)<\/strong><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public void set<\/strong><em><strong>PropertyName<\/strong><\/em><strong>(int index, <\/strong><em><strong>Type<\/strong><\/em><strong> t)<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">where&nbsp;index&nbsp;is the (0-based) index into the array. Since these methods index into the array of property values, it is possible for an&nbsp;ArrayIndexOutOfBoundsException&nbsp;to occur. Therefore, you may declare them as follows, if you wish:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public <\/strong><em><strong>Type<\/strong><\/em><strong> get<\/strong><em><strong>PropertyName<\/strong><\/em><strong>(int index)\n\tthrows ArrayIndexOutOfBoundsException<\/strong><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public void set<\/strong><em><strong>PropertyName<\/strong><\/em><strong>(int index, <\/strong><em><strong>Type<\/strong><\/em><strong> t)<\/strong>\n<strong>\tthrows ArrayIndexOutOfBoundsException<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">(Note that&nbsp;<strong>ArrayIndexOutOfBoundsException<\/strong>&nbsp;is a&nbsp;<strong>RuntimeException<\/strong>, and so is unchecked; consequently, you don&#8217;t have to declare it, even if the method can throw it.)<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Example_A_SimpleScatterPlot_Bean\"><\/span>Example: A SimpleScatterPlot Bean<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s an example that shows the use of both simple and indexed properties &#8212; a <em><strong>Simple Scatter Plot bean<\/strong><\/em>. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The code for the Bean is as follows. It&#8217;s rather long. You don&#8217;t really have to study the&nbsp;paint()&nbsp;method and other related methods. Instead, concentrate on the get\/set methods for now.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage javaBeans;\n\nimport java.awt.Color;\nimport java.awt.Dimension;\nimport java.awt.Graphics;\nimport java.awt.Point;\nimport java.awt.Rectangle;\n\nimport java.util.Random;\nimport javax.swing.JPanel;\n\n\/**\n * A class that implements a simple scatter plot Java Bean.\n *\n * @author Bryan J. Higgs, 6 April 2000\n *\/\npublic class SimpleScatterPlot extends JPanel\n{\n  \/**\n   * Constructor\n   *\/\n  public SimpleScatterPlot()\n  {\n    m_title = &quot;Simple Scatter Plot&quot;;\n    setBackground(Color.lightGray);\n  }\n\n  \/\/\/\/ Set\/get properties \/\/\/\/\n  \/**\n   * Gets the array of points being displayed.\n   *\/\n  public Point&#x5B;] getPoints()\n  {\n    return m_points;\n  }\n\n  \/**\n   * Sets the array of points to be displayed. Causes the display to be\n   * automatically refreshed.\n   *\/\n  public void setPoints(Point&#x5B;] points)\n  {\n    m_points = points;\n    m_autoRangingDone = false;\n    repaint();\n  }\n\n  \/**\n   * Gets the i-th (0-based) point being displayed.\n   *\n   * @return the Point, or null if the index is out of range.\n   *\/\n  public Point getPoints(int i)\n  {\n    Point p = null;\n    if (m_points != null &amp;&amp; i &gt;= 0 &amp;&amp; i &lt; m_points.length)\n    {\n      p = m_points&#x5B;i];\n    }\n    return p;\n  }\n\n  \/**\n   * Sets the i-th point being displayed. If i represents one of the existing\n   * points, it is replaced. If i represents a point immediately after the last\n   * point, then it is added to the end, becoming the new last point. Otherwise,\n   * an IllegalArgumentException is thrown.\n   *\/\n  public void setPoints(int i, Point p)\n  {\n    if (m_points != null)\n    {\n      int currentSize = m_points.length;\n      if (i &gt;= 0 &amp;&amp; i &lt; currentSize)\n      {\n        \/\/ Replace an existing point\n        m_points&#x5B;i] = p;\n        m_autoRangingDone = false;\n        repaint();\n        return;\n      }\n      else if (i &gt; currentSize)\n      {\n        \/\/ We can&#039;t add this, since it would\n        \/\/ create a null entry.\n        throw new IllegalArgumentException();\n      }\n    }\n\n    \/\/ Add a new point\n    addPoint(p);\n  }\n\n  \/**\n   * Adds a point to the existing array of points to be displayed.\n   *\/\n  public void addPoint(Point p)\n  {\n    if (m_points == null)\n    {\n      m_points = new Point&#x5B;1];\n      m_points&#x5B;0] = p;\n    }\n    else\n    {\n      int currentSize = m_points.length;\n      Point&#x5B;] newArray = new Point&#x5B;currentSize + 1];\n      System.arraycopy(m_points, 0, \/\/ from\n              newArray, 0, \/\/ to\n              currentSize \/\/ size\n      );\n      m_points = newArray;\n      m_points&#x5B;currentSize] = p;\n    }\n\n    m_autoRangingDone = false;\n    repaint();\n  }\n\n  \/*\n    *   Gets the number of points currently being displayed.\n   *\/\n  public int getPointCount()\n  {\n    int count = 0;\n    if (m_points != null)\n    {\n      count = m_points.length;\n    }\n    return count;\n  }\n\n  \/**\n   * Gets the scatter plot title.\n   *\/\n  public String getTitle()\n  {\n    return m_title;\n  }\n\n  \/**\n   * Sets the scatter plot title. Refreshes the display.\n   *\/\n  public void setTitle(String title)\n  {\n    m_title = title;\n    repaint();\n  }\n\n  \/**\n   * Gets the current title text color.\n   *\/\n  public Color getTitleColor()\n  {\n    return m_titleColor;\n  }\n\n  \/**\n   * Sets the title text color. Refreshes the display.\n   *\/\n  public void setTitleColor(Color color)\n  {\n    m_titleColor = color;\n    repaint();\n  }\n\n  \/**\n   * Gets the current plot background color.\n   *\/\n  public Color getPlotBackColor()\n  {\n    return m_plotBackColor;\n  }\n\n  \/**\n   * Sets the plot background color. Refreshes the display.\n   *\/\n  public void setPlotBackColor(Color color)\n  {\n    m_plotBackColor = color;\n    repaint();\n  }\n\n  \/**\n   * Gets the current point display color.\n   *\/\n  public Color getPointColor()\n  {\n    return m_pointColor;\n  }\n\n  \/**\n   * Sets the point display color.\n   *\/\n  public void setPointColor(Color color)\n  {\n    m_pointColor = color;\n    repaint();\n  }\n\n  \/**\n   * Gets the current grid color.\n   *\/\n  public Color getGridColor()\n  {\n    return m_gridColor;\n  }\n\n  \/**\n   * Sets the grid color. Refreshes the display.\n   *\/\n  public void setGridColor(Color color)\n  {\n    m_gridColor = color;\n    repaint();\n  }\n\n  \/**\n   * Gets the current plot bounds.\n   *\/\n  public PlotBounds getPlotBounds()\n  {\n    return m_bounds;\n  }\n\n  \/**\n   * Sets the plot bounds. Refreshes the display.\n   *\/\n  public void setPlotBounds(PlotBounds bounds)\n  {\n    m_bounds = bounds;\n    m_autoRangingDone = false;\n    repaint();\n  }\n\n  \/**\n   * Gets whether auto-ranging is turned on for the x direction.\n   *\/\n  public boolean isAutoRangeX()\n  {\n    return m_autoRangeX;\n  }\n\n  \/**\n   * Sets auto-ranging on or off for the x direction. Refreshes the display.\n   *\/\n  public void setAutoRangeX(boolean autoRangeX)\n  {\n    m_autoRangeX = autoRangeX;\n    m_autoRangingDone = false;\n    repaint();\n  }\n\n  \/**\n   * Gets whether auto-ranging is turned on for the y direction.\n   *\/\n  public boolean isAutoRangeY()\n  {\n    return m_autoRangeY;\n  }\n\n  \/**\n   * Sets auto-ranging on or off for the y direction. Refreshes the display.\n   *\/\n  public void setAutoRangeY(boolean autoRangeY)\n  {\n    m_autoRangeY = autoRangeY;\n    m_autoRangingDone = false;\n    repaint();\n  }\n\n  \/**\n   * Gets whether the gird should be shown.\n   *\/\n  public boolean isShowGrid()\n  {\n    return m_showGrid;\n  }\n\n  \/**\n   * Sets the display of the grid on or off. Refreshes the display.\n   *\/\n  public void setShowGrid(boolean showGrid)\n  {\n    m_showGrid = showGrid;\n    repaint();\n  }\n\n  \/**\n   * Sets the preferred size for the scatter plot canvas.\n   *\/\n  public Dimension getPreferredSize()\n  {\n    if (m_preferredSize == null)\n    {\n      m_preferredSize = new Dimension(300, 300);\n    }\n    return m_preferredSize;\n  }\n\n  \/**\n   * Sets the preferred size for the scatter plot canvas. Refreshes the display.\n   *\/\n  public void setPreferredSize(Dimension d)\n  {\n    m_preferredSize = d;\n    repaint();\n  }\n\n  \/**\n   * Paints the scatter plot canvas.\n   *\/\n  public void paintComponent(Graphics g)\n  {\n    super.paintComponent(g);\n    \/\/ Get information necessary to paint\n    Dimension size = getSize();\n    int width = size.width;\n    int height = size.height;\n\n    paintTitle(g, width, height);\n\n    autoRange();\n\n    \/\/ Create a new clipped area to draw the actual plot into.\n    Graphics area\n            = g.create((int) ((width \/ 10.0) + 0.5),\n                    (int) ((height \/ 10.0) + 0.5),\n                    (int) ((width * 8.0 \/ 10.0) + 0.5),\n                    (int) ((height * 8.0 \/ 10.0) + 0.5)\n            );\n\n    plotPoints(area);\n\n    if (isShowGrid())\n    {\n      paintGrid(area);\n    }\n\n    \/\/ Draw rectangle around the plot\n    Rectangle rect = area.getClipBounds();\n    area.setColor(Color.black);\n    area.drawRect(0, 0, rect.width - 1, rect.height - 1);\n  }\n\n  \/\/\/\/ Protected methods \/\/\/\/\n  \/**\n   * Paints the title text.\n   *\/\n  protected void paintTitle(Graphics g, int width, int height)\n  {\n    \/\/ Baseline at 7% from top\n    int baseline = height * 7 \/ 100;\n    int titleWidth = getFontMetrics(getFont()).stringWidth(m_title);\n    int xStart = (width - titleWidth) \/ 2;\n\n    if (xStart &lt; 0)\n    {\n      xStart = 0;\n    }\n\n    g.setColor(m_titleColor);\n    g.drawString(m_title, xStart, baseline);\n  }\n\n  \/**\n   * Determines and sets the bounds from the set of points being displayed.\n   *\/\n  protected void autoRange()\n  {\n    \/\/ If there are points, and we&#039;re autoranging, do the work...\n    \/\/ (If autoranging has been done, don&#039;t bother doing it again.)\n    if (m_points != null\n            &amp;&amp; !m_autoRangingDone\n            &amp;&amp; (m_autoRangeX || m_autoRangeY))\n    {\n      if (m_autoRangeX)\n      {\n        m_bounds.setXMin(m_points&#x5B;0].x);\n        m_bounds.setXMax(m_points&#x5B;0].x);\n      }\n      if (m_autoRangeY)\n      {\n        m_bounds.setYMin(m_points&#x5B;0].y);\n        m_bounds.setYMax(m_points&#x5B;0].y);\n      }\n      for (int i = 1; i &lt; getPointCount(); i++)\n      {\n        if (m_autoRangeX)\n        {\n          if (m_points&#x5B;i].x &lt; m_bounds.getXMin())\n          {\n            m_bounds.setXMin(m_points&#x5B;i].x);\n          }\n          if (m_points&#x5B;i].x &gt; m_bounds.getXMax())\n          {\n            m_bounds.setXMax(m_points&#x5B;i].x);\n          }\n        }\n        if (m_autoRangeY)\n        {\n          if (m_points&#x5B;i].y &lt; m_bounds.getYMin())\n          {\n            m_bounds.setYMin(m_points&#x5B;i].y);\n          }\n          if (m_points&#x5B;i].y &gt; m_bounds.getYMax())\n          {\n            m_bounds.setYMax(m_points&#x5B;i].y);\n          }\n        }\n      }\n\n      m_autoRangingDone = true;\n    }\n  }\n\n  \/**\n   * Plots the points on the scatter plot.\n   *\/\n  protected void plotPoints(Graphics g)\n  {\n    Rectangle rect = g.getClipBounds();\n\n    \/\/ Set window for graphics\n    int height = rect.height;\n    int width = rect.width;\n\n    \/\/ Fill background\n    g.setColor(m_plotBackColor);\n    g.fillRect(0, 0, width - 1, height - 1);\n\n    Point thePoint;\n    for (int i = 0; i &lt; getPointCount(); i++)\n    {\n      thePoint = getPoints(i);\n\n      \/\/ Figure out where the point goes.\n      \/\/ If autoscaling is on along one axis, we extend\n      \/\/ the scale by 10% so points don&#039;t end up\n      \/\/ being cut off by the graph edges.\n      double dyExpand = m_autoRangeY ? 1.1 : 1.0;\n      int y = height\n              - (int) (height * thePoint.y \/ (m_bounds.getYMax() * dyExpand));\n\n      double dxExpand = m_autoRangeX ? 1.1 : 1.0;\n      int x\n              = (int) (width * thePoint.x \/ (m_bounds.getXMax() * dxExpand));\n\n      \/\/ Draw points.\n      g.setColor(m_pointColor);\n      g.fillRect(x - 4, y - 4, 8, 8); \/\/ Draw a colored rectangle &#039;point&#039;.\n    }\n  }\n\n  \/**\n   * Paints the scatter plot grid.\n   *\/\n  protected void paintGrid(Graphics g)\n  {\n    Rectangle rect = g.getClipBounds();\n    if (!m_showGrid)\n    {\n      return;\n    }\n\n    \/\/ Set window for graphics\n    int height = rect.height;\n    int width = rect.width;\n\n    if (m_xTic == 0)\n    {\n      m_xTic = ((m_bounds.getXMax() - m_bounds.getXMin()) \/ 5);\n    }\n    if (m_xTic == 0)\n    {\n      m_xTic = 10;\n    }\n\n    if (m_yTic == 0)\n    {\n      m_yTic = ((m_bounds.getYMax() - m_bounds.getYMin()) \/ 5);\n    }\n    if (m_yTic == 0)\n    {\n      m_yTic = 10;\n    }\n\n    \/\/ Draw x grid lines\n    g.setColor(m_gridColor);\n\n    int xRange = m_bounds.getXMax() - m_bounds.getXMin();\n    if (xRange == 0)\n    {\n      xRange = 100;\n    }\n    double xPixPerUnit = width \/ xRange;\n\n    for (int xval = 0; xval &lt;= m_bounds.getXMax(); xval += m_xTic)\n    {\n      int xpos = (int) (xval * xPixPerUnit);\n      g.drawLine(xpos, 0, xpos, height);\n    }\n\n    \/\/ Draw y grid lines\n    int yRange = m_bounds.getYMax() - m_bounds.getYMin();\n    if (yRange == 0)\n    {\n      yRange = 100;\n    }\n    double yPixPerUnit = height \/ yRange;\n\n    for (int yval = 0; yval &lt;= m_bounds.getYMax(); yval += m_yTic)\n    {\n      int ypos = (int) (yval * yPixPerUnit);\n      g.drawLine(0, ypos, width, ypos);\n    }\n  }\n\n  \/\/\/\/ Private data \/\/\/\/\n  private String m_title;\n  private Point m_points&#x5B;];\n  private PlotBounds m_bounds = new PlotBounds(0, 0, 0, 0);\n  private boolean m_showGrid = true;\n  private boolean m_autoRangeY = true;\n  private boolean m_autoRangeX = true;\n\n  private Color m_titleColor = Color.black;\n  private Color m_plotBackColor = Color.white;\n  private Color m_pointColor = Color.green;\n  private Color m_gridColor = Color.gray;\n\n  private int m_xTic = 0;\n  private int m_yTic = 0;\n\n  private Dimension m_preferredSize;\n  private boolean m_autoRangingDone = false;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Here is the <strong>PlotBounds<\/strong> class that it uses:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage javaBeans;\n\n\/**\n * A class to represent the bounds of a scatter plot.\n *\n * @author Bryan J. Higgs, 6 April, 2000\n *\/\npublic class PlotBounds\n{\n  \/**\n   * Constructor\n   *\/\n  public PlotBounds(int xMin, int yMin, int xMax, int yMax)\n  {\n    m_xMin = xMin;\n    m_yMin = yMin;\n    m_xMax = xMax;\n    m_yMax = yMax;\n  }\n\n  public int getXMin()\n  {\n    return m_xMin;\n  }\n\n  public void setXMin(int x)\n  {\n    m_xMin = x;\n  }\n\n  public int getYMin()\n  {\n    return m_yMin;\n  }\n\n  public void setYMin(int y)\n  {\n    m_yMin = y;\n  }\n\n  public int getXMax()\n  {\n    return m_xMax;\n  }\n\n  public void setXMax(int x)\n  {\n    m_xMax = x;\n  }\n\n  public int getYMax()\n  {\n    return m_yMax;\n  }\n\n  public void setYMax(int y)\n  {\n    m_yMax = y;\n  }\n\n  \/\/\/\/ Private Data \/\/\/\/\n  private int m_xMin = 0;     \/\/ The minimum x value\n  private int m_yMin = 0;     \/\/ The minimum y value\n  private int m_xMax = 0;     \/\/ The maximum x value\n  private int m_yMax = 0;     \/\/ The maximum y value\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">and finally, the test program that displays it:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage javaBeans;\n\nimport java.awt.BorderLayout;\nimport java.awt.Point;\nimport java.awt.event.WindowAdapter;\nimport java.awt.event.WindowEvent;\n\nimport javax.swing.JFrame;\nimport javax.swing.JPanel;\nimport static javax.swing.WindowConstants.EXIT_ON_CLOSE;\n\n\/**\n * A class to test the SimpleScatterPlot Java Bean.\n *\n * @author Bryan J. Higgs, 6 April, 2000\n *\/\npublic class TestSimpleScatterPlot\n{\n  \/**\n   * Main entry point\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    JFrame frame = new JFrame(&quot;Simple Scatter Plot Bean&quot;);\n    JPanel panel = (JPanel) frame.getContentPane();\n    panel.setLayout( new BorderLayout() );\n    \/\/ Create the scatter plot\n    SimpleScatterPlot p = new SimpleScatterPlot();\n    \/\/ Specify the set of points for it to display\n    p.setPoints(m_points);\n    \/\/ Add it to the content panel\n    panel.add(p, BorderLayout.CENTER);\n    \/\/ Autosize the Frame, based on its contents.\n    frame.pack();\n    \n    frame.setDefaultLookAndFeelDecorated(true);\n    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);\n    \/\/ Finally, make it visible.\n    frame.setVisible(true);\n  }\n\n  \/\/\/\/ Private Data \/\/\/\/\n  \/**\n   * The set of points to display.\n   *\/\n  private static final Point&#x5B;] m_points =\n  {\n    new Point(10, 12),\n    new Point(5, 5),\n    new Point(15, 22),\n    new Point(21, 24),\n    new Point(12, 9),\n    new Point(18, 44)\n  };\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">This produces the following:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"614\" height=\"672\" src=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/03\/SimpleScatterPlot.png\" alt=\"\" class=\"wp-image-581\" srcset=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/03\/SimpleScatterPlot.png 614w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/03\/SimpleScatterPlot-274x300.png 274w\" sizes=\"auto, (max-width: 614px) 100vw, 614px\" \/><\/figure><\/div>\n\n\n\n<div style=\"height:23px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">You can use such Java Beans within a Java IDE, and the IDE will recognize the properties, and, if supports a property editor (about which more later), allow you to change their values, and include them in visual components.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Bound_Properties\"><\/span>Bound Properties<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">When the value of a Bean property changes, it&#8217;s sometimes useful for interested Bean listeners to be informed of those changes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Bound properties<\/em>&nbsp;tell these interested listeners when their value changes. They cause events to be sent to those interested listeners when a value changes, to allow those listeners to take some appropriate action in response. For example, a SpreadSheet Bean might tell a PieChart bean to redraw itself whenever the spreadsheet changes.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Bound_Property_Requirements\"><\/span>Bound Property Requirements<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">To implement a bound property, you must follow the normal property naming conventions, and also implement the following:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>The Bean must implement the following two methods to allow other classes to register as&nbsp;<strong>PropertyChangeListener<\/strong><strong>s<\/strong>:<strong>public void addPropertyChangeListener( PropertyChangeListener listener)<\/strong><strong>public void removePropertyChangeListener( PropertyChangeListener listener)<\/strong><\/li><li>Whenever the value of the bound property changes, the Bean must send a&nbsp;<strong>PropertyChangeEvent<\/strong>&nbsp;to all registered listeners<\/li><\/ol>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_PropertyChangeListener_Interface\"><\/span>The&nbsp;PropertyChangeListener&nbsp;Interface<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The&nbsp;<strong>PropertyChangeListener<\/strong>&nbsp;interface has a single method:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public void propertyChange(PropertyChangeEvent evt)<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">When a class implements this interface, it must implement this method. The method is called, if the class is registered as a&nbsp;<strong>PropertyChangeListener<\/strong>, when it receives a&nbsp;<strong>PropertyChangeEvent<\/strong>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_PropertyChangeSupport_Class\"><\/span>The&nbsp;PropertyChangeSupport&nbsp;Class<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The java.beans package contains a convenience class,&nbsp;<strong>PropertyChangeSupport<\/strong>, that makes it trivial to write the&nbsp;<strong>addPropertyChangeListener<\/strong>&nbsp;and&nbsp;<strong>removePropertyChangeListener<\/strong>&nbsp;methods:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>private void PropertyChangeSupport m_changeSupport =\n\tnew PropertyChangeSupport(this);<\/strong><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public void addPropertyChangeListener(PropertyChangeListener l)\n{\n    m_changeSupport.addPropertyChangeListener(l);\n}<\/strong><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public void removePropertyChangeListener(PropertyChangeListener l)\n{\n    m_changeSupport.removePropertyChangeListener(l);\n}<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>PropertyChangeSupport<\/strong>&nbsp;also makes it simple to &#8220;fire&#8221; a&nbsp;<strong>PropertyChangeEvent<\/strong>:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>m_changeSupport.firePropertyChange(propertyName,\n\t\t\t\t   oldValue,\n\t\t\t\t   newValue);<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the property has a primitive type, then you must &#8220;wrap&#8221; the values:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>m_changeSupport.firePropertyChange(propertyName,\n\t\t\t\t   new Integer(oldValue),\n\t\t\t\t   new Integer(newValue));<\/strong><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Example_A_New_BarChart_Bean\"><\/span>Example: A New BarChart Bean<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The example is an extension of the earlier BarChart bean.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The program is similar to the previous BarChart example, but in place of the two buttons, it now has an input text field to supply the value for the bar chart.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The input text field is an&nbsp;<strong>JFormattedTextField<\/strong>&nbsp;bean, which is restricted to integer values. Whenever the value is changed (enter a new value, and hit Enter, or Tab), it will cause the bar chart to display appropriately. This is implemented using a <em>bound property<\/em> &#8220;value&#8221; supplied by the&nbsp;<strong><strong>JFormattedTextField<\/strong>&nbsp;<\/strong>bean, and the use of a <strong>PropertyChangeListener<\/strong> in the&nbsp;<strong>BarChart<\/strong>&nbsp;bean.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the code for the <strong>BarChart<\/strong> bean:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage javaBeans_1;\n\nimport java.awt.Color;\nimport java.awt.Dimension;\nimport java.awt.Graphics;\n\nimport java.beans.PropertyChangeEvent;\nimport java.beans.PropertyChangeListener;\n\nimport javax.swing.BorderFactory;\nimport javax.swing.JPanel;\n\n\/**\n * A BarChart JavaBean class.\n *\n * @author Bryan J. Higgs, 12 March, 2000\n *\/\npublic class BarChart extends JPanel\n        implements PropertyChangeListener\n{\n  \/**\n   * Constructs a BarChart instance\n   *\/\n  public BarChart()\n  {\n    setPreferredSize(new Dimension(m_barWidth, m_barHeight));\n    setBorder(BorderFactory.createLineBorder(m_borderColor, m_borderWidth));\n    System.out.println(&quot;m_barWidth = &quot; + m_barWidth);\n  }\n\n  \/\/\/\/ Accessor methods \/\/\/\/\n  \/**\n   * Sets the percent for bar display.\n   *\/\n  public void setPercent(int percent)\n  {\n    if (percent &lt;= 100 &amp;&amp; percent &gt;= 0)\n    {\n      m_percent = percent;\n      repaint();\n    }\n  }\n\n  \/**\n   * Gets the percent for bar display.\n   *\/\n  public int getPercent()\n  {\n    return m_percent;\n  }\n\n  \/\/ Respond to a property change event for the property\n  \/\/ &quot;value&quot; by updating my value to a new value.\n  public void propertyChange(PropertyChangeEvent event)\n  {\n    System.out.println(&quot;Property changed!&quot;);\n    String propertyName = event.getPropertyName();\n    if (propertyName.equals(&quot;value&quot;))\n    {\n      System.out.println(&quot;Property &#039;&quot; + propertyName + &quot;&#039; changed.&quot;);\n      Object newValue = event.getNewValue();\n      int value = ((Number) newValue).intValue();\n      System.out.println(&quot;New value = &quot; + value);\n      setPercent(value);\n    }\n  }\n\n  \/**\n   * Paints the BarChart using the specified Graphics.\n   *\/\n  public void paintComponent(Graphics g)\n  {\n    super.paintComponent(g);\n    System.out.println(&quot;Painting for new value of &quot; + m_percent);\n    System.out.println(&quot;Width: &quot; + getWidth() + &quot; Height: &quot; + getHeight());\n\n    \/\/ Paint the background color for the bar\n    setBackground(m_floodColor);\n\n    \/\/ Paint the part of the bar that represents the percentage\n    g.setColor(m_fillColor);\n    int y = (getHeight() * (100 - m_percent) \/ 100);\n    int width = getWidth();\n    int height = getHeight() * m_percent \/ 100;\n    System.out.println(&quot;Filling Rectangle at &#x5B;&quot; + 0 + &quot;, &quot; + y + &quot;] Width: &quot; + \n                       width + &quot; Height: &quot; + height);\n    System.out.println(&quot;m_barWidth = &quot; + m_barWidth);\n    g.fillRect(0, y, width, height);\n  }\n\n  \/\/\/\/ Private data \/\/\/\/\n  private int m_percent = 0;\n  private Color m_floodColor = Color.blue;\n  private Color m_fillColor = Color.red;\n  private Color m_borderColor = Color.black;\n  private int m_barWidth = 25;\n  private int m_barHeight = 150;\n  private int m_borderWidth = 2;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Finally, the code for the&nbsp;<strong>BarChartFrame<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage javaBeans_1;\n\nimport java.awt.BorderLayout;\nimport java.awt.Color;\nimport java.awt.Panel;\nimport java.awt.Rectangle;\nimport java.awt.event.ComponentAdapter;\nimport java.awt.event.ComponentEvent;\nimport java.text.NumberFormat;\nimport javax.swing.JFormattedTextField;\n\nimport javax.swing.JFrame;\nimport javax.swing.JPanel;\n\n\/**\n * The BarChartFrame contains two beans: BarChart and JFormattedTextField.\n *\n * @author Bryan J. Higgs, 8 April, 2021\n *\/\npublic class BarChartFrame extends JFrame\n{\n\n  \/**\n   * Main entry point\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    BarChartFrame frame = new BarChartFrame();\n    frame.setDefaultLookAndFeelDecorated(true);\n    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);\n    frame.setVisible(true);\n  }\n\n  \/**\n   * Constructor\n   *\/\n  public BarChartFrame()\n  {\n    setSize(300, 250);\n    setTitle(&quot;Color Bar Frame&quot;);\n\n    \/\/ Initialize the beans\n    m_barChart.setPercent(0);\n    m_intBox.setText(&quot;0&quot;);\n    m_intBox.setEditable(true);\n\n    JPanel contentPane = (JPanel) getContentPane();\n    contentPane.setLayout(new BorderLayout());\n\n    JPanel panel = new JPanel();\n    panel.add(m_barChart);\n\n    contentPane.add(panel, BorderLayout.CENTER);\n    contentPane.add(m_intBox, BorderLayout.SOUTH);\n\n    \/\/ Set the BarChart to listen for property change events for the\n    \/\/ JFormattedTextField &#039;value&#039; property.\n    m_intBox.addPropertyChangeListener(&quot;value&quot;, m_barChart);\n\n  }\n\n  \/\/\/\/ Private Data \/\/\/\/\n  private static BarChart m_barChart = new BarChart();\n  private static JFormattedTextField m_intBox\n          = new JFormattedTextField( NumberFormat.getIntegerInstance() );\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">When run, this application shows a window like this (I&#8217;ve entered 40 into the text box):<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"632\" height=\"536\" src=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/04\/Screen-Shot-2021-04-08-at-1.57.42-PM.png\" alt=\"\" class=\"wp-image-595\" srcset=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/04\/Screen-Shot-2021-04-08-at-1.57.42-PM.png 632w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/04\/Screen-Shot-2021-04-08-at-1.57.42-PM-300x254.png 300w\" sizes=\"auto, (max-width: 632px) 100vw, 632px\" \/><\/figure><\/div>\n\n\n\n<div style=\"height:17px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Note that I have left in the code some debugging prints that can show you what&#8217;s happening.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Constrained_Properties\"><\/span>Constrained Properties<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A Bean can be set up to listen for a property value change and &#8220;make a fuss&#8221; if the value is not to its liking. In fact, the listener can prevent the property change from happening, by&nbsp;<em>vetoing<\/em>&nbsp;it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A property that is prepared to handle this is called a&nbsp;<em>constrained property<\/em>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Constrained_Property_Requirements\"><\/span>Constrained Property Requirements<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">A constrained property is also a bound property (a constrained property that is not a bound property doesn&#8217;t make much sense, as you&#8217;ll see).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To implement a constrained property, you must follow the normal bound property naming conventions, and also implement the following:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>The Bean must implement the following two methods to allow other classes to register as&nbsp;<strong>VetoableChangeListeners<\/strong>:<br><strong>public void addVetoableChangeListener( <\/strong><br>                           <strong>VetoableChangeListener listener)<\/strong><br><strong>public void removeVetoableChangeListener( <\/strong><br>                            <strong>VetoableChangeListener listener)<\/strong><\/li><li>Whenever the value of the constrained property changes, the Bean must send a&nbsp;<strong>PropertyChangeEvent<\/strong>&nbsp;to all registered<strong> VetoableChangeListeners.<\/strong><\/li><\/ol>\n\n\n\n<h5 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_VetoableChangeListener_Interface\"><\/span>The&nbsp;VetoableChangeListener&nbsp;Interface<span class=\"ez-toc-section-end\"><\/span><\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">The&nbsp;<strong>VetoableChangeListener<\/strong>&nbsp;interface has a single method:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public void vetoableChange(PropertyChangeEvent evt) \n\t\tthrows PropertyVetoException<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">When a class implements this interface, it must implement this method. The method is called, if the class is registered as a&nbsp;<strong>VetoableChangeListener<\/strong>, when it receives a&nbsp;<em>vetoable<\/em>&nbsp;<strong>PropertyChangeEvent<\/strong>.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_VetoableChangeSupport_Class\"><\/span>The&nbsp;VetoableChangeSupport&nbsp;Class<span class=\"ez-toc-section-end\"><\/span><\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">In a manner similar to the case of&nbsp;<strong>PropertyChangeListener<\/strong>s, the java.beans&nbsp;package contains a convenience class, <strong>VetoableChangeSupport<\/strong>, that makes it trivial to write the <strong>addVetoableChangeListener<\/strong> and <strong>removeVetoableChangeListener<\/strong> methods:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>private void <\/strong><strong>Vetoable<\/strong><strong>ChangeSupport m_vetoSupport =\n\tnew <\/strong><strong>Vetoable<\/strong><strong>ChangeSupport(this);<\/strong><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public void add<\/strong><strong>Vetoable<\/strong><strong>ChangeListener(<\/strong><strong>Vetoable<\/strong><strong>ChangeListener l)\n{\n    m_vetoSupport.add<\/strong><strong>Vetoable<\/strong><strong>ChangeListener(l);\n}<\/strong><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>public void remove<\/strong><strong>Vetoable<\/strong><strong>ChangeListener(<\/strong><strong>Vetoable<\/strong><strong>ChangeListener l)\n{\n    m_vetoSupport.remove<\/strong><strong>Vetoable<\/strong><strong>ChangeListener(l);\n}<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>VetoableChangeSupport<\/strong>&nbsp;also makes it simple to &#8220;fire&#8221; a vetoable&nbsp;<strong>PropertyChangeEvent<\/strong>:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>m_vetoSupport.fireVetoableChange(propertyName,\n\t\t\t   \t oldValue,\n\t\t\t\t newValue);<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">As before, if the property has a primitive type, then you must &#8220;wrap&#8221; the values:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>m_vetoSupport.firePropertyChange(propertyName,\n\t\t\t\t new Integer(oldValue),\n\t\t\t\t new Integer(newValue));<\/strong><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Example_A_BarChart_with_a_Constrained_Property\"><\/span><strong>Example: A&nbsp;BarChart with a Constrained Property<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The example is a modification of the earlier <strong>BarChart<\/strong> Bean. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Previously, you could set the <strong>JFormattedTextField <\/strong>to contain a value outside the range 0 &#8211; 100. If you did that, the <strong>BarChart<\/strong> would check for an invalid value, and ignore any invalue value you&#8217;re trying to set.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this version, when you attempt to enter a value outside the range, the previous value is forced back into the JFormattedTextField, reverting to its former value.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is implemented using a <em>constrainted property<\/em> in the&nbsp;<strong>JFormattedTextField<\/strong>, and a <strong>VetoableChangeListener<\/strong> in the <strong>BarChart<\/strong> Bean.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>NOTE:<br>I really struggled coming up with this example. The main sticking point was figuring out how to cause the JFormattedTextField to revert back to its original value. What I came up with is, admittedly, somewhat of a kludge. It works, but I&#8217;m not happy with it. It causes too many property change events, and I had to expose knowledge of the property source (owner) to the BarChart. Consequently, the example is somewhat convoluted, which you&#8217;ll see if you study it. If you run the example, you&#8217;ll see some output which might help you figure out what&#8217;s happening.<br><br>Note also that the example depends on JFormattedTextField being a bean, and exposing a number of Javabean interfaces.<br><br>It should go without saying that this example will take a fair amount of study to understand&#8230;<\/p><\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the code for the <strong>BarChart<\/strong>&nbsp;Bean:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\npackage javaBeans_2;\n\nimport java.awt.Color;\nimport java.awt.Component;\nimport java.awt.Dimension;\nimport java.awt.Graphics;\n\nimport java.beans.PropertyChangeEvent;\nimport java.beans.PropertyChangeListener;\nimport java.beans.PropertyChangeSupport;\nimport java.beans.PropertyVetoException;\nimport java.beans.VetoableChangeListener;\nimport java.beans.VetoableChangeSupport;\n\nimport javax.swing.BorderFactory;\nimport javax.swing.JFormattedTextField;\nimport javax.swing.JPanel;\nimport javax.swing.event.ChangeListener;\n\n\/**\n * A BarChart JavaBean class.\n *\n * @author Bryan J. Higgs, 8 April, 2021\n *\/\npublic class BarChart extends JPanel\n        implements PropertyChangeListener,\n                   VetoableChangeListener\n{\n  \/**\n   * Constructs a BarChart instance\n   *\/\n  public BarChart()\n  {\n    setPreferredSize(new Dimension(m_barWidth, m_barHeight));\n    setBorder(BorderFactory.createLineBorder(m_borderColor, m_borderWidth));\n    System.out.println(&quot;m_barWidth = &quot; + m_barWidth);\n    \n    \/\/ Have this instance listen for properties and vetoable changes\n    addPropertyChangeListener(&quot;percent&quot;, this);\n    addVetoableChangeListener(this);\n  }\n\n  \/\/\/\/ Accessor methods \/\/\/\/\n  \/**\n   * Sets the percent for bar display.\n   *\/\n  public void setPercent(int newPercent)\n          throws PropertyVetoException \/\/ Now, this setter can be vetoed\n  {\n    \/\/ If no change, do nothing...\n    if (newPercent == m_percent)\n      return;\n    \n    Integer oldValue = new Integer(m_percent);\n    Integer newValue = new Integer(newPercent);\n    fireVetoableChange(&quot;percent&quot;, oldValue, newValue);\n\n    \n    \/\/ If we get here, nobody vetoed, so we make the change\n    m_percent = newPercent;\n    \n    \/\/ Ensure any other listeners see the change\n    firePropertyChange(&quot;percent&quot;, oldValue, newValue);\n    \n    \/\/ Ensure the GUI updates\n    System.out.println(&quot;Repainting...&quot;);\n    repaint();\n  }\n\n  \/**\n   * Gets the percent for bar display.\n   *\/\n  public int getPercent()\n  {\n    return m_percent;\n  }\n    \n  \/**\n   * Respond to a property change event for the property\n   * &quot;value&quot; by updating my value to a new value.\n   *\/\n  public void propertyChange(PropertyChangeEvent event)\n  {\n    \/\/ If the property changed is &quot;value&quot;, use it to try\n    \/\/ to update the percent property (which is subject to constraints)\n    String propertyName = event.getPropertyName();\n    System.out.println(&quot;Property &#039;&quot; + propertyName + &quot;&#039; change...&quot;);\n    \n    \/\/ Is it of interest?\n    if ( propertyName.equals(&quot;value&quot;) )\n    {\n      Number newValue = (Number)(event.getNewValue());\n      \/\/ If there&#039;s nothing to change, just exit\n      if (newValue == null || newValue.intValue() == m_percent)\n      {\n        return;\n      }\n      \n      \/\/ If we get here, we try to change the value, subject to constraints\n      int value = newValue.intValue();\n      System.out.println(&quot;Property &#039;&quot; + propertyName + \n                         &quot;&#039;: changing to &quot; + value);\n\n      \/\/ Change the percent property (subject to constraints)\n      try\n      {\n        \/\/ If this returns without throwing an exception, we changed the value\n        setPercent(value);\n      }\n      catch (PropertyVetoException pve)\n      {\n        \/\/ Somebody vetoed, so revert the value of the property back to its\n        \/\/ original value.\n        Number oldValue = (Number)(event.getOldValue());\n        short oldInt = oldValue.shortValue();\n        System.out.println(&quot;Reverting value back to &quot; + oldInt);\n        JFormattedTextField source = (JFormattedTextField)(event.getSource());\n        source.setValue(oldValue);\n      }\n    }\n    else\n    {\n      System.out.println(&quot;Property &#039;&quot; + propertyName \n                         + &quot;&#039; change to &quot; +  event.getNewValue());\n      \/\/ We don&#039;t care about properties other than &quot;value&quot; here\n      \/\/ so do nothing\n    }\n  }\n  \n  \/**\n   * Respond to a vetoable property change event for the \n   * property &quot;value&quot; by checking the new value for validity\n   * If it&#039;s not valid, a PropertyVetoException is thrown.\n   * (We leave it to the propertyChange() method above to\n   * actually change the value.)\n   *\/\n  public void vetoableChange(PropertyChangeEvent event)\n      throws PropertyVetoException\n  {\n    String propertyName = event.getPropertyName();\n    System.out.println(&quot;Received vetoable change for property &#039;&quot; \n                       + propertyName + &quot;&#039;&quot;);\n    if ( propertyName.equals(&quot;percent&quot;) )\n    {\n      int newPercent = ((Integer)event.getNewValue()).intValue();\n      System.out.println(&quot;Checking property change &#039;&quot; \n                         + propertyName + &quot;&#039; for potential veto...&quot;);\n      if (newPercent &amp;lt; 0 || newPercent &gt; 100)\n      {\n        System.out.println(&quot;Vetoing!&quot;);\n        throw new PropertyVetoException(&quot;No way, Jose!&quot;, event);\n      }\n      else\n      {\n        System.out.println(&quot;Not vetoed!&quot;);\n      }\n    }\n    else\n    {\n      \/\/ We don&#039;t expect, or care, about other properties, here\n    }\n  }\n\n  \/**\n   * Paints the BarChart using the specified Graphics.\n   *\/\n  public void paintComponent(Graphics g)\n  {\n    super.paintComponent(g);\n    System.out.println(&quot;Painting for new value of &quot; + m_percent);\n    System.out.println(&quot;Width: &quot; + getWidth() + &quot; Height: &quot; + getHeight());\n\n    \/\/ Paint the background color for the bar\n    setBackground(m_floodColor);\n\n    \/\/ Paint the part of the bar that represents the percentage\n    g.setColor(m_fillColor);\n    int y = (getHeight() * (100 - m_percent) \/ 100);\n    int width = getWidth();\n    int height = getHeight() * m_percent \/ 100;\n    System.out.println(&quot;Filling Rectangle at &#x5B;&quot; + 0 + &quot;, &quot; + y + &quot;] Width: &quot; + \n                       width + &quot; Height: &quot; + height);\n    System.out.println(&quot;m_barWidth = &quot; + m_barWidth);\n    g.fillRect(0, y, width, height);\n  }\n\n  \/\/\/\/ Private data \/\/\/\/\n  private int m_percent = 0;\n  private Color m_floodColor = Color.blue;\n  private Color m_fillColor = Color.red;\n  private Color m_borderColor = Color.black;\n  private int m_barWidth = 25;\n  private int m_barHeight = 150;\n  private int m_borderWidth = 2;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the source code for the BarChartFrame:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\npackage javaBeans_2;\n\nimport java.awt.BorderLayout;\nimport java.awt.Color;\nimport java.awt.Panel;\nimport java.awt.Rectangle;\nimport java.awt.event.ComponentAdapter;\nimport java.awt.event.ComponentEvent;\nimport java.text.NumberFormat;\nimport javax.swing.JFormattedTextField;\n\nimport javax.swing.JFrame;\nimport javax.swing.JPanel;\n\n\/**\n * The BarChartFrame contains two beans: BarChart and JFormattedTextField.\n *\n * @author Bryan J. Higgs, 8 April, 2021\n *\/\npublic class BarChartFrame extends JFrame\n{\n\n  \/**\n   * Main entry point\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    BarChartFrame frame = new BarChartFrame();\n    frame.setDefaultLookAndFeelDecorated(true);\n    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);\n    frame.setVisible(true);\n  }\n\n  \/**\n   * Constructor\n   *\/\n  public BarChartFrame()\n  {\n    setSize(300, 250);\n    setTitle(&quot;Color Bar Frame&quot;);\n\n    \/\/ Initialize the beans\n    m_intBox.setText(&quot;0&quot;);\n    m_intBox.setEditable(true);\n\n    JPanel contentPane = (JPanel) getContentPane();\n    contentPane.setLayout(new BorderLayout());\n\n    JPanel panel = new JPanel();\n    panel.add(m_barChart);\n\n    contentPane.add(panel, BorderLayout.CENTER);\n    contentPane.add(m_intBox, BorderLayout.SOUTH);\n\n    \/\/ Set the BarChart to listen for property change events for the\n    \/\/ JFormattedTextField &#039;value&#039; property.\n    m_intBox.addPropertyChangeListener(&quot;value&quot;, m_barChart);\n    \n    \/\/ Set the BarChart to listen for vetoable change events from the\n    \/\/ JFormattedTextField.\n    m_intBox.addVetoableChangeListener(m_barChart);\n  }\n\n  \/\/\/\/ Private Data \/\/\/\/\n  private static BarChart m_barChart = new BarChart();\n  private static JFormattedTextField m_intBox\n          = new JFormattedTextField( NumberFormat.getIntegerInstance() );\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">The output is identical with the former examples, except that if you enter, say, 200 in the text box, it refuses to accept that value, and the former value replaces the 200.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"PropertyChangeSupport_VetoableChangeSupport\"><\/span>PropertyChangeSupport &amp; VetoableChangeSupport<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>PropertyChangeSupport<\/strong> is a thread-safe utility\/convenience class that can be used by beans that support <em>bound properties<\/em>. It manages a list of listeners and dispatches PropertyChangeEvents to them. You can use an instance of this class as a member field of your bean and delegate these types of work to it. The PropertyChangeListener can be registered for all properties or for a property specified by name. It simplifies the implementation of property change listeners; it does a lot of the hard work for you.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here is an example of&nbsp;<code>PropertyChangeSupport<\/code>&nbsp;usage that follows the rules and recommendations laid out in the JavaBeans\u2122 specification [from the JavaDoc]<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public class MyBean {\n     private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);\n\n     public void addPropertyChangeListener(PropertyChangeListener listener) {\n         this.pcs.addPropertyChangeListener(listener);\n     }\n\n     public void removePropertyChangeListener(PropertyChangeListener listener) {\n         this.pcs.removePropertyChangeListener(listener);\n     }\n\n     private String value;\n\n     public String getValue() {\n         return this.value;\n     }\n\n     public void setValue(String newValue) {\n         String oldValue = this.value;\n         this.value = newValue;\n         this.pcs.firePropertyChange(\"value\", oldValue, newValue);\n     }\n\n     &#91;...]\n }<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>VetoableChangeSupport<\/strong> is a thread-safe utility\/convenience class that can be used by beans that support <em>constrained properties<\/em>. It manages a list of listeners and dispatches PropertyChangeEvents to them. You can use an instance of this class as a member field of your bean and delegate these types of work to it. The VetoableChangeListener can be registered for all properties or for a property specified by name.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here is an example of&nbsp;<code>VetoableChangeSupport<\/code>&nbsp;usage that follows the rules and recommendations laid out in the JavaBeans\u2122 specification:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public class MyBean {\n     private final VetoableChangeSupport vcs = new VetoableChangeSupport(this);\n\n     public void addVetoableChangeListener(VetoableChangeListener listener) {\n         this.vcs.addVetoableChangeListener(listener);\n     }\n\n     public void removeVetoableChangeListener(VetoableChangeListener listener) {\n         this.vcs.removeVetoableChangeListener(listener);\n     }\n\n     private String value;\n\n     public String getValue() {\n         return this.value;\n     }\n\n     public void setValue(String newValue) throws PropertyVetoException {\n         String oldValue = this.value;\n         this.vcs.fireVetoableChange(\"value\", oldValue, newValue);\n         this.value = newValue;\n     }\n\n     &#91;...]\n }<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Simplified_Example_of_a_Bound_and_Constrained_Property\"><\/span>Simplified Example of a Bound and Constrained Property<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s a simpler version of an application with a bound and constrained property.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We have a GUI application that contains two buttons and two labels. The buttons control a value (incrementing up or down), and directly control the value in the &#8220;primary label&#8221;. This primary label provides a single property, &#8220;value&#8221;. The other label (&#8220;mirror label&#8221;) listens to the changes in the primary label&#8217;s &#8220;value&#8221; property, and changes its own value to match.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In addition, we have a class Constrainer, which prevents the value of the primary button from going out of the range 10 &#8211; 20. It uses a constrained property to accomplish this.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the code for the class NumberLabel, which is the class used for each of the two labels:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage javaBeans_3;\n\nimport java.beans.PropertyChangeEvent;\nimport java.beans.PropertyChangeListener;\nimport java.beans.PropertyChangeSupport;\nimport java.beans.PropertyVetoException;\nimport java.beans.VetoableChangeListener;\nimport java.beans.VetoableChangeSupport;\nimport javax.swing.JLabel;\n\n\/**\n * The NumberLabel class is a subclass of java.swing.JLabel that has a bound \n * and constrained property named Value\n *\n * @author bryanhiggs\n *\/\n\/\/ the NumberLabel class\nclass NumberLabel extends JLabel\n        implements PropertyChangeListener\n{\n  \/**\n   * Constructor\n   *\/\n  public NumberLabel(String text)\n  {\n    \/\/ call the super class\n    super(text);    \n    \/\/ Defer property change support\n    boundSupport = new PropertyChangeSupport(this);\n    \/\/ Defer vetoable change support\n    vetoSupport = new VetoableChangeSupport(this);\n  }\n\n  \/\/ add a bound property listener\n  public void addPropertyChangeListener(PropertyChangeListener listener)\n  {\n    if (boundSupport == null)\n      boundSupport = new PropertyChangeSupport(this);\n    \/\/ defer to the support object\n    boundSupport.addPropertyChangeListener(listener);\n  }\n\n  \/\/ remove a bound property listener\n  public void removePropertyChangeListener(PropertyChangeListener listener)\n  {\n    \/\/ defer to the support object\n    boundSupport.removePropertyChangeListener(listener);\n  }\n\n  \/\/ add a constrained property listener\n  public void addVetoableChangeListener(VetoableChangeListener listener)\n  {\n    if (vetoSupport == null)\n      vetoSupport = new VetoableChangeSupport(this);\n    \/\/ defer to the support object\n    vetoSupport.addVetoableChangeListener(listener);\n  }\n\n  \/\/ remove a constrained property listener\n  public void removeVetoableChangeListener(VetoableChangeListener listener)\n  {\n    \/\/ defer to the support object\n    vetoSupport.removeVetoableChangeListener(listener);\n  }\n\n  \/\/ the get method for the Value property\n  public int getValue()\n  {\n    return theValue;\n  }\n\n  \/\/ the set method for the Value property -- subject to constraints\n  public void setValue(int newValue)\n          throws PropertyVetoException\n  {\n    \/\/ fire the change to any constrained listeners\n    vetoSupport.fireVetoableChange(&quot;Value&quot;, \n                                   Integer.valueOf(theValue),\n                                   Integer.valueOf(newValue));\n\n    \/\/ no veto, so save the old value and then change it\n    Integer oldVal = Integer.valueOf(theValue);\n    theValue = newValue;\n    setText(String.valueOf(theValue));\n    repaint();\n\n    \/\/ fire the change to any bound listeners\n    boundSupport.firePropertyChange(&quot;Value&quot;, \n                                    oldVal,\n                                    Integer.valueOf(theValue));\n  }\n\n  \/\/ handle property change events from others\n  public void propertyChange(PropertyChangeEvent evt)\n  {\n    \/\/ only interested in changes to Value properties\n    if (evt.getPropertyName().equals(&quot;Value&quot;))\n    {\n      \/\/ just change our own property\n      Integer val = (Integer)(evt.getNewValue());\n\n      try\n      {\n        setValue(val.intValue());\n      }\n      catch (PropertyVetoException e)\n      {\n      }\n    }\n  }\n\n  \/\/ Private data\n  \n  \/\/ the support object for bound listeners\n  protected PropertyChangeSupport boundSupport;\n\n  \/\/ the support object for constrained listeners\n  protected VetoableChangeSupport vetoSupport;\n\n  \/\/ the implementation of the Value property\n  protected int theValue = 15;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">This is the Constrainer class:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\npackage javaBeans_3;\n\nimport java.beans.PropertyChangeEvent;\nimport java.beans.PropertyVetoException;\nimport java.beans.VetoableChangeListener;\n\n\/**\n * The Constrainer class vetoes any property changes that \n * attempt to change the Value property of a NumberLabel \n * object to a value below 10 or above 20.\n * \n * @author bryanhiggs\n *\/\npublic class Constrainer implements VetoableChangeListener\n{\n   \/\/ handle the vetoable change event\n   public void vetoableChange(PropertyChangeEvent event)\n           throws PropertyVetoException\n   {\n      \/\/ we constrain the value to between 10 and 20\n      Integer value = (Integer)event.getNewValue();\n      if (value.intValue() &lt; 10 || value.intValue() &gt; 20)\n      {\n         throw new PropertyVetoException(&quot;Bad Value&quot;, event);\n      }\n   }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the main application that implements the GUI:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage javaBeans_3;\n\nimport java.awt.BorderLayout;\nimport java.awt.Color;\nimport static java.awt.FlowLayout.CENTER;\nimport java.awt.FlowLayout;\nimport java.awt.event.ActionEvent;\nimport java.awt.event.ActionListener;\n\nimport java.beans.PropertyVetoException;\n\nimport javax.swing.JButton;\nimport javax.swing.JFrame;\nimport javax.swing.JPanel;\n\n\/**\n * Example of use of a constrained property in a Javabean\n *\n * @author bryanhiggs\n *\/\npublic class ConstrainedPropertyExample extends JFrame\n{\n\n  \/**\n   * Main entry point\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    ConstrainedPropertyExample frame = new ConstrainedPropertyExample();\n    frame.setDefaultLookAndFeelDecorated(true);\n    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);\n    frame.setVisible(true);\n  }\n\n  \/**\n   * Constructor\n   *\/\n  public ConstrainedPropertyExample()\n  {\n    setSize(300, 125);\n    setTitle(&quot;Constrained Property Example&quot;);\n    JPanel panel = (JPanel) getContentPane();\n    panel.setLayout( new BorderLayout() );\n    JPanel northPanel = new JPanel();\n    panel.add(northPanel, BorderLayout.NORTH);\n    JPanel southPanel = new JPanel( new FlowLayout(CENTER, 20, 5) );\n    panel.add(southPanel, BorderLayout.SOUTH);\n\n    \/\/ add the user interface elements\n    northPanel.add(decButton);\n    northPanel.add(incButton);\n    southPanel.add(primaryLabel);\n    southPanel.add(mirrorLabel);\n    \n    decButton.addActionListener(new ActionListener() {\n         public void actionPerformed(ActionEvent event) {\n            handleDecrement(event);\n         }\n      });\n    incButton.addActionListener(new ActionListener() {\n         public void actionPerformed(ActionEvent event) {\n            handleIncrement(event);\n         }\n      });\n\n    \/\/ register the constrainer with the primary label\n    primaryLabel.addVetoableChangeListener(constrainer);\n\n    \/\/ register the mirroring label with the primary label\n    primaryLabel.addPropertyChangeListener(mirrorLabel);\n\n    \/\/ start the labels at different values\n    try\n    {\n      primaryLabel.setValue(15);\n      mirrorLabel.setValue(5);\n    }\n    catch (PropertyVetoException pve)\n    {\n    }\n  }\n\n  \/\/ handle the decrement button push\n  public void handleDecrement(ActionEvent evt)\n  {\n    \/\/ get the current value and subtract 1\n    int value = primaryLabel.getValue() - 1;\n\n    \/\/ try to set the new value\n    try\n    {\n      primaryLabel.setValue(value);\n    }\n    catch (PropertyVetoException pve)\n    {\n\n    }\n  }\n\n  \/\/ handle the increment button push\n  public void handleIncrement(ActionEvent evt)\n  {\n    \/\/ get the current value and add 1\n    int value = primaryLabel.getValue() + 1;\n\n    try\n    {\n      \/\/ try to set the new value\n      primaryLabel.setValue(value);\n    }\n    catch (PropertyVetoException ex)\n    {\n      \n    }\n  }\n\n  \/\/ Private data\n  \n  \/\/ the decrement button\n  protected JButton decButton = new JButton(&quot;&lt;&lt;&quot;);\n\n  \/\/ the increment button\n  protected JButton incButton = new JButton(&quot;&gt;&gt;&quot;);\n\n  \/\/ the constrained label\n  protected NumberLabel primaryLabel = new NumberLabel(&quot;*****&quot;);\n\n  \/\/ the label that mirrors the primary label\n  protected NumberLabel mirrorLabel = new NumberLabel(&quot;*****&quot;);\n\n  \/\/ the constraining object\n  protected Constrainer constrainer = new Constrainer();\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">The application produces a frame that looks like this:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"620\" height=\"270\" src=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/04\/ConstrainedPropertyExample.png\" alt=\"\" class=\"wp-image-613\" srcset=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/04\/ConstrainedPropertyExample.png 620w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/04\/ConstrainedPropertyExample-300x131.png 300w\" sizes=\"auto, (max-width: 620px) 100vw, 620px\" \/><\/figure><\/div>\n\n\n\n<div style=\"height:31px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">When you click on the &#8220;&lt;&lt;&#8221; button, you will see that the values displayed in the labels at the bottom of the frame change, to cause them both to show 14, and so on, until the values reach 10, at which point they won&#8217;t go lower. Similarly, if you click on the &#8220;>>&#8221; button, the values increase until they reach 20 and then will not go higher.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s work through the high-level steps. Once the GUI is up and running, let&#8217;s see what happens if the user clicks on the &#8220;&lt;&lt;&#8221; button:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>The <strong>ActionListener<\/strong> for the <strong>decButton<\/strong> is invoked. It calls the <strong>handleDecrement<\/strong> method<\/li><li>The <strong>handleDecrement<\/strong> method extracts the value from the <strong>primaryLabel<\/strong> into a local copy and decrements it. It then attempts to set the value of the <strong>primaryLabel<\/strong> to that value, by calling the <strong>primaryLabel<\/strong>&#8216;s <strong>setValue<\/strong> method.<\/li><li>The <strong>primaryLabel<\/strong>&#8216;s <strong>setValue<\/strong> method first calls the <strong>fireVetoableChange<\/strong> method to ask all the <strong>vetoableChange<\/strong> listeners if it&#8217;s OK with them.<\/li><li>The <strong>fireVetoableChange<\/strong> method, via the <strong>VetoableChangeSupport<\/strong> class, invokes the <strong>Constrainer<\/strong> class&#8217;s <strong>vetoableChange<\/strong> method (the <strong>Constrainer<\/strong> class was previously registered as a <strong>VetoableChangeListener<\/strong> on the <strong>primaryLabel<\/strong>).<\/li><li>The <strong>Constrainer<\/strong> class&#8217;s <strong>vetoableChange<\/strong> method checks the new value to see whether it is within the allowed bounds (10 to 20).<\/li><li>If it is within bounds:<ol><li>It simply returns to the <strong>primaryLabel<\/strong>&#8216;s <strong>setValue<\/strong> method, which extracts the old and new values of the property, and sets the new value of the <strong>primaryLabel<\/strong><\/li><li>It then calls the <strong>firePropertyChange<\/strong> method to inform all <strong>PropertyListeners<\/strong> of the change.<\/li><li>This causes the <strong>mirrorLabel<\/strong>&#8216;s <strong>propertyChange<\/strong> method to be invoked, which first calls the <strong>fireVetoableChange<\/strong> method, but this has no effect as there are no <strong>VetoableChangeListener<\/strong>s registered for the <strong>mirrorLabel<\/strong>.<\/li><li>The <strong>mirrorLabel<\/strong>&#8216;s <strong>propertyChange<\/strong> method then extracts the value of the <strong>mirrorLabel<\/strong>&#8216;s old and new values, and sets the new value for the <strong>mirrorLabel<\/strong>.<\/li><li>Finally, the <strong>mirrorLabel<\/strong>&#8216;s <strong>propertyChange<\/strong> method calls the <strong>firePropertyChange<\/strong> method, which has no effect, because the <strong>mirrorLabel<\/strong> has no <strong>PropertyChangeListener<\/strong>s registered.<\/li><\/ol><\/li><li>If it is not within bounds:<ol><li>the <strong>Constrainer<\/strong> class&#8217;s <strong>vetoableChange<\/strong> method throws a <strong>PropertyVetoException<\/strong>, which goes back through the <strong>primaryLabel<\/strong>&#8216;s <strong>setValue<\/strong> method (which indicates that it can throw a <strong>PropertyVetoException<\/strong>), to the <strong>handleDecrement<\/strong> method, which catches the exception. It does nothing in the catch handler, because there is no further action to take, at this point.<\/li><\/ol><\/li><\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">As a result, the application has caused the <strong>primaryLabel<\/strong> to display changes made, and the <strong>mirrorLabel<\/strong> to mirror the value from the <strong>primaryLabel<\/strong>, through a <em>bound property<\/em>. The <strong>primaryLabel<\/strong> and <strong>mirrorLabel<\/strong> both are constrained to displaying values within the range, through a <em>constrained property<\/em> enforced by the <strong>Constrainer<\/strong> class.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Have you ever used an IDE to create a form?&nbsp; Used Visual Basic to create a GUI application?&nbsp; If so, you&#8217;ll be familiar with the idea of visual components and combining them to produce a GUI interface for users. In the Microsoft world, such visual components are implemented using OLE, COM, or ActiveX controls, depending [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":19,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_eb_attr":"","ocean_front_end_style_editor":"no","ocean_post_layout":"left-sidebar","ocean_both_sidebars_style":"","ocean_both_sidebars_content_width":0,"ocean_both_sidebars_sidebars_width":0,"ocean_sidebar":"ocs-course-topics-sidebar","ocean_second_sidebar":"0","ocean_disable_margins":"enable","ocean_add_body_class":"","ocean_shortcode_before_top_bar":"","ocean_shortcode_after_top_bar":"","ocean_shortcode_before_header":"","ocean_shortcode_after_header":"","ocean_has_shortcode":"","ocean_shortcode_after_title":"","ocean_shortcode_before_footer_widgets":"","ocean_shortcode_after_footer_widgets":"","ocean_shortcode_before_footer_bottom":"","ocean_shortcode_after_footer_bottom":"","ocean_display_top_bar":"default","ocean_display_header":"default","ocean_header_style":"","ocean_center_header_left_menu":"0","ocean_custom_header_template":"0","ocean_custom_logo":0,"ocean_custom_retina_logo":0,"ocean_custom_logo_max_width":0,"ocean_custom_logo_tablet_max_width":0,"ocean_custom_logo_mobile_max_width":0,"ocean_custom_logo_max_height":0,"ocean_custom_logo_tablet_max_height":0,"ocean_custom_logo_mobile_max_height":0,"ocean_header_custom_menu":"0","ocean_menu_typo_font_family":"0","ocean_menu_typo_font_subset":"","ocean_menu_typo_font_size":0,"ocean_menu_typo_font_size_tablet":0,"ocean_menu_typo_font_size_mobile":0,"ocean_menu_typo_font_size_unit":"px","ocean_menu_typo_font_weight":"","ocean_menu_typo_font_weight_tablet":"","ocean_menu_typo_font_weight_mobile":"","ocean_menu_typo_transform":"","ocean_menu_typo_transform_tablet":"","ocean_menu_typo_transform_mobile":"","ocean_menu_typo_line_height":0,"ocean_menu_typo_line_height_tablet":0,"ocean_menu_typo_line_height_mobile":0,"ocean_menu_typo_line_height_unit":"","ocean_menu_typo_spacing":0,"ocean_menu_typo_spacing_tablet":0,"ocean_menu_typo_spacing_mobile":0,"ocean_menu_typo_spacing_unit":"","ocean_menu_link_color":"","ocean_menu_link_color_hover":"","ocean_menu_link_color_active":"","ocean_menu_link_background":"","ocean_menu_link_hover_background":"","ocean_menu_link_active_background":"","ocean_menu_social_links_bg":"","ocean_menu_social_hover_links_bg":"","ocean_menu_social_links_color":"","ocean_menu_social_hover_links_color":"","ocean_disable_title":"default","ocean_disable_heading":"default","ocean_post_title":"","ocean_post_subheading":"","ocean_post_title_style":"","ocean_post_title_background_color":"","ocean_post_title_background":0,"ocean_post_title_bg_image_position":"","ocean_post_title_bg_image_attachment":"","ocean_post_title_bg_image_repeat":"","ocean_post_title_bg_image_size":"","ocean_post_title_height":0,"ocean_post_title_bg_overlay":0.5,"ocean_post_title_bg_overlay_color":"","ocean_disable_breadcrumbs":"default","ocean_breadcrumbs_color":"","ocean_breadcrumbs_separator_color":"","ocean_breadcrumbs_links_color":"","ocean_breadcrumbs_links_hover_color":"","ocean_display_footer_widgets":"default","ocean_display_footer_bottom":"default","ocean_custom_footer_template":"0","footnotes":""},"class_list":["post-572","page","type-page","status-publish","hentry","entry"],"_links":{"self":[{"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages\/572","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/comments?post=572"}],"version-history":[{"count":21,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages\/572\/revisions"}],"predecessor-version":[{"id":616,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages\/572\/revisions\/616"}],"up":[{"embeddable":true,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages\/19"}],"wp:attachment":[{"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/media?parent=572"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}