2011-12-29 27 views
16

Trong tất cả các phiên bản của Java lên đến 6, hành vi mặc định của một JTextPane đặt bên trong một JScrollPane là: bọc các đường ở ranh giới từ nếu có thể. Nếu không, sau đó quấn chúng.Quấn các từ dài trong JTextPane (Java 7)

Trong JDK 7, hành vi mặc định có vẻ là: các đường bao bọc ở các ranh giới từ nếu có thể. Nếu không, chỉ cần mở rộng chiều rộng của JTextPane (không bao giờ quấn các từ dài).

Nó rất dễ dàng để tái sản xuất này, đây là một SSCCE:


public class WrappingTest extends JFrame 
{ 

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

    public WrappingTest() 
    { 
     setSize(200,200); 
     getContentPane().setLayout(new BorderLayout()); 
     JTextPane jtp = new JTextPane(); 
     JScrollPane jsp = new JScrollPane(jtp); 
     jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); 
     getContentPane().add(jsp,BorderLayout.CENTER); 
     setVisible(true); 
    } 

} 

Chỉ cần chạy nó trong JDK 6 và trong JDK 7, viết một số từ nhỏ, và viết một từ lâu, và bạn sẽ thấy những Sự khác biệt.

Câu hỏi của tôi rất đơn giản ... hành vi mặc định mới trong JDK 7 hoàn toàn làm rối loạn chương trình của tôi (họ nên cẩn thận hơn với Oracle khi thay đổi kiểu mặc định này ... có vẻ không quan trọng nhưng khi bạn đang sử dụng một JTextPane để hiển thị dữ liệu thường chứa các chuỗi ký tự rất dài, chúng không quá quan trọng - trong thực tế tôi sẽ gửi một báo cáo lỗi, nhưng tôi muốn có một cách giải quyết trong khi/nếu chúng không giải quyết nó). Bất kỳ cách nào để quay trở lại hành vi trước đó?

Lưu ý rằng tôi đã kiểm tra câu trả lời cho câu hỏi liên quan How is word-wrapping implemented in JTextPane, and how do I make it wrap a string without spaces? nhưng không trả lời câu hỏi này - nó cung cấp cách tạo gói JTextPane mà không quan tâm đến khoảng trắng, nhưng đối với tôi, hành vi mong muốn được chia các dòng ở khoảng trống nếu có thể, và ở nơi khác nếu không thể (như trong các phiên bản Java trước).

+0

Không sử dụng [ 'invokeLater()'] (http://download.oracle.com/javase/tutorial/uiswing/concurrency/ initial.html) trợ giúp? –

+0

Không ... hiệu ứng tương tự. –

+0

Tôi có cùng một vấn đề. Liên quan: https://forums.oracle.com/forums/thread.jspa?threadID=2374090 (không có câu trả lời ...) Các poster đã tạo ra một báo cáo lỗi, nhưng nó đã được đóng lại là "không phải là một lỗi", mà không có một lời giải thích ... – PhiLho

Trả lời

1
+0

Cảm ơn, nó khá giống nhau ... nhưng tiếc là nó không có vẻ là lỗi tương tự (nó phải làm với bộ thuộc tính, và đã được cố định từ lâu):/ –

+0

Vâng, tôi nghĩ rằng nó có liên quan, mặc dù hành vi trong 1.6 đã không thay đổi. Nhìn nhận xét: "Cần lưu ý rằng hành vi phân chia mặc định được yêu cầu (phá vỡ GlyphView tại vị trí tùy ý khi BreakIterator không tìm thấy điểm ngắt hợp lệ) là sai lầm khủng khiếp và không được khôi phục trong bất kỳ bản phát hành JDK nào, trong tương lai hoặc quá khứ." Có vẻ như chúng ta cần phải làm nhiều việc hơn bây giờ ... – PhiLho

1

Hi Tôi đã có cùng một vấn đề nhưng không tìm thấy một công việc xung quanh:

chỉ cần tạo một lớp mở rộng của JTextPane ví dụ

 MyWrapJTextPane extends JTextPane 

và ghi đè lên các phương pháp sau đây - nó hoạt động ;-)

 public boolean getScrollableTracksViewportWidth() { 
      return true; 
     } 
+0

Xin lỗi: không có việc gì! điều này giải quyết vấn đề với các dòng dài (chứa khoảng trắng) - chúng được bọc ngay bây giờ - nhưng từ dài vẫn không được bọc :-( – Thomwiesel

2

Good catch từ @ dk89, nhưng than ôi cách giải quyết cho không làm việc: JDK 7 dường như vẫn không đưa ra một chờ đợi để thiết lập một BreakIterator tùy chỉnh trên một JTextComponent; thậm chí không phải trên một GlyphView, nơi mà thế hệ của BreakIterator là riêng tư. Và nếu chúng ta chèn chuỗi char bằng char, nó vẫn không hoạt động: Tôi cho rằng việc chạy liên tục của văn bản với kiểu giống nhau (AttributeSet) được thu gọn lại với nhau.

Tôi đã dành hai ngày cố gắng để làm một EditorKit tùy chỉnh, như được khuyên ở nơi khác, nhưng nó không hoạt động tốt (với JDK 1.7.0_4 ít nhất) như văn bản.

Tôi đã thử các giải pháp được đưa ra tại How to word wrap text stored in JTextPanes which are cells in a JList và một biến thể tìm thấy tại http://www.experts-exchange.com/Programming/Languages/Java/Q_20393892.html

Nhưng tôi phát hiện ra rằng breakView không còn được gọi khi JTextPane nhỏ hơn từ dài nhất trong câu. Vì vậy, nó không hoạt động chút nào khi chỉ có một từ (dài). Đó là trường hợp của chúng tôi, khi chúng tôi hiển thị các chuỗi giống như mã định danh do người dùng cung cấp, thường không có dấu cách, trong các không gian khá nhỏ.

Cuối cùng tôi đã tìm thấy một giải pháp đơn giản, bắt nguồn từ gợi ý trong báo cáo lỗi: thực sự, chèn chuỗi char bằng char, nhưng các kiểu thay thế! Vì vậy, chúng tôi có nhiều phân đoạn như chúng tôi có ký tự, và chuỗi được bọc tại giới hạn char. Cho đến khi "sửa lỗi" tiếp theo?

đoạn Code:

private JTextPane tp; 
private SimpleAttributeSet sas = new SimpleAttributeSet(); 

tp= new JTextPane(); 
sas.addAttribute("A", "C"); // Arbitrary attribute names and value, not used actually 

    // Set the global attributes (italics, etc.) 
    tp.setParagraphAttributes(styleParagraphAttributes, true); 

    Document doc = tp.getDocument(); 
    try 
    { 
     doc.remove(0, doc.getLength()); // Clear 
     for (int i = 0; i < textToDisplay.length(); i++) 
     { 
      doc.insertString(doc.getLength(), textToDisplay.substring(i, i+1), 
        // Change attribute every other char 
        i % 2 == 0 ? null : sas); 
     } 
    } 
    catch (BadLocationException ble) 
    { 
     log.warn("Cannot happen...", ble); 
    } 

Như đã nêu trong các lỗi, họ nên đã cung cấp một cách dễ dàng (một số tài sản có lẽ, hoặc một số công cụ tiêm) để trở lại các hành vi cũ.

11

Đối với tôi, công trình sửa chữa (thử nghiệm dưới 1.7.0_09)

import javax.swing.*; 
import javax.swing.text.*; 
import java.awt.*; 

public class WrapTestApp extends JFrame { 

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

    public WrapTestApp() { 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setSize(200,200); 
     getContentPane().setLayout(new BorderLayout()); 
     JTextPane jtp = new JTextPane(); 
     jtp.setEditorKit(new WrapEditorKit()); 
     JScrollPane jsp = new JScrollPane(jtp); 
     jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); 
     getContentPane().add(jsp, BorderLayout.CENTER); 
     jtp.setText("ExampleOfTheWrapLongWordWithoutSpaces"); 
     setVisible(true); 
    } 

    class WrapEditorKit extends StyledEditorKit { 
     ViewFactory defaultFactory=new WrapColumnFactory(); 
     public ViewFactory getViewFactory() { 
      return defaultFactory; 
     } 

    } 

    class WrapColumnFactory implements ViewFactory { 
     public View create(Element elem) { 
      String kind = elem.getName(); 
      if (kind != null) { 
       if (kind.equals(AbstractDocument.ContentElementName)) { 
        return new WrapLabelView(elem); 
       } else if (kind.equals(AbstractDocument.ParagraphElementName)) { 
        return new ParagraphView(elem); 
       } else if (kind.equals(AbstractDocument.SectionElementName)) { 
        return new BoxView(elem, View.Y_AXIS); 
       } else if (kind.equals(StyleConstants.ComponentElementName)) { 
        return new ComponentView(elem); 
       } else if (kind.equals(StyleConstants.IconElementName)) { 
        return new IconView(elem); 
       } 
      } 

      // default to text display 
      return new LabelView(elem); 
     } 
    } 

    class WrapLabelView extends LabelView { 
     public WrapLabelView(Element elem) { 
      super(elem); 
     } 

     public float getMinimumSpan(int axis) { 
      switch (axis) { 
       case View.X_AXIS: 
        return 0; 
       case View.Y_AXIS: 
        return super.getMinimumSpan(axis); 
       default: 
        throw new IllegalArgumentException("Invalid axis: " + axis); 
      } 
     } 

    } 
} 
+0

+1 cho Java7 :-), ViewFactory thú vị – mKorbel

+1

Thực tế tất cả chúng ta cần là để getMinimumSpan() của LabelView trả về 0 cho X_AXIS. ViewFactory là một cách để thay thế mặc định LabelView – StanislavL

+0

aaach tôi có thể nhìn thấy và nhận được nó, cảm ơn bạn, khá chính xác để làm việc cho 'jtp.setComponentOrientation (RTL);' quá – mKorbel

Các vấn đề liên quan