2015-07-02 32 views
11

W aplikacji Swing utworzyłem niestandardowy dokument, który był w stanie określić i ograniczyć liczbę wierszy w obszarze tekstowym, niezależnie od tego, czy linia była opakowana, czy został naciśnięty wiersz. Miałem nadzieję znaleźć coś podobnego w FX, ale nie byłem w stanie. Wszelkie sugestie dotyczące sposobu ograniczania liczby dozwolonych wierszy?JavaFX - Limit wierszy TextArea?

Edytuj: W ten sposób próbowałem dowiedzieć się, ile zawijanych wierszy znajduje się w obszarze TextArea. Największym problemem jest uzyskanie dokładnej szerokości, która przejdzie do setWrappingWidth, ponieważ wydaje się, że niektóre dopełnienie zawartości TextArea wraz z granicami.

Text helper = new Text(); 
helper.setText(text); 
helper.setFont(getFont()); 
helper.wrappingWidthProperty().bind(widthBinding); 
Font font = getFont(); 
FontMetrics fontMetrics = Toolkit.getToolkit().getFontLoader().getFontMetrics(font); 
int preferredHeight = new Double(helper.getLayoutBounds().getHeight()).intValue(); 
int lineHeight = new Double(fontMetrics.getMaxAscent() + fontMetrics.getMaxDescent()).intValue(); 
System.err.println("preferredHeight/lineHeight: " + preferredHeight/lineHeight); 
return preferredHeight/lineHeight; 
+0

nie '.setPrefRowCount (10);' pracę? z ustawieniem wrapText na true? również textarea respektuje jego obszar, więc stara się go wypełnić, chyba że ograniczysz go do maxsize lub czegoś takiego – Elltz

+0

Z tego co wiem setPrefRowCount i setPrefColCount uwzględniają tylko preferowany rozmiar TextArea i nie ograniczają zawartości. – Tommo

+0

To nie ma żadnego sensu. Nie możesz oczekiwać, że linie będą ograniczone, podczas gdy ty. sol. sprawiają, że tekst jest mniejszy. To koszmar użyteczności. Jaki jest tego pożytek? – Roland

Odpowiedz

6

Każdy TextInputControl dostał TextFormatter dla tego zadania, ponieważ Java 8 Update 40.

Posiada dwie funkcje, z których ten można wykorzystać do zadań:

filtr (getFilter()), który może przechwytywać i modyfikować dane wprowadzane przez użytkownika. Pomaga to zachować tekst w pożądanym formacie.

Jest bardzo prostych próba rozwiązania tego problemu:

public class Main extends Application { 
    @Override 
    public void start(Stage primaryStage) { 
     BorderPane root = new BorderPane(); 

     final TextArea textArea = new TextArea(); 
     textArea.setTextFormatter(createTextFormatter()); 
     root.setCenter(textArea); 

     primaryStage.setScene(new Scene(root, 400, 400)); 
     primaryStage.show(); 
    } 

    private static <T> TextFormatter<T> createTextFormatter() { 

     final IntegerProperty lines = new SimpleIntegerProperty(1); 

     return new TextFormatter<>(change -> { 
      if (change.isAdded()) { 
       if (change.getText().indexOf('\n') > -1) { 
        lines.set(lines.get() + 1); 
       } 
       if (lines.get() > 10) { 
        change.setText(""); 
       } 
      } 
      return change; 
     }); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 

ta skutecznie chroni użytkownika przed wejściem ponad 10 linii. Ale trzeba poprawić to rozwiązanie, na przykład do obsługi:

  • tekst został zastąpiony
  • tekst został skasowany

TextFormatter jest naprawdę mocny i powinien być w stanie obsługiwać to wszystko.

+0

Zajrzę do tego za kilka godzin. Uważam, że częścią trudną jest wyliczenie liczby linii z powodu zawijania tekstu w polu w przeciwieństwie do użytkownika naciskającego klawisz Enter. W tej chwili nie jestem w pobliżu mojego komputera, ale byłem blisko rozwiązania tego problemu za pomocą węzła Tekst. – Tommo

+0

@Tommo Ale teraz całkowicie zmieniłeś zakres swojego pytania z "Jak (które metody, pliki klas) mogę ograniczyć liczbę linii w TextField" do "Jak określić liczbę linii w TextField". – eckig

+0

Cóż, oni idą w parze, prawda? Ustalenie liczby linii jest prawie wymagane, ponieważ możliwe jest ograniczenie liczby linii. – Tommo

-2

Przypisana TextFormatter poprzez:

setTextFormatter(new TextFormatter<>(change -> { 
    if(change.isContentChange()) { 
    if(getWrappedLines(change.getControlText(), change.getControlNewText()) > maxRows) { 
     change.setText(""); 
    } 
    } 
    return change; 
})); 

i metoda getWrappedLines:

int getWrappedLines(String oldText, String newText) { 
    Text helper = (Text)lookup(".text"); 
    if(helper != null) { 
    helper.setText(newText); 
    FontMetrics fontMetrics = Toolkit.getToolkit().getFontLoader().getFontMetrics(getFont()); 
    int preferredHeight = new Double(helper.getLayoutBounds().getHeight()).intValue(); 
    int lineHeight = new Double(fontMetrics.getLineHeight()).intValue(); 
    // Initially a line's preferredHeight = 14, however each new line seems to increase the preferredHeight by 
    // 16 instead of 14. 
    preferredHeight = preferredHeight == lineHeight ? preferredHeight : preferredHeight - 2; 
    helper.setText(oldText); 
    return preferredHeight/lineHeight; 
    } 
    else { 
    return 0; 
    } 

}

+0

Jakieś powody głosowania w dół? – Tommo

+1

po prostu skopiować/wkleić razem z tej strony, bez badań, a nie rozwiązania. – eckig

+0

Sugerowanie TextFormatter było krokiem we właściwym kierunku, jednak metoda getWrappedLines była czymś, co napisałem pierwotnie. Połączenie dwóch rozwiązało problem. – Tommo