2012-04-05 31 views
11

Tôi hiện đang làm việc trên cửa sổ bảng điều khiển trong Swing. Nó dựa trên một JTextArea và hoạt động giống như một dòng lệnh chung. Bạn gõ lệnh trong một dòng và nhấn Enter. Trong dòng tiếp theo, đầu ra được hiển thị và dưới đầu ra đó, bạn có thể viết lệnh tiếp theo.Làm cho các phần của JTextArea không thể chỉnh sửa (không phải toàn bộ JTextArea!)

Bây giờ tôi muốn, bạn chỉ có thể chỉnh sửa dòng hiện tại bằng lệnh của mình. Tất cả các dòng ở trên (lệnh và kết quả cũ) sẽ không thể chỉnh sửa được. Tôi có thể làm cái này như thế nào?

Trả lời

17

Bạn không cần phải tạo thành phần của riêng mình.

Điều này có thể được thực hiện (như tôi đã làm) bằng cách sử dụng tùy chỉnh DocumentFilter.

Bạn có thể tải tài liệu từ textPane.getDocument() và đặt bộ lọc trên đó bằng document.setFilter(). Trong bộ lọc, bạn có thể kiểm tra vị trí nhắc và chỉ cho phép sửa đổi nếu vị trí sau dấu nhắc.

Ví dụ:

private class Filter extends DocumentFilter { 
    public void insertString(final FilterBypass fb, final int offset, final String string, final AttributeSet attr) 
      throws BadLocationException { 
     if (offset >= promptPosition) { 
      super.insertString(fb, offset, string, attr); 
     } 
    } 

    public void remove(final FilterBypass fb, final int offset, final int length) throws BadLocationException { 
     if (offset >= promptPosition) { 
      super.remove(fb, offset, length); 
     } 
    } 

    public void replace(final FilterBypass fb, final int offset, final int length, final String text, final AttributeSet attrs) 
      throws BadLocationException { 
     if (offset >= promptPosition) { 
      super.replace(fb, offset, length, text, attrs); 
     } 
    } 
} 

Tuy nhiên, điều này ngăn cản bạn từ trình chèn nội dung vào đầu ra (noneditable) phần của nhà ga. Thay vào đó, những gì bạn có thể làm là cờ vượt qua trên bộ lọc mà bạn đặt khi bạn sắp thêm đầu ra hoặc (những gì tôi đã làm) đặt bộ lọc tài liệu thành null trước khi thêm đầu ra rồi đặt lại khi bạn ' làm lại.

+1

((AbstractDocument) jta.getDocument()). SetDocumentFilter (dfilter); –

0

AFAIK, bạn cần phải thực hiện kiểm soát của riêng bạn

Có lẽ bạn có thể mô phỏng nó với một danh sách các textfields (thậm chí kích hoạt và lẻ vô hiệu hóa) hoặc một kết hợp của textfields/nhãn

EDIT:

Tôi sẽ đặt cược cho một vùng văn bản không thể chỉnh sửa và một trường văn bản có thể chỉnh sửa. Nhập vào trường văn bản, nhấn enter, thêm "command" và xuất ra textarea

3
import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import javax.swing.text.*; 
public class OnlyEditCurrentLineTest { 
    public JComponent makeUI() { 
    JTextArea textArea = new JTextArea(8,0); 
    textArea.setText("> aaa\n> "); 
    ((AbstractDocument)textArea.getDocument()).setDocumentFilter(
     new NonEditableLineDocumentFilter()); 
    JPanel p = new JPanel(new BorderLayout()); 
    p.add(new JScrollPane(textArea), BorderLayout.NORTH); 
    return p; 
    } 
    public static void main(String[] args) { 
    EventQueue.invokeLater(new Runnable() { 
     @Override public void run() { createAndShowGUI(); } 
    }); 
    } 
    public static void createAndShowGUI() { 
    JFrame f = new JFrame(); 
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
    f.getContentPane().add(new OnlyEditCurrentLineTest().makeUI()); 
    f.setSize(320,240); 
    f.setLocationRelativeTo(null); 
    f.setVisible(true); 
    } 
} 
class NonEditableLineDocumentFilter extends DocumentFilter { 
    @Override public void insertString(
     DocumentFilter.FilterBypass fb, int offset, String string, 
     AttributeSet attr) throws BadLocationException { 
    if(string == null) { 
     return; 
    }else{ 
     replace(fb, offset, 0, string, attr); 
    } 
    } 
    @Override public void remove(
     DocumentFilter.FilterBypass fb, int offset, 
     int length) throws BadLocationException { 
    replace(fb, offset, length, "", null); 
    } 
    private static final String PROMPT = "> "; 
    @Override public void replace(
     DocumentFilter.FilterBypass fb, int offset, int length, 
     String text, AttributeSet attrs) throws BadLocationException { 
    Document doc = fb.getDocument(); 
    Element root = doc.getDefaultRootElement(); 
    int count = root.getElementCount(); 
    int index = root.getElementIndex(offset); 
    Element cur = root.getElement(index); 
    int promptPosition = cur.getStartOffset()+PROMPT.length(); 
    //As Reverend Gonzo says: 
    if(index==count-1 && offset-promptPosition>=0) { 
     if(text.equals("\n")) { 
     String cmd = doc.getText(promptPosition, offset-promptPosition); 
     if(cmd.isEmpty()) { 
      text = "\n"+PROMPT; 
     }else{ 
      text = "\n"+cmd+"\n xxxxxxxxxx\n" + PROMPT; 
     } 
     } 
     fb.replace(offset, length, text, attrs); 
    } 
    } 
} 
0

gì về điều đó, khi ">>" là sự khởi đầu của mỗi dòng trong dòng lệnh mà người dùng có thể nhập vào một lệnh:

textArea.addKeyListener(new KeyAdapter() { 

    public void keyPressed(KeyEvent event) { 

     int code = event.getKeyCode();   
     int caret = textArea.getCaretPosition(); 
     int last = textArea.getText().lastIndexOf(">> ") + 3; 

     if(caret <= last) { 

      if(code == KeyEvent.VK_BACK_SPACE) { 

       textArea.append(" "); 

       textArea.setCaretPosition(last + 1); 
      } 

      textArea.setCaretPosition(textArea.getText().length()); 
     } 
    } 
}); 
+1

-1 cho keyListener -far quá mức thấp để phục vụ yêu cầu an toàn – kleopatra

+2

+1 KeyListener là cách dễ nhất để thực hiện chức năng như vậy, không có vấn đề an toàn nào tôi đã sử dụng KeyListener từ nhiều năm nay. – ShadowDoom

0

Đây là implemitation của tôi về một diễn xuất lọc tài liệu như một giao diện điều khiển trong java. Tuy nhiên với một số sửa đổi để cho phép tôi có một "khu vực lệnh" và "khu vực đăng nhập", có nghĩa là kết quả từ các lệnh in trong khu vực nhật ký và lệnh in thực tế trong vùng lệnh. Khu vực đăng nhập chỉ là một khu vực Jtext khác không thể chỉnh sửa. Tôi thấy rằng nó rất hữu ích, vì vậy mabey ai đó cố gắng đạt được một cái gì đó tương tự như việc thực hiện này có thể tìm thấy một số gợi ý!

class NonEditableLineDocumentFilter extends DocumentFilter 
{ 
    private static final String PROMPT = "Command> "; 

    @Override 
    public void insertString(DocumentFilter.FilterBypass fb, int offset, String string,AttributeSet attr) throws BadLocationException 
    { 
     if(string == null) 
     { 
      return; 
     } 
     else 
     { 
      replace(fb, offset, 0, string, attr); 
     } 
    } 

    @Override 
    public void remove(DocumentFilter.FilterBypass fb, int offset,int length) throws BadLocationException 
    { 
     replace(fb, offset, length, "", null); 
    } 

    @Override 
    public void replace(DocumentFilter.FilterBypass fb, int offset, int length,String text, AttributeSet attrs) throws BadLocationException 
    {  
     Document doc = fb.getDocument(); 
     Element root = doc.getDefaultRootElement(); 
     int count = root.getElementCount(); 
     int index = root.getElementIndex(offset); 
     Element cur = root.getElement(index); 
     int promptPosition = cur.getStartOffset()+PROMPT.length(); 

     if(index==count-1 && offset-promptPosition>=0) 
     { 
      if(text.equals("\n")) 
      { 
       cmd = doc.getText(promptPosition, offset-promptPosition); 

       if(cmd.trim().isEmpty()) 
       { 
        text = "\n"+PROMPT; 
       } 
       else 
       { 
        text = "\n" + PROMPT; 
       } 
      } 
      fb.replace(offset, length, text, attrs); 
     } 
    } 
} 
Các vấn đề liên quan