<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # Java Swing 模型架構 > [http://zetcode.com/tutorials/javaswingtutorial/swingmodels/](http://zetcode.com/tutorials/javaswingtutorial/swingmodels/) Swing 工程師創建了 Swing 工具箱,實現了修改后的 MVC 設計模式。 這樣可以有效地處理數據,并在運行時使用可插入的外觀。 傳統的 MVC 模式將應用分為三個部分:模型,視圖和控制器。 該模型表示應用中的數據。 視圖是數據的視覺表示。 最后,控制器處理并響應事件(通常是用戶操作),并可以調用模型上的更改。 這個想法是通過引入一個中間組件:控制器,將數據訪問和業務邏輯與數據表示和用戶交互分開。 Swing 工具箱使用修改后的 MVC 設計模式。 對于視圖和控制器,它只有一個 UI 對象。 有時將這種修改后的 MVC 稱為可分離模型架構。 在 Swing 工具箱中,每個組件都有其模型,甚至包括按鈕之類的基本組件。 Swing 工具箱中有兩種模型: * 狀態模型 * 數據模型 狀態模型處理組件的狀態。 例如,模型會跟蹤組件是處于選中狀態還是處于按下狀態。 數據模型處理它們使用的數據。 列表組件保留其顯示的項目列表。 對于 Swing 開發者來說,這意味著他們通常需要獲取模型實例才能操縱組件中的數據。 但是也有例外。 為了方便起見,有一些方法可以返回數據,而無需程序員訪問模型。 ```java public int getValue() { return getModel().getValue(); } ``` 一個示例是`JSlider`組件的`getValue()`方法。 開發者無需直接使用模型。 而是在后臺進行對模型的訪問。 在如此簡單的情況下直接使用模型將是一個過大的殺傷力。 因此,Swing 提供了一些便捷的方法,如上一個。 要查詢模型的狀態,我們有兩種通知: * 輕量級通知 * 狀態通知 輕量級通知使用`ChangeListener`類。 對于來自組件的所有通知,我們只有一個事件(`ChangeEvent)`。對于更復雜的組件,將使用狀態通知。對于此類通知,我們具有不同類型的事件。例如,`JList`組件具有`ListDataEvent`和`ListSelectionEvent`。 如果我們不為組件設置模型,則會創建一個默認模型。 例如,按鈕組件具有`DefaultButtonModel`模型。 ```java public JButton(String text, Icon icon) { // Create the model setModel(new DefaultButtonModel()); // initialize init(text, icon); } ``` 查看`JButton.java`源文件,我們發現默認模型是在構建組件時創建的。 ## 按鈕模型 該模型用于各種按鈕,例如按鈕,復選框,單選框和菜單項。 以下示例說明了`JButton`的模型。 因為沒有數據可以與按鈕關聯,所以我們只能管理按鈕的狀態。 `ButtonModelEx.java` ```java package com.zetcode; import javax.swing.AbstractAction; import javax.swing.DefaultButtonModel; import javax.swing.GroupLayout; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.EventQueue; import java.awt.event.ActionEvent; public class ButtonModelEx extends JFrame { private JButton okBtn; private JLabel enabledLbl; private JLabel pressedLbl; private JLabel armedLbl; private JCheckBox checkBox; public ButtonModelEx() { initUI(); } private void initUI() { okBtn = new JButton("OK"); okBtn.addChangeListener(new DisabledChangeListener()); checkBox = new JCheckBox(); checkBox.setAction(new CheckBoxAction()); enabledLbl = new JLabel("Enabled: true"); pressedLbl = new JLabel("Pressed: false"); armedLbl = new JLabel("Armed: false"); createLayout(okBtn, checkBox, enabledLbl, pressedLbl, armedLbl); setTitle("ButtonModel"); setLocationRelativeTo(null); setDefaultCloseOperation(EXIT_ON_CLOSE); } private void createLayout(JComponent... arg) { var pane = getContentPane(); var gl = new GroupLayout(pane); pane.setLayout(gl); gl.setAutoCreateContainerGaps(true); gl.setAutoCreateGaps(true); gl.setHorizontalGroup(gl.createParallelGroup() .addGroup(gl.createSequentialGroup() .addComponent(arg[0]) .addGap(80) .addComponent(arg[1])) .addGroup(gl.createParallelGroup() .addComponent(arg[2]) .addComponent(arg[3]) .addComponent(arg[4])) ); gl.setVerticalGroup(gl.createSequentialGroup() .addGroup(gl.createParallelGroup() .addComponent(arg[0]) .addComponent(arg[1])) .addGap(40) .addGroup(gl.createSequentialGroup() .addComponent(arg[2]) .addComponent(arg[3]) .addComponent(arg[4])) ); pack(); } private class DisabledChangeListener implements ChangeListener { @Override public void stateChanged(ChangeEvent e) { var model = (DefaultButtonModel) okBtn.getModel(); if (model.isEnabled()) { enabledLbl.setText("Enabled: true"); } else { enabledLbl.setText("Enabled: false"); } if (model.isArmed()) { armedLbl.setText("Armed: true"); } else { armedLbl.setText("Armed: false"); } if (model.isPressed()) { pressedLbl.setText("Pressed: true"); } else { pressedLbl.setText("Pressed: false"); } } } private class CheckBoxAction extends AbstractAction { public CheckBoxAction() { super("Disabled"); } @Override public void actionPerformed(ActionEvent e) { if (okBtn.isEnabled()) { okBtn.setEnabled(false); } else { okBtn.setEnabled(true); } } } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new ButtonModelEx(); ex.setVisible(true); }); } } ``` 在我們的示例中,我們有一個按鈕,一個復選框和三個標簽。 標簽代表按鈕的三個屬性:按下,禁用或布防狀態。 ```java okbtn.addChangeListener(new DisabledChangeListener()); ``` 我們使用`ChangeListener`來監聽按鈕狀態的變化。 ```java var model = (DefaultButtonModel) okBtn.getModel(); ``` 在這里,我們獲得默認的按鈕模型。 ```java if (model.isEnabled()) { enabledLbl.setText("Enabled: true"); } else { enabledLbl.setText("Enabled: false"); } ``` 我們查詢模型是否啟用了按鈕。 標簽會相應更新。 ```java if (okBtn.isEnabled()) { okBtn.setEnabled(false); } else { okBtn.setEnabled(true); } ``` 該復選框啟用或禁用該按鈕。 要啟用“確定”按鈕,我們調用`setEnabled()`方法。 因此,我們更改了按鈕的狀態。 模型在哪里? 答案就在`AbstractButton.java`文件中。 ```java public void setEnabled(boolean b) { if (!b && model.isRollover()) { model.setRollover(false); } super.setEnabled(b); model.setEnabled(b); } ``` 答案是,Swing 工具箱在內部與模型一起使用。 `setEnabled()`是程序員的另一種便捷方法。 ![ButtonModel](https://img.kancloud.cn/87/a1/87a1bc88605801f8dda794cd2f14226a_320x204.jpg) 圖:`ButtonModel` ## 自定義`ButtonModel` 在前面的示例中,我們使用了默認按鈕模型。 在下面的代碼示例中,我們將使用我們自己的按鈕模型。 `CustomButtonModelEx.java` ```java package com.zetcode; import javax.swing.AbstractAction; import javax.swing.DefaultButtonModel; import javax.swing.GroupLayout; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import java.awt.EventQueue; import java.awt.event.ActionEvent; public class CustomButtonModelEx extends JFrame { private JButton okBtn; private JLabel enabledLbl; private JLabel pressedLbl; private JLabel armedLbl; private JCheckBox checkBox; public CustomButtonModelEx() { initUI(); } private void initUI() { okBtn = new JButton("OK"); checkBox = new JCheckBox(); checkBox.setAction(new CheckBoxAction()); enabledLbl = new JLabel("Enabled: true"); pressedLbl = new JLabel("Pressed: false"); armedLbl = new JLabel("Armed: false"); var model = new OkButtonModel(); okBtn.setModel(model); createLayout(okBtn, checkBox, enabledLbl, pressedLbl, armedLbl); setTitle("Custom button model"); setLocationRelativeTo(null); setDefaultCloseOperation(EXIT_ON_CLOSE); } private void createLayout(JComponent... arg) { var pane = getContentPane(); var gl = new GroupLayout(pane); pane.setLayout(gl); gl.setAutoCreateContainerGaps(true); gl.setAutoCreateGaps(true); gl.setHorizontalGroup(gl.createParallelGroup() .addGroup(gl.createSequentialGroup() .addComponent(arg[0]) .addGap(80) .addComponent(arg[1])) .addGroup(gl.createParallelGroup() .addComponent(arg[2]) .addComponent(arg[3]) .addComponent(arg[4])) ); gl.setVerticalGroup(gl.createSequentialGroup() .addGroup(gl.createParallelGroup() .addComponent(arg[0]) .addComponent(arg[1])) .addGap(40) .addGroup(gl.createSequentialGroup() .addComponent(arg[2]) .addComponent(arg[3]) .addComponent(arg[4])) ); pack(); } private class OkButtonModel extends DefaultButtonModel { @Override public void setEnabled(boolean b) { if (b) { enabledLbl.setText("Enabled: true"); } else { enabledLbl.setText("Enabled: false"); } super.setEnabled(b); } @Override public void setArmed(boolean b) { if (b) { armedLbl.setText("Armed: true"); } else { armedLbl.setText("Armed: false"); } super.setArmed(b); } @Override public void setPressed(boolean b) { if (b) { pressedLbl.setText("Pressed: true"); } else { pressedLbl.setText("Pressed: false"); } super.setPressed(b); } } private class CheckBoxAction extends AbstractAction { public CheckBoxAction() { super("Disabled"); } @Override public void actionPerformed(ActionEvent e) { if (okBtn.isEnabled()) { okBtn.setEnabled(false); } else { okBtn.setEnabled(true); } } } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new CustomButtonModelEx(); ex.setVisible(true); }); } } ``` 本示例與上一個示例具有相同的作用。 區別在于我們不使用變更監聽器,而使用自定義按鈕模型。 ```java var model = new OkButtonModel(); okBtn.setModel(model); ``` 我們為按鈕設置自定義模型。 ```java private class OkButtonModel extends DefaultButtonModel { ... } ``` 我們創建一個自定義按鈕模型并覆蓋必要的方法。 ```java @Override public void setEnabled(boolean b) { if (b) { enabledLbl.setText("Enabled: true"); } else { enabledLbl.setText("Enabled: false"); } super.setEnabled(b); } ``` 我們重寫`setEnabled()`方法,并在其中添加一些功能。 我們一定不要忘記調用父方法來繼續進行處理。 ## `JList`模型 幾個組件具有兩個模型。 `JList`是其中之一。 它具有以下模型:`ListModel`和`ListSelectionModel`。 `ListModel`處理數據,`ListSelectionModel`處理列表的選擇狀態。 以下示例使用兩種模型。 `ListModelsEx.java` ```java package com.zetcode; import javax.swing.DefaultListModel; import javax.swing.GroupLayout; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; import java.awt.EventQueue; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import static javax.swing.GroupLayout.Alignment.CENTER; public class ListModelsEx extends JFrame { private DefaultListModel<String> model; private JList<String> myList; private JButton remAllBtn; private JButton addBtn; private JButton renBtn; private JButton delBtn; public ListModelsEx() { initUI(); } private void createList() { model = new DefaultListModel<>(); model.addElement("Amelie"); model.addElement("Aguirre, der Zorn Gottes"); model.addElement("Fargo"); model.addElement("Exorcist"); model.addElement("Schindler's myList"); myList = new JList<>(model); myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); myList.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { int index = myList.locationToIndex(e.getPoint()); var item = model.getElementAt(index); var text = JOptionPane.showInputDialog("Rename item", item); String newItem; if (text != null) { newItem = text.trim(); } else { return; } if (!newItem.isEmpty()) { model.remove(index); model.add(index, newItem); var selModel = myList.getSelectionModel(); selModel.setLeadSelectionIndex(index); } } } }); } private void createButtons() { remAllBtn = new JButton("Remove All"); addBtn = new JButton("Add"); renBtn = new JButton("Rename"); delBtn = new JButton("Delete"); addBtn.addActionListener(e -> { var text = JOptionPane.showInputDialog("Add a new item"); String item; if (text != null) { item = text.trim(); } else { return; } if (!item.isEmpty()) { model.addElement(item); } }); delBtn.addActionListener(event -> { var selModel = myList.getSelectionModel(); int index = selModel.getMinSelectionIndex(); if (index >= 0) { model.remove(index); } }); renBtn.addActionListener(e -> { var selModel = myList.getSelectionModel(); int index = selModel.getMinSelectionIndex(); if (index == -1) { return; } var item = model.getElementAt(index); var text = JOptionPane.showInputDialog("Rename item", item); String newItem; if (text != null) { newItem = text.trim(); } else { return; } if (!newItem.isEmpty()) { model.remove(index); model.add(index, newItem); } }); remAllBtn.addActionListener(e -> model.clear()); } private void initUI() { createList(); createButtons(); var scrollPane = new JScrollPane(myList); createLayout(scrollPane, addBtn, renBtn, delBtn, remAllBtn); setTitle("JList models"); setLocationRelativeTo(null); setDefaultCloseOperation(EXIT_ON_CLOSE); } private void createLayout(JComponent... arg) { var pane = getContentPane(); var gl = new GroupLayout(pane); pane.setLayout(gl); gl.setAutoCreateContainerGaps(true); gl.setAutoCreateGaps(true); gl.setHorizontalGroup(gl.createSequentialGroup() .addComponent(arg[0]) .addGroup(gl.createParallelGroup() .addComponent(arg[1]) .addComponent(arg[2]) .addComponent(arg[3]) .addComponent(arg[4])) ); gl.setVerticalGroup(gl.createParallelGroup(CENTER) .addComponent(arg[0]) .addGroup(gl.createSequentialGroup() .addComponent(arg[1]) .addComponent(arg[2]) .addComponent(arg[3]) .addComponent(arg[4])) ); gl.linkSize(addBtn, renBtn, delBtn, remAllBtn); pack(); } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new ListModelsEx(); ex.setVisible(true); }); } } ``` 該示例顯示了一個列表組件和四個按鈕。 這些按鈕控制列表組件中的數據。 該示例更大,因為我們在那里進行了一些其他檢查。 例如,我們不允許在列表組件中輸入空格。 ```java model = new DefaultListModel<>(); model.addElement("Amelie"); model.addElement("Aguirre, der Zorn Gottes"); model.addElement("Fargo"); ... ``` 我們創建一個默認列表模型,并向其中添加元素。 ```java myList = new JList<>(model); myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ``` 我們創建一個列表組件。 構造器的參數是我們創建的模型。 我們使列表進入單選模式。 ```java if (text != null) { item = text.trim(); } else { return; } if (!item.isEmpty()) { model.addElement(item); } ``` 我們僅添加不等于`null`且不為空的項目,例如包含至少一個非空格字符的項目。 在列表中添加空格或空值沒有意義。 ```java var selModel = myList.getSelectionModel(); int index = selModel.getMinSelectionIndex(); if (index >= 0) { model.remove(index); } ``` 這是我們按下刪除按鈕時運行的代碼。 為了從列表中刪除一個項目,必須選擇它-我們必須找出當前選擇的項目。 為此,我們調用`getSelectionModel()`方法。 我們使用`getMinSelectionIndex()`獲取選定的索引,并使用`remove()`方法刪除該項目。 在此示例中,我們使用了兩種列表模型。 我們調用列表數據模型的`add()`,`remove()`和`clear()`方法來處理我們的數據。 并且我們使用了一個列表選擇模型,以便找出所選項目。 ![List models](https://img.kancloud.cn/7d/d9/7dd90b45eee9ae673932e5e234ff5b66_360x228.jpg) 圖:列表模型 ## 文件模型 文檔模型是從視覺表示中分離數據的一個很好的例子。 在`JTextPane`組件中,我們有一個`StyledDocument`用于設置文本數據的樣式。 `DocumentModelEx.java` ```java package com.zetcode; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextPane; import javax.swing.JToolBar; import javax.swing.text.StyleConstants; import javax.swing.text.StyledDocument; import java.awt.BorderLayout; import java.awt.EventQueue; public class DocumentModelEx extends JFrame { private StyledDocument sdoc; private JTextPane textPane; public DocumentModelEx() { initUI(); } private void initUI() { createToolbar(); var panel = new JPanel(new BorderLayout()); panel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); textPane = new JTextPane(); sdoc = textPane.getStyledDocument(); initStyles(textPane); panel.add(new JScrollPane(textPane)); add(panel); pack(); setTitle("Document Model"); setLocationRelativeTo(null); setDefaultCloseOperation(EXIT_ON_CLOSE); } private void createToolbar() { var toolbar = new JToolBar(); var bold = new ImageIcon("src/main/resources/bold.png"); var italic = new ImageIcon("src/main/resources/italic.png"); var strike = new ImageIcon("src/main/resources/strike.png"); var underline = new ImageIcon("src/main/resources/underline.png"); var boldBtn = new JButton(bold); var italBtn = new JButton(italic); var striBtn = new JButton(strike); var undeBtn = new JButton(underline); toolbar.add(boldBtn); toolbar.add(italBtn); toolbar.add(striBtn); toolbar.add(undeBtn); add(toolbar, BorderLayout.NORTH); boldBtn.addActionListener(e -> sdoc.setCharacterAttributes( textPane.getSelectionStart(), textPane.getSelectionEnd() - textPane.getSelectionStart(), textPane.getStyle("Bold"), false)); italBtn.addActionListener(e -> sdoc.setCharacterAttributes( textPane.getSelectionStart(), textPane.getSelectionEnd() - textPane.getSelectionStart(), textPane.getStyle("Italic"), false)); striBtn.addActionListener(e -> sdoc.setCharacterAttributes( textPane.getSelectionStart(), textPane.getSelectionEnd() - textPane.getSelectionStart(), textPane.getStyle("Strike"), false)); undeBtn.addActionListener(e -> sdoc.setCharacterAttributes( textPane.getSelectionStart(), textPane.getSelectionEnd() - textPane.getSelectionStart(), textPane.getStyle("Underline"), false)); } private void initStyles(JTextPane textPane) { var style = textPane.addStyle("Bold", null); StyleConstants.setBold(style, true); style = textPane.addStyle("Italic", null); StyleConstants.setItalic(style, true); style = textPane.addStyle("Underline", null); StyleConstants.setUnderline(style, true); style = textPane.addStyle("Strike", null); StyleConstants.setStrikeThrough(style, true); } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new DocumentModelEx(); ex.setVisible(true); }); } } ``` 該示例具有一個文本窗格和一個工具欄。 在工具欄中,我們有四個按鈕可以更改文本的屬性。 ```java sdoc = textpane.getStyledDocument(); ``` 在這里,我們獲得樣式化的文檔,該文檔是文本窗格組件的模型。 ```java var style = textpane.addStyle("Bold", null); StyleConstants.setBold(style, true); ``` 樣式是一組文本屬性,例如顏色和大小。 在這里,我們為文本窗格組件注冊了一個粗體樣式。 可以隨時檢索已注冊的樣式。 ```java doc.setCharacterAttributes(textpane.getSelectionStart(), textpane.getSelectionEnd() - textpane.getSelectionStart(), textpane.getStyle("Bold"), false); ``` 在這里,我們更改文本的屬性。 參數是選擇的偏移量和長度,樣式和布爾值替換。 偏移量是我們應用粗體文本的開頭。 我們通過減去選擇結束值和選擇開始值來獲得長度值。 布爾值`false`表示我們不會用新樣式替換舊樣式,而是將它們合并。 這意味著如果文本帶有下劃線,并且我們將其設為粗體,則結果為帶下劃線的粗體文本。 ![Document model](https://img.kancloud.cn/69/5b/695b69ce9e5a0f25606c1f4d60a8755a_505x363.jpg) 圖:文檔模型 在本章中,我們提到了 Swing 模型。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看