জে টেক্সটফিল্ডে মান পরিবর্তন শ্রোতাদের


215

আমি চাই যে ব্যবহারকারী পাঠ্যক্ষেত্রের মান পরিবর্তন করার সাথে সাথে বার্তা বাক্সটি উপস্থিত হয়। বর্তমানে, বার্তাটি পপ-আপ করার জন্য আমার প্রবেশ কী টিপুন। আমার কোডে কিছু ভুল আছে?

textField.addActionListener(new java.awt.event.ActionListener() {
    public void actionPerformed(java.awt.event.ActionEvent e) {

        if (Integer.parseInt(textField.getText())<=0){
            JOptionPane.showMessageDialog(null,
                    "Error: Please enter number bigger than 0", "Error Message",
                    JOptionPane.ERROR_MESSAGE);
        }       
    }
}

কোন সাহায্য প্রশংসা হবে!

উত্তর:


373

অন্তর্নিহিত নথিতে শ্রোতা যুক্ত করুন, যা স্বয়ংক্রিয়ভাবে আপনার জন্য তৈরি করা হয়েছে।

// Listen for changes in the text
textField.getDocument().addDocumentListener(new DocumentListener() {
  public void changedUpdate(DocumentEvent e) {
    warn();
  }
  public void removeUpdate(DocumentEvent e) {
    warn();
  }
  public void insertUpdate(DocumentEvent e) {
    warn();
  }

  public void warn() {
     if (Integer.parseInt(textField.getText())<=0){
       JOptionPane.showMessageDialog(null,
          "Error: Please enter number bigger than 0", "Error Message",
          JOptionPane.ERROR_MESSAGE);
     }
  }
});

সতর্কতা / টাইপ কাস্টের জন্য ভাল ফর্ম্যাট। একই প্যাটার্নটি দ্বিগুণ পরিমাণ (বিক্রয় পরিসংখ্যান / মূল্য প্রবেশ করানো বা প্রদর্শিত) পরিচালনা করতে কার্যকর হবে
ম্যাক্স ওয়েস্ট

এটি ঠিকঠাক কাজ করছে তবে আমার একটি প্রশ্ন রয়েছে যে আমি যখন টেক্সটফিল্ডে কিছু পাঠ্য সন্নিবেশ করি তখন আমি কোনও পদ্ধতিতে কল করতে চাই। এটি কীভাবে করা হয় সে সম্পর্কে আমার খুব বেশি ধারণা নেই ...

আমি অন্য কোনও টেবিল কক্ষে ক্লিক করার সময় একটি জেটিবেলকে সম্পাদনাযোগ্য জকমোবক্স থেকে পাঠ্য বাক্সের আপডেট না পেয়ে সমস্যা হচ্ছিল এবং এটিকে সঠিকভাবে কাজ করার একমাত্র উপায় ছিল এখানে সন্নিবেশআপড ফাংশন।
উইনচেলা

14
"ম্যাসেজ ত্রুটি"
ungato

51

এর সাধারণ উত্তরটি হল "ইউজ এ DocumentListener" " যাইহোক, আমি সর্বদা সেই ইন্টারফেসটিকে জটিল মনে করি find সত্য সত্য ইন্টারফেস অতিরিক্ত ইঞ্জিনিয়ারড। পাঠ্য সন্নিবেশ, অপসারণ এবং প্রতিস্থাপনের জন্য এর তিনটি পদ্ধতি রয়েছে, যখন কেবলমাত্র একটি পদ্ধতি প্রয়োজন: প্রতিস্থাপন। (একটি সন্নিবেশকে কিছু পাঠ্যের সাথে কোনও পাঠ্য প্রতিস্থাপন হিসাবে দেখা যায় এবং কোনও অপসারণ কোনও পাঠ্য না করেই কোনও পাঠ্য প্রতিস্থাপন হিসাবে দেখা যায়))

সাধারণত আপনি যা জানতে চান তা হ'ল বাক্সের পাঠ্যটি কখন পরিবর্তন হয়েছে , সুতরাং একটি সাধারণ DocumentListenerপ্রয়োগের তিনটি পদ্ধতিতে একটি পদ্ধতিকে কল করা হয়।

অতএব আমি নিম্নলিখিত ইউটিলিটি পদ্ধতিটি তৈরি করেছি, যা আপনাকে এগুলির ChangeListenerচেয়ে সহজতর ব্যবহার করতে দেয় DocumentListener। (এটি জাভা 8-এর ল্যাম্বদা সিনট্যাক্স ব্যবহার করে তবে প্রয়োজনে আপনি এটি পুরানো জাভার জন্য মানিয়ে নিতে পারেন))

/**
 * Installs a listener to receive notification when the text of any
 * {@code JTextComponent} is changed. Internally, it installs a
 * {@link DocumentListener} on the text component's {@link Document},
 * and a {@link PropertyChangeListener} on the text component to detect
 * if the {@code Document} itself is replaced.
 * 
 * @param text any text component, such as a {@link JTextField}
 *        or {@link JTextArea}
 * @param changeListener a listener to receieve {@link ChangeEvent}s
 *        when the text is changed; the source object for the events
 *        will be the text component
 * @throws NullPointerException if either parameter is null
 */
public static void addChangeListener(JTextComponent text, ChangeListener changeListener) {
    Objects.requireNonNull(text);
    Objects.requireNonNull(changeListener);
    DocumentListener dl = new DocumentListener() {
        private int lastChange = 0, lastNotifiedChange = 0;

        @Override
        public void insertUpdate(DocumentEvent e) {
            changedUpdate(e);
        }

        @Override
        public void removeUpdate(DocumentEvent e) {
            changedUpdate(e);
        }

        @Override
        public void changedUpdate(DocumentEvent e) {
            lastChange++;
            SwingUtilities.invokeLater(() -> {
                if (lastNotifiedChange != lastChange) {
                    lastNotifiedChange = lastChange;
                    changeListener.stateChanged(new ChangeEvent(text));
                }
            });
        }
    };
    text.addPropertyChangeListener("document", (PropertyChangeEvent e) -> {
        Document d1 = (Document)e.getOldValue();
        Document d2 = (Document)e.getNewValue();
        if (d1 != null) d1.removeDocumentListener(dl);
        if (d2 != null) d2.addDocumentListener(dl);
        dl.changedUpdate(null);
    });
    Document d = text.getDocument();
    if (d != null) d.addDocumentListener(dl);
}

ডকুমেন্টে সরাসরি শ্রোতা যুক্ত করার বিপরীতে, এটি (অসাধারণ) কেস পরিচালনা করে যে আপনি কোনও পাঠ্য উপাদানটিতে একটি নতুন দস্তাবেজ অবজেক্ট ইনস্টল করেছেন। অধিকন্তু, এটি জিন-মার্ক অ্যাসেটসানার উত্তরে উল্লিখিত সমস্যাটিকে ঘিরে কাজ করে , যেখানে ডকুমেন্টটি কখনও কখনও তার প্রয়োজনের চেয়ে বেশি ইভেন্টে গুলি চালায়

যাইহোক, এই পদ্ধতিটি আপনাকে বিরক্তিকর কোডটি প্রতিস্থাপন করতে দেয় যা দেখতে এটির মতো দেখাচ্ছে:

someTextBox.getDocument().addDocumentListener(new DocumentListener() {
    @Override
    public void insertUpdate(DocumentEvent e) {
        doSomething();
    }

    @Override
    public void removeUpdate(DocumentEvent e) {
        doSomething();
    }

    @Override
    public void changedUpdate(DocumentEvent e) {
        doSomething();
    }
});

সঙ্গে:

addChangeListener(someTextBox, e -> doSomething());

কোড পাবলিক ডোমেনে প্রকাশিত। আনন্দ কর!


5
অনুরূপ সমাধান: abstract class DocumentChangeListener implements DocumentListenerএকটি অতিরিক্ত বিমূর্ত পদ্ধতি সহ একটি তৈরি করুন change(DocumentEvent e)যা আপনি অন্য 3 টি পদ্ধতি থেকে কল করেন। এটি আমার কাছে আরও স্পষ্ট বলে মনে হচ্ছে যেহেতু এটি abstract *Adapterশ্রোতাদের মতো কম-বেশি একই যুক্তি ব্যবহার করে ।
geronimo

changedUpdateপদ্ধতি হিসাবে +1 স্পষ্টভাবে প্রত্যেকের মধ্যে একটি কলের মাধ্যমে insertUpdateএবং removeUpdateএটি কাজ করার জন্য অনুরোধ করা হবে ..
কাইস

16

ডকুমেন্টলিস্টনার প্রসারিত এবং সমস্ত ডকুমেন্টলিস্টনার পদ্ধতি প্রয়োগ করে: কেবল একটি ইন্টারফেস তৈরি করুন

@FunctionalInterface
public interface SimpleDocumentListener extends DocumentListener {
    void update(DocumentEvent e);

    @Override
    default void insertUpdate(DocumentEvent e) {
        update(e);
    }
    @Override
    default void removeUpdate(DocumentEvent e) {
        update(e);
    }
    @Override
    default void changedUpdate(DocumentEvent e) {
        update(e);
    }
}

এবং তারপর:

jTextField.getDocument().addDocumentListener(new SimpleDocumentListener() {
    @Override
    public void update(DocumentEvent e) {
        // Your code here
    }
});

অথবা আপনি ল্যাম্বদা এক্সপ্রেশন ব্যবহার করতে পারেন:

jTextField.getDocument().addDocumentListener((SimpleDocumentListener) e -> {
    // Your code here
});

1
ভুলে যাবেন না যে এই সমাধানটির জাভা ৮ এর আগে সমস্ত সংস্করণে ইন্টারফেসের পরিবর্তে একটি বিমূর্ত শ্রেণীর প্রয়োজন
ক্লার

15

সচেতন হন যে ব্যবহারকারী যখন ক্ষেত্রটি সংশোধন করে, ডকুমেন্টলিস্টনার কিছু সময় দুটি ইভেন্ট পেতে পারে। উদাহরণস্বরূপ যদি ব্যবহারকারী পুরো ক্ষেত্রের সামগ্রী নির্বাচন করে, তবে একটি কী টিপুন, আপনি একটি অপসারণ আপডেট (সমস্ত সামগ্রী মুছে ফেলা হবে) এবং একটি সন্নিবেশকৃত আপডেট পাবেন। আপনার ক্ষেত্রে, আমি মনে করি এটি সমস্যা নয় তবে সাধারণভাবে বলতে গেলে এটি হয় is দুর্ভাগ্যক্রমে, মনে হচ্ছে জে টেক্সটফিল্ড সাবক্লাসিং না করে পাঠ্যফিল্ডের সামগ্রীটি ট্র্যাক করার কোনও উপায় নেই। এখানে একটি শ্রেণীর কোড যা একটি "পাঠ্য" বৈশিষ্ট্য সরবরাহ করে:

package net.yapbam.gui.widget;

import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

/** A JTextField with a property that maps its text.
 * <br>I've found no way to track efficiently the modifications of the text of a JTextField ... so I developed this widget.
 * <br>DocumentListeners are intended to do it, unfortunately, when a text is replace in a field, the listener receive two events:<ol>
 * <li>One when the replaced text is removed.</li>
 * <li>One when the replacing text is inserted</li>
 * </ul>
 * The first event is ... simply absolutely misleading, it corresponds to a value that the text never had.
 * <br>Anoter problem with DocumentListener is that you can't modify the text into it (it throws IllegalStateException).
 * <br><br>Another way was to use KeyListeners ... but some key events are throw a long time (probably the key auto-repeat interval)
 * after the key was released. And others events (for example a click on an OK button) may occurs before the listener is informed of the change.
 * <br><br>This widget guarantees that no "ghost" property change is thrown !
 * @author Jean-Marc Astesana
 * <BR>License : GPL v3
 */

public class CoolJTextField extends JTextField {
    private static final long serialVersionUID = 1L;

    public static final String TEXT_PROPERTY = "text";

    public CoolJTextField() {
        this(0);
    }

    public CoolJTextField(int nbColumns) {
        super("", nbColumns);
        this.setDocument(new MyDocument());
    }

    @SuppressWarnings("serial")
    private class MyDocument extends PlainDocument {
        private boolean ignoreEvents = false;

        @Override
        public void replace(int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
            String oldValue = CoolJTextField.this.getText();
            this.ignoreEvents = true;
            super.replace(offset, length, text, attrs);
            this.ignoreEvents = false;
            String newValue = CoolJTextField.this.getText();
            if (!oldValue.equals(newValue)) CoolJTextField.this.firePropertyChange(TEXT_PROPERTY, oldValue, newValue);
        }

        @Override
        public void remove(int offs, int len) throws BadLocationException {
            String oldValue = CoolJTextField.this.getText();
            super.remove(offs, len);
            String newValue = CoolJTextField.this.getText();
            if (!ignoreEvents && !oldValue.equals(newValue)) CoolJTextField.this.firePropertyChange(TEXT_PROPERTY, oldValue, newValue);
        }
    }

3
সুইং ইতিমধ্যে হয়েছে পাঠ্যক্ষেত্র এক ধরনের যে একটি সম্পত্তি দস্তাবেজের পরিবর্তনগুলি মানচিত্র - এটা JFormattedTextField বলা হচ্ছে :-)
kleopatra

11

আমি জানি এটি একটি সত্যই পুরানো সমস্যার সাথে সম্পর্কিত, তবে এটি আমার কিছু সমস্যার কারণও হয়েছিল। ক্লিওপাত্রা যেমন উপরে একটি মন্তব্যে প্রতিক্রিয়া জানিয়েছে, আমি সমস্যা সমাধান করেছি একটি দিয়ে JFormattedTextField। যাইহোক, সমাধানটির জন্য আরও কিছু কাজ প্রয়োজন, তবে এটি আরও পরিচ্ছন্ন।

JFormattedTextFieldডিফল্ট ট্রিগার দ্বারা একটি সম্পত্তি পরিবর্তন যে টেক্সট পর মাঠে পরিবর্তন করে না। এর ডিফল্ট কনস্ট্রাক্টর JFormattedTextFieldএকটি ফর্ম্যাটর তৈরি করে না।

তবে ওপি যা পরামর্শ দিয়েছে তা করতে, আপনাকে এমন একটি ফর্ম্যাটর ব্যবহার করতে হবে যা commitEdit()ক্ষেত্রটির প্রতিটি বৈধ সম্পাদনার পরে পদ্ধতিটি শুরু করবে । commitEdit()পদ্ধতি এই ডিফল্টরূপে নজরদারি পরিবর্তন অথবা যখন চাবি টেপা হলে লিখুন উপর সূত্রপাত হয়, আমি কি দেখতে পাচ্ছ? থেকে ফরম্যাটার ছাড়া সম্পত্তি পরিবর্তন আরম্ভ করে হয়।

আরও তথ্যের জন্য http://docs.oracle.com/javase/tutorial/uiswing/components/formattedtextfield.html#value দেখুন ।

এটির কনস্ট্রাক্টর বা সেটার পদ্ধতির মাধ্যমে হয় কোনও ডিফল্ট ফর্ম্যাটার ( DefaultFormatter) অবজেক্ট তৈরি করুন JFormattedTextField। ডিফল্ট ফর্ম্যাটারের একটি পদ্ধতি হ'ল পাঠ্যটি প্রতিবার পরিবর্তিত setCommitsOnValidEdit(boolean commit)হওয়ার সাথে সাথে commitEdit()পদ্ধতিটি ট্রিগার করতে ফর্ম্যাটর সেট করে। এটি পরে PropertyChangeListenerএবং একটি propertyChange()পদ্ধতি ব্যবহার করে বাছাই করা যেতে পারে ।


2
textBoxName.getDocument().addDocumentListener(new DocumentListener() {
   @Override
   public void insertUpdate(DocumentEvent e) {
       onChange();
   }

   @Override
   public void removeUpdate(DocumentEvent e) {
      onChange();
   }

   @Override
   public void changedUpdate(DocumentEvent e) {
      onChange();
   } 
});

তবে আমি কেবল তার কীবোর্ডে ব্যবহারকারীর (সম্ভবত দুর্ঘটনায়) যে কোনও কিছু স্পর্শ করে তার কোনও বিশ্লেষণ করব না Integer। আপনার যে কোনও Exceptionগুলি ফেলে দেওয়া উচিত এবং JTextFieldতা খালি নেই তা নিশ্চিত করা উচিত ।


2

যদি আমরা দৌড়নযোগ্য পদ্ধতিটি ব্যবহার করি তবে ডকুমেন্ট শ্রোতার অ্যাপ্লিকেশনটি কখনও কখনও আটকা পড়ে যায় এবং ফলাফলটি আপডেট করতে সময় নেয় (আমার পরীক্ষা অনুযায়ী)। এর পরিবর্তে আমরা এখানে উল্লিখিত হিসাবে পাঠ্য ক্ষেত্র পরিবর্তন শ্রোতার জন্য কী-রিলেজড ইভেন্টটিও ব্যবহার করতে পারি

usernameTextField.addKeyListener(new KeyAdapter() {
    public void keyReleased(KeyEvent e) {
        JTextField textField = (JTextField) e.getSource();
        String text = textField.getText();
        textField.setText(text.toUpperCase());
    }
});

1

এটি কোডমউইনসি-র আপডেট সংস্করণ ছিল। তার কোডটি বেশ ভাল এবং ত্রুটি বার্তা ব্যতীত দুর্দান্ত কাজ করে। ত্রুটি এড়াতে আপনার অবশ্যই শর্ত বিবৃতি পরিবর্তন করতে হবে।

  // Listen for changes in the text
textField.getDocument().addDocumentListener(new DocumentListener() {
  public void changedUpdate(DocumentEvent e) {
    warn();
  }
  public void removeUpdate(DocumentEvent e) {
    warn();
  }
  public void insertUpdate(DocumentEvent e) {
    warn();
  }

  public void warn() {
     if (textField.getText().length()>0){
       JOptionPane.showMessageDialog(null,
          "Error: Please enter number bigger than 0", "Error Massage",
          JOptionPane.ERROR_MESSAGE);
     }
  }
});

যখনই টেক্সটফিল্ডে দৈর্ঘ্য = 0 এর চেয়ে বেশি দীর্ঘতম স্ট্রিং প্রবেশ করা হয় তখন আপনার অভিযোজন ত্রুটি বার্তা সংলাপটিকে আগুন দেয়। সুতরাং এটি মূলত খালি স্ট্রিং ব্যতীত অন্য কোনও স্ট্রিং। এটি অনুরোধ করা সমাধান নয়।
ক্লার

0

আপনি নিয়ন্ত্রণ করতে এমনকি "মাউসএক্সিত" ব্যবহার করতে পারেন। উদাহরণ:

 private void jtSoMauMouseExited(java.awt.event.MouseEvent evt) {                                    
        // TODO add your handling code here:
        try {
            if (Integer.parseInt(jtSoMau.getText()) > 1) {
                //auto update field
                SoMau = Integer.parseInt(jtSoMau.getText());
                int result = SoMau / 5;

                jtSoBlockQuan.setText(String.valueOf(result));
            }
        } catch (Exception e) {

        }

    }   

6
সত্যিই না: প্রয়োজন কিছু করছে যখন টেক্সট পরিবর্তিত হয় - যে mouseEvents করার ;-) সম্পর্কহীন এর
kleopatra

0

আমি উইন্ডোবিল্ডারের কাছে একেবারে নতুন, এবং আসলে কয়েক বছর পরে জাভাতে ফিরে আসছি, তবে আমি "কিছু" প্রয়োগ করেছি, তখন ভেবেছিলাম আমি এটি সন্ধান করব এবং এই থ্রেডটি পেরিয়ে আসব।

আমি এই পরীক্ষার মাঝখানে আছি, সুতরাং, এই সমস্ত কিছুর জন্য নতুন হওয়ার ভিত্তিতে, আমি নিশ্চিত যে আমার অবশ্যই কিছু মিস করা হবে।

আমি যা করেছি তা এখানে, যেখানে "রানটেক্সট" একটি পাঠ্যবক্স এবং "রাননাম" শ্রেণীর একজন ডেটা সদস্য:

public void focusGained(FocusEvent e) {
    if (e.getSource() == runTxt) {
        System.out.println("runTxt got focus");
        runTxt.selectAll();
    }
}

public void focusLost(FocusEvent e) {
    if (e.getSource() == runTxt) {
        System.out.println("runTxt lost focus");
        if(!runTxt.getText().equals(runName))runName= runTxt.getText();
        System.out.println("runText.getText()= " + runTxt.getText() + "; runName= " + runName);
    }
}

এখন পর্যন্ত এখানে যা আছে তার থেকে অনেক সহজ বলে মনে হচ্ছে, এবং এটি কাজ করছে বলে মনে হচ্ছে, তবে, যেহেতু আমি এই লেখার মাঝখানে আছি, আমি কোনও অবহেলিত গ্যাচচা শুনার প্রশংসা করব। এটি কী এমন একটি সমস্যা যা ব্যবহারকারী প্রবেশ করে পাঠ্যবক্সে ডাব্লু / ও পরিবর্তন রেখে দিতে পারে? আমি মনে করি আপনারা সমস্ত কিছু একটি অপ্রয়োজনীয় কাজ ment


-1

অ্যাকশনলিস্টনারের পরিবর্তে কী-লিস্টেনার (যা কোনও কীতে ট্রিগার করে) ব্যবহার করুন (যা প্রবেশের সময় ট্রিগার করে)


এটি কাজ করে না কারণ ক্ষেত্রের মান সঠিকভাবে ক্যাপচার করা হয়নি, field.getText()প্রাথমিক মানটি দেয়। এবং ইভেন্ট ( arg0.getKeyChar()) কী চাপলে ত্রুটি যাচাই করা দরকার যা ক্ষেত্রের পাঠ্যের সাথে সম্মতি জানাতে হবে কিনা তা নির্ধারণ করতে হবে।
glend

@ ইলেক্ট, আপনি কী টাইপড ইভেন্টের পরিবর্তে কী-রিলেজড ইভেন্ট ব্যবহার করতে পারেন। এটি আমার পক্ষে এবং সম্পূর্ণ মূল্য অর্জনের জন্য কাজ করেছিল।
কাকুমানু শিব কৃষ্ণ

-1

ডকুমেন্টফিল্টার ? এটি আপনাকে কারচুপি করার ক্ষমতা দেয়।

[ Http://www.java2s.com/Tutorial/Java/0240__Swing/FormatJTextFieldstexttouppercase.htm ]

দুঃখিত। জেথন (জাভাতে পাইথন) ব্যবহার করছেন - তবে বুঝতে সহজ

# python style
# upper chars [ text.upper() ]

class myComboBoxEditorDocumentFilter( DocumentFilter ):
def __init__(self,jtext):
    self._jtext = jtext

def insertString(self,FilterBypass_fb, offset, text, AttributeSet_attrs):
    txt = self._jtext.getText()
    print('DocumentFilter-insertString:',offset,text,'old:',txt)
    FilterBypass_fb.insertString(offset, text.upper(), AttributeSet_attrs)

def replace(self,FilterBypass_fb, offset, length, text, AttributeSet_attrs):
    txt = self._jtext.getText()
    print('DocumentFilter-replace:',offset, length, text,'old:',txt)
    FilterBypass_fb.replace(offset, length, text.upper(), AttributeSet_attrs)

def remove(self,FilterBypass_fb, offset, length):
    txt = self._jtext.getText()
    print('DocumentFilter-remove:',offset, length, 'old:',txt)
    FilterBypass_fb.remove(offset, length)

// (java style ~example for ComboBox-jTextField)
cb = new ComboBox();
cb.setEditable( true );
cbEditor = cb.getEditor();
cbEditorComp = cbEditor.getEditorComponent();
cbEditorComp.getDocument().setDocumentFilter(new myComboBoxEditorDocumentFilter(cbEditorComp));
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.