2012-05-04 4 views
5

मैंने पहले जावा में कुछ जीयूआई अनुप्रयोग बनाए हैं, और हर बार जब मैं चीज करता हूं तब तक मैं वास्तव में बस गड़बड़ कर रहा हूं, जो कि मैं इसे करना चाहता हूं, कई जीयूआई उदाहरणों से स्निपिट का उपयोग करके मैं वेब पर मिलता हूं। हाल ही में मैंने स्विंग का उपयोग करके जावा में जीयूआई लिखते समय अच्छे प्रथाओं के बारे में कुछ और पढ़ा, लेकिन फिर भी कुछ चीजें मेरे लिए अस्पष्ट हैं। मुझे पहले से बताएं कि मैं अपने अगले प्रोजेक्ट में करने के लिए इतना है कि हम चाहते हैं कि उपयोग कर सकते हैं एक उदाहरण के रूप चाहते हैं:एमवीसी मॉडल में क्या स्टोर करना है और घटक कैसे संवाद करते हैं?

मैं, एक निष्पादन योग्य आवेदन है कि एक उपयोगकर्ता छवियों को लोड करने की क्षमता देता बनाना चाहते हैं, पर कुछ कार्रवाई करने इन छवियों और परियोजना को बचाओ। भारित छवियों के बीच स्विच करने के लिए नीचे एक सरल नेविगेटर के साथ कोर पर एक मुख्य छवि दर्शक होना चाहिए। ऐसे बटन वाले पैनल होना चाहिए जो किसी छवि पर संचालन करते हैं (उदाहरण के लिए बटन 'छवि से पृष्ठभूमि रंग चुनें') और इन परिचालनों को वैकल्पिक रूप से टूलबार या मेनू से एक्सेस किया जाना चाहिए।

मुझे पता है कि उदाहरण के लिए जीयूआई इवेंट डिस्पैच थ्रेड से शुरू किया जाना चाहिए और मैं समय-समय पर संचालन के लिए स्विंगवर्कर का उपयोग कर सकता हूं। साथ ही मैंने सीखा कि क्रियाओं का उपयोग करके मैं राज्य से कार्यक्षमता को अलग कर सकता हूं और पैनल बटन, टूलबार बटन और मेनू आइटम दोनों के लिए एक क्रिया बना सकता हूं।

जो मुझे समझ में नहीं आता है यह है कि ये सभी चीजें एक दूसरे के साथ कैसे संवाद करती हैं, और जहां मैंने रखा। उदाहरण के लिए: क्या मैं एक अलग मॉडल में अपने प्रोग्राम की स्थिति को बनाए रखता हूं (इसलिए कौन सी छवि वर्तमान में प्रदर्शित होती है, कौन सी सेटिंग्स सेट की जाती हैं) और इस मॉडल को मेरे मुख्य विंडो क्लास में संदर्भित करें? और नियंत्रकों के बारे में क्या? क्या मैं नियंत्रकों में मॉडलों का संदर्भ रखता हूं? और जब मैंने किसी छवि पर कुछ गणना की, तो क्या मैं नियंत्रक से गुई में छवि को अपडेट करता हूं, या एक साधारण पश्चाताप का उपयोग करके गुई से ही अद्यतन करता हूं?

मुझे लगता है कि मेरी मुख्य समस्या यह है कि मैं वास्तव में समझ नहीं पा रहा हूं कि मेरे प्रोग्राम के विभिन्न हिस्सों को कैसे संवाद करना है। एक जीयूआई में बहुत से हिस्से होते हैं, और फिर ये सभी क्रियाएं और श्रोताओं, मॉडल, नियंत्रक, और इन सभी को किसी भी तरह से बातचीत करने की आवश्यकता होती है। मैं इन सभी वस्तुओं में लगभग हर चीज के संदर्भ जोड़ता रहता हूं, लेकिन यह सबकुछ बेहद गन्दा बनाता है।

एक और उदाहरण मैं वेब पर पाया: "। 'कट' एक्शन किया है चाहेंगे" http://www.devdaily.com/java/java-action-abstractaction-actionlistener

मैं समझता हूँ कि यह कैसे काम करता है, क्या मुझे समझ नहीं आता वास्तव में परिवर्तित करने का तरीका है वास्तविक कटौती कार्रवाई में। आइए मान लें कि इसमें दर्शक में मेरी छवि का एक हिस्सा शामिल करना शामिल है, क्या मैं छवि को कार्रवाई में पास कर दूंगा? और यदि इस प्रक्रिया में अधिक समय लगेगा, तो क्या मैंने कार्रवाई के अंदर एक नया स्विंगवर्कर बनाया होगा? और फिर मैं स्विंगवर्कर को गणना करते समय GUI को कैसे अपडेट करूं? क्या मैं स्विंगवर्कर को जीयूआई का संदर्भ दूंगा जैसे कि यह समय-समय पर अपडेट कर सके?

क्या किसी के पास यह कैसे करना है या शायद इसे सही ढंग से सीखने के तरीके पर कुछ सुझाव हैं, क्योंकि मुझे कुछ नुकसान हुआ है। चीजों को करने के लिए बहुत सारी जानकारी और कई अलग-अलग तरीके हैं, और मैं वास्तव में सीखना चाहता हूं कि क्लीन कोड के साथ स्केलेबल एप्लिकेशन कैसे बनाएं। क्या शायद एक अच्छा ओपन-सोर्स प्रोजेक्ट है जिसमें बहुत अधिक कोड नहीं है जो कि मैंने जो वर्णन किया है, उतना ही अच्छी तरह से एक जीयूआई प्रदर्शित करता है ताकि मैं उससे सीख सकूं?

+1

भी देखें इस [उदाहरण] (http://stackoverflow.com/a/3072979/230513) या इस [उदाहरण] (http://stackoverflow.com/a/8534162/230513), दोनों में से किसी जो आपके [एसएससीएस] (http://sscce.org/) को सूचित कर सकता है। – trashgod

+0

आप एमवीपी (मॉडल-व्यू-प्रेजेंटर) भी देखना चाहते हैं, उदा। [इस प्रस्तुति] में [http://www.jgoodies.com/download/presentations/patterns-and-binding.pdf) – Robin

उत्तर

6

मैंने कुछ स्विंग और एसडब्ल्यूटी जीयूआई बनाया है। मुझे जो मिला है वह है कि एक जीयूआई के लिए अपने मॉडल - व्यू (एमवी) संरचना की आवश्यकता होती है। एप्लिकेशन नियंत्रक जीयूआई घटकों की बजाय जीयूआई मॉडल के साथ बातचीत करता है।

असल में, मैं अपने जीयूआई में प्रत्येक स्विंग जेपीनेल के लिए जावा बीन का निर्माण करता हूं। जीयूआई घटक जावा बीन के साथ बातचीत करते हैं, और एप्लिकेशन नियंत्रक जावा बीन के साथ इंटरैक्ट करता है।

यहां एक स्पाइरोग्राफ जीयूआई है जिसे मैंने बनाया है।

enter image description here

यहाँ जावा सेम कि spirograph मापदंडों का प्रबंधन करता है।

import java.awt.Color; 

public class ControlModel { 

    protected boolean isAnimated; 

    protected int jpanelWidth; 
    protected int outerCircle; 
    protected int innerCircle; 
    protected int penLocation; 
    protected int penSize; 

    protected Color penColor; 
    protected Color backgroundColor; 

    public ControlModel() { 
     init(); 
     this.penColor = Color.BLUE; 
     this.backgroundColor = Color.WHITE; 
    } 

    public void init() { 
     this.jpanelWidth = 512; 
     this.outerCircle = 1000; 
     this.innerCircle = 520; 
     this.penLocation = 400; 
     this.penSize = 2; 
     this.isAnimated = true; 
    } 

    public int getOuterCircle() { 
     return outerCircle; 
    } 

    public void setOuterCircle(int outerCircle) { 
     this.outerCircle = outerCircle; 
    } 

    public int getInnerCircle() { 
     return innerCircle; 
    } 

    public void setInnerCircle(int innerCircle) { 
     this.innerCircle = innerCircle; 
    } 

    public int getPenLocation() { 
     return penLocation; 
    } 

    public void setPenLocation(int penLocation) { 
     this.penLocation = penLocation; 
    } 

    public int getPenSize() { 
     return penSize; 
    } 

    public void setPenSize(int penSize) { 
     this.penSize = penSize; 
    } 

    public boolean isAnimated() { 
     return isAnimated; 
    } 

    public void setAnimated(boolean isAnimated) { 
     this.isAnimated = isAnimated; 
    } 

    public Color getPenColor() { 
     return penColor; 
    } 

    public void setPenColor(Color penColor) { 
     this.penColor = penColor; 
    } 

    public Color getBackgroundColor() { 
     return backgroundColor; 
    } 

    public void setBackgroundColor(Color backgroundColor) { 
     this.backgroundColor = backgroundColor; 
    } 

    public int getJpanelWidth() { 
     return jpanelWidth; 
    } 

    public int getJpanelHeight() { 
     return jpanelWidth; 
    } 

} 

संपादित नियंत्रण कक्ष वर्ग को जोड़ने के लिए।

import java.awt.Color; 
import java.awt.Component; 
import java.awt.Container; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.GridLayout; 
import java.awt.Insets; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.JButton; 
import javax.swing.JColorChooser; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JTextField; 
import javax.swing.JToggleButton; 
import javax.swing.SwingConstants; 

import com.ggl.spirograph.model.ControlModel; 

public class ControlPanel { 

    protected static final Insets entryInsets = new Insets(0, 10, 4, 10); 
    protected static final Insets titleInsets = new Insets(0, 10, 20, 10); 

    protected ControlModel model; 

    protected DrawingPanel drawingPanel; 

    protected JButton drawButton; 
    protected JButton stopButton; 
    protected JButton resetButton; 
    protected JButton foregroundColorButton; 
    protected JButton backgroundColorButton; 

    protected JLabel message; 

    protected JPanel panel; 

    protected JTextField outerCircleField; 
    protected JTextField innerCircleField; 
    protected JTextField penLocationField; 
    protected JTextField penSizeField; 
    protected JTextField penFadeField; 

    protected JToggleButton animationToggleButton; 
    protected JToggleButton fastToggleButton; 

    protected static final int messageLength = 100; 
    protected String blankMessage; 

    public ControlPanel(ControlModel model) { 
     this.model = model; 
     this.blankMessage = createBlankMessage(); 
     createPartControl(); 
     setFieldValues(); 
     setColorValues(); 
    } 

    public void setDrawingPanel(DrawingPanel drawingPanel) { 
     this.drawingPanel = drawingPanel; 
    } 

    protected String createBlankMessage() { 
     StringBuilder sb = new StringBuilder(); 
     for (int i = 0; i < messageLength/4; i++) { 
      sb.append(" "); 
     } 
     return sb.toString(); 
    } 

    protected void createPartControl() { 
     panel = new JPanel(); 
     panel.setLayout(new GridBagLayout()); 

     int gridy = 0; 

     JLabel title = new JLabel("Spirograph Parameters"); 
     title.setHorizontalAlignment(SwingConstants.CENTER); 
     addComponent(panel, title, 0, gridy++, 4, 1, titleInsets, 
       GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL); 

     resetButton = new JButton("Reset Default Parameters"); 
     resetButton.setHorizontalAlignment(SwingConstants.CENTER); 
     resetButton.addActionListener(new ResetButtonListener()); 
     addComponent(panel, resetButton, 0, gridy++, 4, 1, entryInsets, 
       GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL); 

     JLabel outerCircleLabel = new JLabel("Outer circle radius:"); 
     outerCircleLabel.setHorizontalAlignment(SwingConstants.LEFT); 
     addComponent(panel, outerCircleLabel, 0, gridy, 2, 1, entryInsets, 
       GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); 

     outerCircleField = new JTextField(5); 
     outerCircleField.setHorizontalAlignment(SwingConstants.LEFT); 
     addComponent(panel, outerCircleField, 2, gridy++, 2, 1, entryInsets, 
       GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); 

     JLabel innerCircleLabel = new JLabel("Inner circle radius:"); 
     innerCircleLabel.setHorizontalAlignment(SwingConstants.LEFT); 
     addComponent(panel, innerCircleLabel, 0, gridy, 2, 1, entryInsets, 
       GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); 

     innerCircleField = new JTextField(5); 
     innerCircleField.setHorizontalAlignment(SwingConstants.LEFT); 
     addComponent(panel, innerCircleField, 2, gridy++, 2, 1, entryInsets, 
       GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); 

     JLabel penLocationLabel = new JLabel("Pen location radius:"); 
     penLocationLabel.setHorizontalAlignment(SwingConstants.LEFT); 
     addComponent(panel, penLocationLabel, 0, gridy, 2, 1, entryInsets, 
       GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); 

     penLocationField = new JTextField(5); 
     penLocationField.setHorizontalAlignment(SwingConstants.LEFT); 
     addComponent(panel, penLocationField, 2, gridy++, 2, 1, entryInsets, 
       GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); 

     JLabel penSizeLabel = new JLabel("Pen size:"); 
     penSizeLabel.setHorizontalAlignment(SwingConstants.LEFT); 
     addComponent(panel, penSizeLabel, 0, gridy, 2, 1, entryInsets, 
       GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); 

     penSizeField = new JTextField(5); 
     penSizeField.setHorizontalAlignment(SwingConstants.LEFT); 
     addComponent(panel, penSizeField, 2, gridy++, 2, 1, entryInsets, 
       GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); 

     message = new JLabel(blankMessage); 
     message.setForeground(Color.RED); 
     message.setHorizontalAlignment(SwingConstants.LEFT); 
     addComponent(panel, message, 0, gridy++, 4, 1, titleInsets, 
       GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); 

     title = new JLabel("Drawing Speed"); 
     title.setHorizontalAlignment(SwingConstants.CENTER); 
     addComponent(panel, title, 0, gridy++, 4, 1, titleInsets, 
       GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL); 

     JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 4, 0)); 

     animationToggleButton = new JToggleButton("Animated"); 
     animationToggleButton.setSelected(model.isAnimated()); 
     animationToggleButton.setHorizontalAlignment(SwingConstants.CENTER); 
     animationToggleButton.addActionListener(new DrawingSpeedListener(
       animationToggleButton)); 
     buttonPanel.add(animationToggleButton); 

     fastToggleButton = new JToggleButton("Fast"); 
     fastToggleButton.setSelected(!model.isAnimated()); 
     fastToggleButton.setHorizontalAlignment(SwingConstants.CENTER); 
     fastToggleButton.addActionListener(new DrawingSpeedListener(
       fastToggleButton)); 
     buttonPanel.add(fastToggleButton); 

     addComponent(panel, buttonPanel, 0, gridy++, 4, 1, titleInsets, 
       GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL); 

     title = new JLabel("Drawing Colors"); 
     title.setHorizontalAlignment(SwingConstants.CENTER); 
     addComponent(panel, title, 0, gridy++, 4, 1, titleInsets, 
       GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL); 

     buttonPanel = new JPanel(new GridLayout(1, 2, 4, 0)); 

     foregroundColorButton = new JButton("Pen"); 
     foregroundColorButton.setHorizontalAlignment(SwingConstants.CENTER); 
     foregroundColorButton.addActionListener(new ColorSelectListener(
       foregroundColorButton)); 
     buttonPanel.add(foregroundColorButton); 

     backgroundColorButton = new JButton("Paper"); 
     backgroundColorButton.setHorizontalAlignment(SwingConstants.CENTER); 
     backgroundColorButton.addActionListener(new ColorSelectListener(
       backgroundColorButton)); 
     buttonPanel.add(backgroundColorButton); 

     addComponent(panel, buttonPanel, 0, gridy++, 4, 1, titleInsets, 
       GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL); 

     title = new JLabel("Drawing Controls"); 
     title.setHorizontalAlignment(SwingConstants.CENTER); 
     addComponent(panel, title, 0, gridy++, 4, 1, titleInsets, 
       GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL); 

     buttonPanel = new JPanel(new GridLayout(1, 2, 4, 0)); 

     drawButton = new JButton("Draw"); 
     drawButton.setHorizontalAlignment(SwingConstants.CENTER); 
     drawButton.addActionListener(new DrawButtonListener()); 
     buttonPanel.add(drawButton); 

     stopButton = new JButton("Stop"); 
     stopButton.setHorizontalAlignment(SwingConstants.CENTER); 
     stopButton.addActionListener(new StopButtonListener()); 
     buttonPanel.add(stopButton); 

     addComponent(panel, buttonPanel, 0, gridy++, 4, 1, titleInsets, 
       GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL); 
    } 

    protected void addComponent(Container container, Component component, 
      int gridx, int gridy, int gridwidth, int gridheight, 
      Insets insets, int anchor, int fill) { 
     GridBagConstraints gbc = new GridBagConstraints(gridx, gridy, 
       gridwidth, gridheight, 1.0, 1.0, anchor, fill, insets, 0, 0); 
     container.add(component, gbc); 
    } 

    protected void setFieldValues() { 
     outerCircleField.setText(Integer.toString(model.getOuterCircle())); 
     innerCircleField.setText(Integer.toString(model.getInnerCircle())); 
     penLocationField.setText(Integer.toString(model.getPenLocation())); 
     penSizeField.setText(Integer.toString(model.getPenSize())); 
    } 

    protected void setColorValues() { 
     foregroundColorButton.setForeground(model.getBackgroundColor()); 
     foregroundColorButton.setBackground(model.getPenColor()); 

     backgroundColorButton.setForeground(model.getPenColor()); 
     backgroundColorButton.setBackground(model.getBackgroundColor()); 
    } 

    public JPanel getPanel() { 
     return panel; 
    } 

    public class ResetButtonListener implements ActionListener { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      model.init(); 
      setFieldValues(); 
     } 

    } 

    public class StopButtonListener implements ActionListener { 

     @Override 
     public void actionPerformed(ActionEvent arg0) { 
      drawingPanel.stop(); 
     } 

    } 

    public class DrawButtonListener implements ActionListener { 

     @Override 
     public void actionPerformed(ActionEvent event) { 
      message.setText(blankMessage); 

      int ocTest = isNumeric(outerCircleField.getText()); 
      int icTest = isNumeric(innerCircleField.getText()); 
      int plTest = isNumeric(penLocationField.getText()); 
      int psTest = isNumeric(penSizeField.getText()); 

      boolean isInvalid = false; 

      if (psTest < 0) { 
       message.setText("Pen size is not a valid integer"); 
       isInvalid = true; 
      } 

      if (plTest < 0) { 
       message.setText("Pen location radius is not a valid integer"); 
       isInvalid = true; 
      } 

      if (icTest < 0) { 
       message.setText("Inner circle radius is not a valid integer"); 
       isInvalid = true; 
      } 

      if (ocTest < 0) { 
       message.setText("Outer circle radius is not a valid integer"); 
       isInvalid = true; 
      } 

      if (isInvalid) { 
       return; 
      } 

      if (ocTest > 1000) { 
       message.setText("The outer circle cannot be larger than 1000"); 
       isInvalid = true; 
      } 

      if (ocTest <= icTest) { 
       message.setText("The inner circle must be smaller than the outer circle"); 
       isInvalid = true; 
      } 

      if (icTest <= plTest) { 
       message.setText("The pen location must be smaller than the inner circle"); 
       isInvalid = true; 
      } 

      if (isInvalid) { 
       return; 
      } 

      model.setOuterCircle(ocTest); 
      model.setInnerCircle(icTest); 
      model.setPenLocation(plTest); 
      model.setPenSize(psTest); 

      drawingPanel.draw(model.isAnimated()); 
     } 

     protected int isNumeric(String field) { 
      try { 
       return Integer.parseInt(field); 
      } catch (NumberFormatException e) { 
       return Integer.MIN_VALUE; 
      } 
     } 

    } 

    public class DrawingSpeedListener implements ActionListener { 

     JToggleButton selectedButton; 

     public DrawingSpeedListener(JToggleButton selectedButton) { 
      this.selectedButton = selectedButton; 
     } 

     @Override 
     public void actionPerformed(ActionEvent arg0) { 
      if (selectedButton.equals(animationToggleButton)) { 
       model.setAnimated(true); 
      } else { 
       model.setAnimated(false); 
      } 

      animationToggleButton.setSelected(model.isAnimated()); 
      fastToggleButton.setSelected(!model.isAnimated()); 
     } 

    } 

    public class ColorSelectListener implements ActionListener { 

     JButton selectedButton; 

     public ColorSelectListener(JButton selectedButton) { 
      this.selectedButton = selectedButton; 
     } 

     @Override 
     public void actionPerformed(ActionEvent arg0) { 
      if (selectedButton.equals(foregroundColorButton)) { 
       Color initialColor = model.getPenColor(); 
       Color selectedColor = JColorChooser.showDialog(drawingPanel, 
         "Select pen color", initialColor); 
       if (selectedColor != null) { 
        model.setPenColor(selectedColor); 
       } 
      } else if (selectedButton.equals(backgroundColorButton)) { 
       Color initialColor = model.getBackgroundColor(); 
       Color selectedColor = JColorChooser.showDialog(drawingPanel, 
         "Select paper color", initialColor); 
       if (selectedColor != null) { 
        model.setBackgroundColor(selectedColor); 
       } 
      } 
      setColorValues(); 
     } 

    } 

} 
+0

ठीक है, यह बहुत उपयोगी लगता है, इसलिए मुझे लगता है कि मुझे प्रोग्राम की स्थिति को सहेजना होगा , उदाहरण के लिए, कुछ मेनविंडोस्टेट ऑब्जेक्ट में, कम से कम इसका जीयूआई हिस्सा। लेकिन फिर मेरा अगला प्रश्न: जब कोई कलम कलर बटन पर क्लिक करता है तो क्या होता है? क्या उसमें से एक श्रोता संलग्न है जिसके पास ControlModel तक पहुंच है? और क्या यह श्रोता एक अलग वर्ग में है या क्या इसे नियंत्रण जेपीनेल में एक आंतरिक वर्ग के रूप में जोड़ा गया है? – FinalArt2005

+1

आपके प्रश्न का उत्तर देने का सबसे आसान तरीका है मेरे उत्तर में नियंत्रण कक्ष के लिए कोड शामिल करना। –

+1

मुझे आपके जीयूआई आवेदन का कोड दिखाने के लिए बहुत बहुत धन्यवाद, यह वास्तव में मुझे यह समझने में मदद करता है कि आपके आवेदन में विभिन्न घटक कैसे इंटरैक्ट करते हैं। मैंने अब अपने आवेदन के लिए एक डिज़ाइन योजना लिखी है और मैं कल कोड लिखना शुरू कर दूंगा। अगर मैं समस्याओं में भाग लेता हूं तो मैं यहां वापस आऊंगा, लेकिन अभी के लिए आपने मुझे बहुत मदद की, धन्यवाद! – FinalArt2005

संबंधित मुद्दे