ورود

View Full Version : سوال: جداسازی سه تایی اعداد ، خطای java.lang.IllegalArgumentException



abarkarbar
شنبه 18 اردیبهشت 1395, 00:12 صبح
با سلام، بنده برای جداسازی اعداد به صورت سه تایی صدگان کد زیر را نوشته ام. می خواهم برای یک ورودی متن با عنوان مبلغ، کاربر هنگام وارد کردن مبلغ، جداسازی شود و ویرگول به میان اعداد سه تایی اضافه شود.

این کار را NumberFormat انجام می دهد. برای وارد کردن عدد تا 9 - 10 تایی به خوبی کار می کند فقط مشکلی که هست وقتی از آن عدد وارد شده چیزی را پاک می کنی (Backspace را می زنی)، پیغام خطا می دهد:


txt_value.textProperty().addListener((observable, oldValue, newValue) -> {
NumberFormat nf = NumberFormat.getInstance();
if(!txt_value.getText().isEmpty() && txt_value.getText().replace(",", "").matches("\\d{0,9}"))
txt_value.setText(nf.format(Integer.parseInt(txt_v alue.getText().replace(",", ""))));
});


موقع پاک کردن خطای زیر را می دهد:

java.lang.IllegalArgumentException: The start must be <= the end

آیا کسی راه حلی داره برای خلاصی از این خطا. ممنونم

vahid-p
یک شنبه 19 اردیبهشت 1395, 05:10 صبح
تست کردم اررور نمیده. اگه ممکنه کد رو کاملتر بذارید و اینکه دقیقا چه ورودی وارد کردید و بعد چیکار کردید که این اررور رو داد؟
خطا رو به صورت کامل (+ stacktrace) بذارید

abarkarbar
یک شنبه 19 اردیبهشت 1395, 09:49 صبح
سلام بنده تصویر آن را گذاشتم یا پروژه ای برای آن در نت بینز ساختم می توانید ببینید:

وقتی از آخرش عددها رو پاک می کنی بعده دو سه عدد پاک شدن خطا میده


140279
140282

متن خطا:

Executing C:\Users\Mohammad\Documents\NetBeansProjects\JavaF XApplication53\dist\run465252255\JavaFXApplication 53.jar using platform C:\Program Files\Java\jdk1.8.0_73\jre/bin/java
Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: The start must be <= the end
at javafx.scene.control.TextInputControl.getText(Text InputControl.java:446)
at javafx.scene.control.TextInputControl.updateConten t(TextInputControl.java:564)
at javafx.scene.control.TextInputControl.replaceText( TextInputControl.java:548)
at javafx.scene.control.TextInputControl.deleteText(T extInputControl.java:496)
at javafx.scene.control.TextInputControl.deletePrevio usChar(TextInputControl.java:899)
at com.sun.javafx.scene.control.skin.TextFieldSkin.de leteChar(TextFieldSkin.java:589)
at com.sun.javafx.scene.control.behavior.TextFieldBeh avior.deleteChar(TextFieldBehavior.java:198)
at com.sun.javafx.scene.control.behavior.TextInputCon trolBehavior.deletePreviousChar(TextInputControlBe havior.java:311)
at com.sun.javafx.scene.control.behavior.TextInputCon trolBehavior.callAction(TextInputControlBehavior.j ava:143)
at com.sun.javafx.scene.control.behavior.BehaviorBase .callActionForEvent(BehaviorBase.java:218)
at com.sun.javafx.scene.control.behavior.TextInputCon trolBehavior.callActionForEvent(TextInputControlBe havior.java:127)
at com.sun.javafx.scene.control.behavior.BehaviorBase .lambda$new$74(BehaviorBase.java:135)
at com.sun.javafx.event.CompositeEventHandler$NormalE ventHandlerRecord.handleBubblingEvent(CompositeEve ntHandler.java:218)
at com.sun.javafx.event.CompositeEventHandler.dispatc hBubblingEvent(CompositeEventHandler.java:80)
at com.sun.javafx.event.EventHandlerManager.dispatchB ubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchB ubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.disp atchBubblingEvent(CompositeEventDispatcher.java:59 )
at com.sun.javafx.event.BasicEventDispatcher.dispatch Event(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispat chEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatch Event(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispat chEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatch Event(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispat chEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(Event Util.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil .java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$KeyHandler.process(Scene.java:3 964)
at javafx.scene.Scene$KeyHandler.access$1800(Scene.ja va:3910)
at javafx.scene.Scene.impl_processKeyEvent(Scene.java :2040)
at javafx.scene.Scene$ScenePeerListener.keyEvent(Scen e.java:2501)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$Ke yEventNotification.run(GlassViewEventHandler.java: 197)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$Ke yEventNotification.run(GlassViewEventHandler.java: 147)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.la mbda$handleKeyEvent$353(GlassViewEventHandler.java :228)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithou tRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.ha ndleKeyEvent(GlassViewEventHandler.java:227)
at com.sun.glass.ui.View.handleKeyEvent(View.java:546 )
at com.sun.glass.ui.View.notifyKey(View.java:966)
at com.sun.glass.ui.win.WinApplication._runLoop(Nativ e Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$14 8(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)

vahid-p
یک شنبه 19 اردیبهشت 1395, 16:57 عصر
خب بازم برای من اررور نمیده. البته فکر میکنم به خاطر نسخه jdk تون هست. من با jdk 1.8.0_31 کامپایل کردم و ارروری نمیده
اما شما با jdk1.8.0_73 و این خطا رو گرفتید. با سرچ در اینترنت هم خطاهای مشابه شما همگی نسخه های بالای jdk1.8.0_45 بود.

البته در این لینک (https://bugs.openjdk.java.net/browse/JDK-8081700) به عنوان باگ گزارش کردن که در جواب بهشون گفتن این باگ نیست:
This is not a bug. The test case attempts to modify the text property inside the change handler. This is not supported, and the property event handlers are not re-entrant.

در change handler نباید در محتوای TextField تغییر ایجاد کنید، چون این تغییر باعث فراخوانی دو مرتبه این هندلر میشه. و چنین چیزی شاید باعث اون خطای شما شده باشه. هر چند چون با اولین تغییر شما متن رو ریپلیس میکنید و دفعه دوم تغییری نداره ما متوجه دوبار اجرا شدنش نمیشیم. این نمیتونه مشکل بزرگی باشه، اما گویا در نسخه های بعدی متد ها تغییراتی داشته که باعث بروز این خطا میشه. از اونجایی که شما نباید در Change Handler تغییر ایجاد کنید، پس این مشکل باگ به حساب نمیاد، بلکه منطق برنامه مشکل داره.
طبق Trace ای که گذاشتید متد replaceText فراخوانی میشه. در نسخه jdk من در کلاس TextInputControl متدی به اسم updateContent وجود نداره در صورتی که در trace شما وجود داره. پس نشون میده تغییراتی در این قسمت ایجاد شده. این متد replaceText من که فراخوانی میشه.


public void replaceText(int start, int end, String text) {
if (start > end) {
throw new IllegalArgumentException();
}

if (text == null) {
throw new NullPointerException();
}

if (start < 0
|| end > getLength()) {
throw new IndexOutOfBoundsException();
}

if (!this.text.isBound()) {
getContent().delete(start, end, text.isEmpty());
getContent().insert(start, text, true);

start += text.length();
selectRange(start, start);
}
}

البته شما میتونید در خطوط زیر در source کتابخونه java 8 تون breakpoint بذارید و debug کنید ببینید دقیقا چرا در getText مقدار start>end است.

at javafx.scene.control.TextInputControl.getText(Text InputControl.java:446)
at javafx.scene.control.TextInputControl.updateConten t(TextInputControl.java:564)
at javafx.scene.control.TextInputControl.replaceText( TextInputControl.java:548)
at javafx.scene.control.TextInputControl.deleteText(T extInputControl.java:496)
at javafx.scene.control.TextInputControl.deletePrevio usChar(TextInputControl.java:899)

چون محل بروز این اکسپشن (خطا) این قسمته:


public String getText(int start, int end) {
// TODO these checks really belong in Content
if (start > end) {
throw new IllegalArgumentException("The start must be <= the end");
}
...

abarkarbar
یک شنبه 19 اردیبهشت 1395, 17:27 عصر
از جزئیات کافی که ارائه کردید تشکر میکنم، منم قبلاً فکر می کردم به این صورت که مقدار تکست باکس در داخل خود هندلر آن مقداردهی بشه از نظر منطق برنامه نویسی زیاد درست به نظر نمیاد ولی چاره ای نداشتم مجبوری برای نتیجه اینجوری نوشتم. شما راه حل دیگری ندارید برای این کار؟ برای برنامه ای که در مورد حساب داری هست و وارد کردن عدد فقط یک مبلغ است، جداسازی سه تایی و افزودن خودکار (،) خیلی قشنگ تر به نظر می رسه تا اینکه ساده عدد مثل 12345 وارد و نمایش داده بشه.

vahid-p
یک شنبه 19 اردیبهشت 1395, 17:55 عصر
البته منطق برنامتون مشکلات دیگه ای هم داره. مثلا من کلید های متوالی 123456 رو که وارد میکنم به دلیل ورود "," در رشته و تغییر نکردن مکان ورود عدد به صورت 123,564 میشه.

در نتیجه این روش درستی نیست حالا یا باید با keyTyped لیسنرها این کار رو انجام بدید یا در آپدیت 40 به بعد ورژن 8 کلاسی اضافه شده به اسم TextFormatter و متدی هم به TextField (همون TextInputControl) اضافه شده به اسم setTextFormatter و این شرطها رو میتونید روش اعمال کنید.

تو این لینک میتونید نحوه استفاده از این کلاس رو بخونید: http://www.javaworld.com/article/2991463/learn-java/javafx-improvements-in-java-se-8u40.html?page=4

امتحان کنید به مشکل برخوردید، کدتون رو بذارید

abarkarbar
دوشنبه 20 اردیبهشت 1395, 03:23 صبح
البته منطق برنامتون مشکلات دیگه ای هم داره. مثلا من کلید های متوالی 123456 رو که وارد میکنم به دلیل ورود "," در رشته و تغییر نکردن مکان ورود عدد به صورت 123,564 میشه.

در نتیجه این روش درستی نیست حالا یا باید با keyTyped لیسنرها این کار رو انجام بدید یا در آپدیت 40 به بعد ورژن 8 کلاسی اضافه شده به اسم TextFormatter و متدی هم به TextField (همون TextInputControl) اضافه شده به اسم setTextFormatter و این شرطها رو میتونید روش اعمال کنید.

تو این لینک میتونید نحوه استفاده از این کلاس رو بخونید: http://www.javaworld.com/article/2991463/learn-java/javafx-improvements-in-java-se-8u40.html?page=4

امتحان کنید به مشکل برخوردید، کدتون رو بذارید

جالبه برای من این مشکل رو نداره همانطور که تصویرشو گذاشتم برای ورود اعداد درست کار می کنه فقط موقع حذف خطا میده

vahid-p
دوشنبه 20 اردیبهشت 1395, 18:27 عصر
جالبه برای من این مشکل رو نداره همانطور که تصویرشو گذاشتم برای ورود اعداد درست کار می کنه فقط موقع حذف خطا میده
درسته JDK ام رو به نسخه 1.8.0_92 آپدیت کردم این مشکل رو نداشت.

vahid-p
سه شنبه 21 اردیبهشت 1395, 05:10 صبح
کلا به خاطر تغییرات یک textfield در listener ها باعث میشه مقادیر یک textfield در چند لحظه متفاوت باشه. همین باعث خیلی از مشکلات میشه. در نتیجه شما قبل از اینکه مقدار textfield آپدیت بشه باید یک مقدار معتبر براش در نظر بگیری و با اون مقدار آپدیت کنی. من راه های مختلفی رو امتحان کردم با listener ها و تقریبا جواب گرفتم اما باز مشکلات ریزی داشت. پس چاره ای جز تعریف یک ساب کلاس برای TextField نداریم. اینجا میتونیم متدهاشو override کنیم و به متدهای private اش دسترسی داشته باشیم.

کلاسی که برامون اینکار رو انجام بده در لینک رو برو پیدا کردم: https://community.oracle.com/thread/2487619?tstart=0
خودش از ورود هر چیزی غیر عدد و "." جلوگیری میکنه و اعداد اعشاری و صحیح رو همونطور که گفتید هندل میکنه.
البته بعضی ویژگی ها رو نداره که به نظرم اگر بهش اضافه بشه بهتر میشه:
1- صفر قبل عدد رو حذف کنه. مگر فقط یک صفر قبل اعشار باشه
2- اجازه ورود چند "." رو نده.
3- ورودی مثل 01. رو به 0.01 تبدیل کنه
که میشه رو همین کلاس کار کرد و این ویژگی ها رو بهش اضافه کرد

اما کد کلاس FormattedDoubleTextField :

public class FormattedDoubleTextField extends TextField {
@Override
public void replaceText(int start, int end, String text) {
// Really crude attempt at parsing. Probably better ways to do this.


// Mock up the result of inserting the text "as is"
StringBuilder mockupText = new StringBuilder(getText());
mockupText.replace(start, end, text);


// Strip the commas out, they will need to move anyway
int commasRemovedBeforeInsert = 0;
for (int commaIndex = mockupText.lastIndexOf(","); commaIndex >= 0; commaIndex = mockupText
.lastIndexOf(",")) {
mockupText.replace(commaIndex, commaIndex + 1, "");
if (commaIndex < start) {
commasRemovedBeforeInsert++;
}
}


// Check if the inserted text is ok (still forms a number)
boolean ok = true;
int decimalPointCount = 0;
for (int i = 0; i < mockupText.length() && ok; i++) {
char c = mockupText.charAt(i);
if (c == '-') {
ok = i == 0;
} else if (c == '.') {
ok = decimalPointCount == 0;
} else {
ok = Character.isDigit(c);
}
}


// if it's ok, insert the commas in the correct place, update the text,
// and position the carat:
if (ok) {
int commasInsertedBeforeInsert = 0;
int startNonFractional = 0;
if (mockupText.length() > 0 && mockupText.charAt(0) == '-') {
startNonFractional = 1;
}
int endNonFractional = mockupText.indexOf(".");
if (endNonFractional == -1) {
endNonFractional = mockupText.length();
}
for (int commaInsertIndex = endNonFractional - 3; commaInsertIndex > startNonFractional; commaInsertIndex -= 3) {
mockupText.insert(commaInsertIndex, ",");
if (commaInsertIndex < start - commasRemovedBeforeInsert
+ text.length()) {
commasInsertedBeforeInsert++;
}
}


final int caratPos = start - commasRemovedBeforeInsert
+ commasInsertedBeforeInsert + text.length();


// System.out.printf("Original text: %s. Replaced text: %s. start: %d. end: %d. commasInsertedBeforeInsert: %d. commasRemovedBeforeInsert: %d. caratPos: %d.%n",
// getText(), mockupText, start, end, commasInsertedBeforeInsert,
// commasRemovedBeforeInsert, caratPos);


// update the text:
this.setText(mockupText.toString());


// move the carat:
// Needs to be scheduled to the fx application thread after the current
// event has finished processing to override
// default behavior
// This seems like a bit of a hack...
Platform.runLater(new Runnable() {
@Override
public void run() {
positionCaret(caratPos);
}
});
}
}


@Override
public void replaceText(IndexRange range, String text) {
this.replaceText(range.getStart(), range.getEnd(), text);
}


@Override
public void insertText(int index, String text) {
this.replaceText(index, index, text);
}


@Override
public void deleteText(int start, int end) {


// special case where user deletes a comma:
if (start >= 1 && end - start == 1 && getText().charAt(start) == ',') {
// move cursor back
this.selectRange(getAnchor() - 1, getAnchor() - 1);
} else {
this.replaceText(start, end, "");
}
}


@Override
public void deleteText(IndexRange range) {
this.deleteText(range.getStart(), range.getEnd());
}


@Override
public void replaceSelection(String replacement) {
this.replaceText(getSelection(), replacement);
}
}

vahid-p
سه شنبه 21 اردیبهشت 1395, 18:15 عصر
این کلاس رو یه خورده دستکاری کردم و اون سه ویژگی رو داره.

به نظرم همه چی درسته. خودتم تست کن:
لطفا اگر به نظرت جواب سوالت رو گرفتی، انتهای عنوان تاپیک "[حل شد]" اضافه کن.

موفق باشید

FormattedDoubleTextField.java :



import javafx.application.Platform;
import javafx.scene.control.IndexRange;
import javafx.scene.control.TextField;


public class FormattedDoubleTextField extends TextField {


@Override
public void replaceText(int start, int end, String text) {
// Really crude attempt at parsing. Probably better ways to do this.


// Mock up the result of inserting the text "as is"
StringBuilder mockupText = new StringBuilder(getText());
mockupText.replace(start, end, text);


// Strip the commas out, they will need to move anyway
int commasRemovedBeforeInsert = 0;
for (int commaIndex = mockupText.lastIndexOf(","); commaIndex >= 0; commaIndex = mockupText
.lastIndexOf(",")) {
mockupText.replace(commaIndex, commaIndex + 1, "");
if (commaIndex < start) {
commasRemovedBeforeInsert++;
}
}


// Check if the inserted text is ok (still forms a number)
boolean ok = true;
int decimalPointCount = 0;
for (int i = 0; i < mockupText.length() && ok; i++) {
char c = mockupText.charAt(i);
if (c == '-') {
ok = i == 0;
} else if (c == '.') {
ok = decimalPointCount == 0;
decimalPointCount = 1; // Prevent adding multiple dot (point)
} else {
ok = Character.isDigit(c);
}
}


// if it's ok, insert the commas in the correct place, update the text,
// and position the carat:
if (ok) {
//
int commasInsertedBeforeInsert = 0;
int startNonFractional = 0;
if (mockupText.length() > 0 && mockupText.charAt(0) == '-') {
startNonFractional = 1;
}
int endNonFractional = mockupText.indexOf(".");
if (endNonFractional == -1) {
endNonFractional = mockupText.length();
}
for (int commaInsertIndex = endNonFractional - 3; commaInsertIndex > startNonFractional; commaInsertIndex -= 3) {
mockupText.insert(commaInsertIndex, ",");
if (commaInsertIndex < start - commasRemovedBeforeInsert
+ text.length()) {
commasInsertedBeforeInsert++;
}
}
/***************Start of changes*****************
* Prevent zeros before number
* Format .xxx to 0.xxx
*/
int firstZeroDeleted = 0;
int pointPos = mockupText.toString().indexOf('.');
if (pointPos == 0) {
mockupText.replace(0, 1, "0.");
firstZeroDeleted--;
} else {
int i = 0;
for (i = 0; i < mockupText.length() - 1 && (pointPos == -1 || i < pointPos - 1); i++) {
if (mockupText.charAt(i) != '0' && mockupText.charAt(i) != ',') {
firstZeroDeleted += i;
break;
}
}
mockupText.replace(0, i, "");
}

final int caratPos = start - commasRemovedBeforeInsert
+ commasInsertedBeforeInsert + text.length() - firstZeroDeleted;
/***************End of changes*****************/
// System.out.printf("Original text: %s. Replaced text: %s. start: %d. end: %d. commasInsertedBeforeInsert: %d. commasRemovedBeforeInsert: %d. caratPos: %d.%n",
// getText(), mockupText, start, end, commasInsertedBeforeInsert,
// commasRemovedBeforeInsert, caratPos);
// update the text:
this.setText(mockupText.toString());


// move the carat:
// Needs to be scheduled to the fx application thread after the current
// event has finished processing to override
// default behavior
// This seems like a bit of a hack...
Platform.runLater(new Runnable() {
@Override
public void run() {
positionCaret(caratPos);
}
});
}
}


@Override
public void replaceText(IndexRange range, String text) {
this.replaceText(range.getStart(), range.getEnd(), text);
}


@Override
public void insertText(int index, String text) {
this.replaceText(index, index, text);
}


@Override
public void deleteText(int start, int end) {


// special case where user deletes a comma:
if (start >= 1 && end - start == 1 && getText().charAt(start) == ',') {
// move cursor back
this.selectRange(getAnchor() - 1, getAnchor() - 1);
} else {
this.replaceText(start, end, "");
}
}


@Override
public void deleteText(IndexRange range) {
this.deleteText(range.getStart(), range.getEnd());
}


@Override
public void replaceSelection(String replacement) {
this.replaceText(getSelection(), replacement);
}
}

abarkarbar
چهارشنبه 22 اردیبهشت 1395, 18:47 عصر
این کلاس رو یه خورده دستکاری کردم و اون سه ویژگی رو داره.

به نظرم همه چی درسته. خودتم تست کن:
لطفا اگر به نظرت جواب سوالت رو گرفتی، انتهای عنوان تاپیک "[حل شد]" اضافه کن.

موفق باشید

FormattedDoubleTextField.java :


سلام از اینکه روی این کد کار کردید و ارائه کردید ممنونم فقط من آن کلاس را در برنامه ایجاد کردم حالا چجوری باید استفاده بکنم؟ در داخل لیسنر تکست باکس باید عضوی بسازم؟

vahid-p
چهارشنبه 22 اردیبهشت 1395, 19:02 عصر
نه نیاز به هیچ listener ای نیست. فقط کافیه فایل fxml تون رو تغییر بدید:
به جای

<TextField fx:id="txt_value" layoutX="78.0" layoutY="84.0" prefHeight="33.0" prefWidth="165.0" />
بنویسید

<javafxapplication53.FormattedDoubleTextField fx:id="txt_value" layoutX="78.0" layoutY="84.0" prefHeight="33.0" prefWidth="165.0" />

یعنی شما به جای TextField پیشفرض JavaFX از TextField خودتون استفاده می کنید.
همچنین در کلاس FXMLDocumentController در متد initialize اون لیسنر رو حذف کنید. نیازی به هندل کردن event ها نداره

abarkarbar
چهارشنبه 22 اردیبهشت 1395, 21:42 عصر
نه نیاز به هیچ listener ای نیست. فقط کافیه فایل fxml تون رو تغییر بدید:
به جای

<TextField fx:id="txt_value" layoutX="78.0" layoutY="84.0" prefHeight="33.0" prefWidth="165.0" />
بنویسید

<javafxapplication53.FormattedDoubleTextField fx:id="txt_value" layoutX="78.0" layoutY="84.0" prefHeight="33.0" prefWidth="165.0" />

یعنی شما به جای TextField پیشفرض JavaFX از TextField خودتون استفاده می کنید.
همچنین در کلاس FormattedDoubleTextField در متد initialize اون لیسنر رو حذف کنید. نیازی به هندل کردن event ها نداره

آقا دمت گرم، تشکر به خوبی کار می کنه و مشکلات قبلی رو نداره.

[حل شده]

abarkarbar
چهارشنبه 29 اردیبهشت 1395, 12:05 عصر
نه نیاز به هیچ listener ای نیست. فقط کافیه فایل fxml تون رو تغییر بدید:
به جای

<TextField fx:id="txt_value" layoutX="78.0" layoutY="84.0" prefHeight="33.0" prefWidth="165.0" />
بنویسید

<javafxapplication53.FormattedDoubleTextField fx:id="txt_value" layoutX="78.0" layoutY="84.0" prefHeight="33.0" prefWidth="165.0" />

یعنی شما به جای TextField پیشفرض JavaFX از TextField خودتون استفاده می کنید.
همچنین در کلاس FXMLDocumentController در متد initialize اون لیسنر رو حذف کنید. نیازی به هندل کردن event ها نداره

سلام، بنده همه انواع ورودی های ممکن برای این تکست باکس را امتحان کردم که مشکلی نداشت فقط برای فیلد دارای ورودی های عدد منفی مشکل کوچکی هست که بعد از وارد کردن - (منفی) می توان هر تعداد صفر را وارد کرد. به صورت: -000000 ... که باید بعده منفی فقط یک صفر قبول کنه. آیا می تونید برای این منظور کد را اصلاح کنید؟ در واقع در قسمت:

// Check if the inserted text is ok (still forms a number) boolean ok = true;

int decimalPointCount = 0;

for (int i = 0; i < mockupText.length() && ok; i++) {

char c = mockupText.charAt(i);

if (c == '-') {

ok = i == 0;

} else if (c == '.') {

ok = decimalPointCount == 0;

decimalPointCount = 1; // Prevent adding multiple dot (point)

} else {

ok = Character.isDigit(c);

}

}


بنده تغییراتی دادم ولی جواب نگرفتم.

vahid-p
جمعه 31 اردیبهشت 1395, 05:20 صبح
قسمت ویرایش شده قبلی که با Start of Changes و End of Changes مشخص شده (خط 66 تا 88) رو حذف و کد زیر رو جایگزین کنید:
یکسری ایرادات کد قبل هم بر طرف شده و امیدوارم کد زیر کامل باشه.
/** * *************Start of changes***************** Prevent zeros
* before number Format .xxx to 0.xxx
*/
boolean minus = false;
if (mockupText.length() > 0 && mockupText.charAt(0) == '-') {
minus = true;
mockupText.deleteCharAt(0);
}
int firstZeroDeleted = 0;
int pointPos = mockupText.toString().indexOf('.');
if (pointPos == 0) {
mockupText.replace(0, 1, "0.");
firstZeroDeleted--;
} else {
int i;
for (i = 0; i < mockupText.length() - 1 && (pointPos == -1 || i < pointPos - 1); i++) {
if (mockupText.charAt(i) != '0' && mockupText.charAt(i) != ',') {
break;
}
}
firstZeroDeleted += i;
mockupText.replace(0, i, "");
}
if (minus) {
mockupText.insert(0, '-');
}
int tempCarat=start - commasRemovedBeforeInsert
+ commasInsertedBeforeInsert + text.length() - firstZeroDeleted;
if(minus && tempCarat<=0){
tempCarat=1;
}
final int caratPos = tempCarat;


/**
* *************End of changes****************
*/