{"id":837,"date":"2021-01-11T19:45:39","date_gmt":"2021-01-11T19:45:39","guid":{"rendered":"https:\/\/bhiggs.x10hosting.com\/PracticalJavaProgramming\/?page_id=837"},"modified":"2021-01-11T19:52:06","modified_gmt":"2021-01-11T19:52:06","slug":"separating-form-from-function","status":"publish","type":"page","link":"https:\/\/bhiggs.x10hosting.com\/PracticalJavaProgramming\/course-topics\/events\/separating-form-from-function\/","title":{"rendered":"Separating Form from Function"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">There are many cases in GUI-based applications where you want to accomplish the same function in more than one way.&nbsp; For example, it is common to allow the user to select a piece of functionality by:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Selecting a menu item, or by&nbsp;<\/li><li>Clicking on a toolbar icon, or by&nbsp;<\/li><li>Clicking the mouse in a particular way, or by&nbsp;<\/li><li>Typing some character sequence on the keyboard.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">In other word, we wish to separate the form (how we expect the user to specify a function) from the actual implementation of that function.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For this reason, it is desirable in most non-trivial GUI programs to separate the GUI-specific interactions from the code that implements the action requested.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Actions<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A convenient way of accomplishing this separation is provided by the Swing&nbsp;<code><strong>Action<\/strong><\/code>&nbsp;interface, and related classes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s an example, which brings up a window that looks like this:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large\"><img fetchpriority=\"high\" decoding=\"async\" width=\"300\" height=\"200\" src=\"https:\/\/bhiggs.x10hosting.com\/PracticalJavaProgramming\/wp-content\/uploads\/2021\/01\/ColorChangeActions.gif\" alt=\"\" class=\"wp-image-841\"\/><\/figure><\/div>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">We allow the user to change the background color of the application:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>By clicking on one of the buttons inside the frame<\/li><li>By selecting one of the menu items<\/li><li>By depressing the Y, B, and R keys on the keyboard (we could have chosen CTRL\/Y, CTRL\/B, and CTRL\/R, or any other reasonable combination).<\/li><\/ul>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; highlight: [8,9,10,11,12,13,14,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126]; title: ; quick-code: false; notranslate\" title=\"\">\npackage swingExamples;\n\nimport java.awt.Color;\nimport java.awt.Container;\n\nimport java.awt.event.KeyEvent;\nimport java.awt.event.ActionEvent;\nimport java.net.MalformedURLException;\nimport java.net.URL;\n\nimport javax.swing.AbstractAction;\nimport javax.swing.Action;\nimport javax.swing.Icon;\nimport javax.swing.ImageIcon;\nimport javax.swing.JComponent;\nimport javax.swing.JFrame;\nimport javax.swing.JMenu;\nimport javax.swing.JMenuBar;\nimport javax.swing.JPanel;\nimport javax.swing.KeyStroke;\nimport javax.swing.JButton;\n\nclass ColorChangePanel extends JPanel\n{\n  public ColorChangePanel(ColorChangeFrame frame)\n  {\n    setBackground(Color.lightGray);\n    \n    \/\/ Set up the color actions for yellow, blue and red\n    setupActions();\n    \n    \/\/ Add the buttons to the panel\n    add( new ActionButton(m_yellowAction) );\n    add( new ActionButton(m_blueAction) );\n    add( new ActionButton(m_redAction) );\n    \n    \/\/ Register keyboard actions for each color\n    registerKeyboardAction(m_yellowAction,\n        KeyStroke.getKeyStroke(KeyEvent.VK_Y, 0),\n        JComponent.WHEN_IN_FOCUSED_WINDOW);\n    registerKeyboardAction(m_blueAction,\n        KeyStroke.getKeyStroke(KeyEvent.VK_B, 0),\n        JComponent.WHEN_IN_FOCUSED_WINDOW);\n    registerKeyboardAction(m_redAction,\n        KeyStroke.getKeyStroke(KeyEvent.VK_R, 0),\n        JComponent.WHEN_IN_FOCUSED_WINDOW);\n    \n    \/\/ Create menu bar with menu of color actions\n    JMenu menu = new JMenu(&quot;Color&quot;);\n    menu.add(m_yellowAction);\n    menu.add(m_blueAction);\n    menu.add(m_redAction);\n    JMenuBar menuBar = new JMenuBar();\n    menuBar.add(menu);\n    \/\/ Add the menu bar to the panel&#039;s frame.\n    frame.setJMenuBar(menuBar);\n  }\n  \n  \/**\n   * Set up the three color actions\n   *\/\n  private void setupActions()\n  {\n    \/\/ Find the images relative to the current class\n    Class baseClass = ColorChangePanel.class;\n    URL url = baseClass.getResource(&quot;..\/images\/yellow-ball.gif&quot;);\n    m_yellowAction =\n        new ColorAction(\n            &quot;Yellow&quot;,\n            new ImageIcon(url),\n            Color.YELLOW\n            );\n    url = baseClass.getResource(&quot;..\/images\/blue-ball.gif&quot;);\n    m_blueAction =\n        new ColorAction(\n            &quot;Blue&quot;,\n            new ImageIcon(url),\n            Color.BLUE\n            );\n    url = baseClass.getResource(&quot;..\/images\/red-ball.gif&quot;);\n    m_redAction =\n        new ColorAction(\n            &quot;Red&quot;,\n            new ImageIcon(url),\n            Color.RED\n            );\n  }\n  \n  \/\/\/\/\/\/\/\/ Private data \/\/\/\/\/\/\/\n  private Action m_yellowAction;\n  private Action m_blueAction;\n  private Action m_redAction;\n  \n  \/\/\/\/\/\/\/\/ Inner class \/\/\/\/\/\/\/\/\n  class ColorAction extends AbstractAction\n  {\n    public ColorAction(String name, Icon icon, Color color)\n    {\n      putValue(Action.NAME, name);\n      putValue(Action.SMALL_ICON, icon);\n      putValue(Action.SHORT_DESCRIPTION,\n          &quot;Set panel color to &quot; + name.toLowerCase());\n      putValue(&quot;color&quot;, color);\n    }\n    \n    public void actionPerformed(ActionEvent ev)\n    {\n      Color color = (Color) getValue(&quot;color&quot;);\n      setBackground(color);\n    }\n  }\n  \n  \/\/\/\/\/\/\/\/ Inner class \/\/\/\/\/\/\/\n  class ActionButton extends JButton\n  {\n    public ActionButton(Action action)\n    {\n      setText( (String) action.getValue(Action.NAME));\n      Icon icon = (Icon) action.getValue(Action.SMALL_ICON);\n      if (icon != null)\n      {\n        setIcon(icon);\n      }\n      addActionListener(action);\n    }\n  }\n}\n\nclass ColorChangeFrame extends JFrame\n{\n  public ColorChangeFrame()\n  {\n    setTitle(&quot;ColorChange&quot;);\n    setSize(300, 200);\n    setDefaultCloseOperation(EXIT_ON_CLOSE);\n    \n    \/\/ Add panel to frame\n    JPanel panel = new ColorChangePanel(this);\n    Container contentPane = getContentPane();\n    contentPane.add(panel);\n  }\n}\n\npublic class ColorChangeActions\n{\n  public static void main(String&#x5B;] args)\n  {\n    ColorChangeFrame frame = new ColorChangeFrame();\n    frame.setVisible(true);\n  }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Note that we centralized the implementation of the change background color in the <strong>ColorAction<\/strong> class, and then set things up so that this class&#8217;s actionPerformed method would be called as a result of any of the three different ways of causing that action to happen.&nbsp; This basically decouples the form from the desired function.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The advantages would become much more evident in a larger, more realistic program.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There are many cases in GUI-based applications where you want to accomplish the same function in more than one way.&nbsp; For example, it is common to allow the user to select a piece of functionality by: Selecting a menu item, or by&nbsp; Clicking on a toolbar icon, or by&nbsp; Clicking the mouse in a particular [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":69,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_eb_attr":"","_uag_custom_page_level_css":"","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-837","page","type-page","status-publish","hentry","entry"],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false,"ocean-thumb-m":false,"ocean-thumb-ml":false,"ocean-thumb-l":false},"uagb_author_info":{"display_name":"Bryan Higgs","author_link":"https:\/\/bhiggs.x10hosting.com\/PracticalJavaProgramming\/author\/bryan\/"},"uagb_comment_info":0,"uagb_excerpt":"There are many cases in GUI-based applications where you want to accomplish the same function in more than one way.&nbsp; For example, it is common to allow the user to select a piece of functionality by: Selecting a menu item, or by&nbsp; Clicking on a toolbar icon, or by&nbsp; Clicking the mouse in a particular&hellip;","_links":{"self":[{"href":"https:\/\/bhiggs.x10hosting.com\/PracticalJavaProgramming\/wp-json\/wp\/v2\/pages\/837","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bhiggs.x10hosting.com\/PracticalJavaProgramming\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/bhiggs.x10hosting.com\/PracticalJavaProgramming\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/bhiggs.x10hosting.com\/PracticalJavaProgramming\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bhiggs.x10hosting.com\/PracticalJavaProgramming\/wp-json\/wp\/v2\/comments?post=837"}],"version-history":[{"count":5,"href":"https:\/\/bhiggs.x10hosting.com\/PracticalJavaProgramming\/wp-json\/wp\/v2\/pages\/837\/revisions"}],"predecessor-version":[{"id":845,"href":"https:\/\/bhiggs.x10hosting.com\/PracticalJavaProgramming\/wp-json\/wp\/v2\/pages\/837\/revisions\/845"}],"up":[{"embeddable":true,"href":"https:\/\/bhiggs.x10hosting.com\/PracticalJavaProgramming\/wp-json\/wp\/v2\/pages\/69"}],"wp:attachment":[{"href":"https:\/\/bhiggs.x10hosting.com\/PracticalJavaProgramming\/wp-json\/wp\/v2\/media?parent=837"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}