2013-04-30 61 views
4

在經歷Java swing時,我遇到了這個問題。 我有一個JTextField具有預定義的不可編輯的文本。用戶應該能夠附加其他文本但不編輯預定義的文本。是否有任何方法來獲得這個解決方案或其他?JTextField其中預定義文本不可編輯,但其他文本可以追加到其中?

+0

爲什麼不把一個標籤與文本字段前不可編輯的文本,如[這個答案]看到(http://stackoverflow.com/a/16271173/418556)? – 2013-04-30 08:03:17

+0

告訴我,如果只想使用JTextfield? – 2013-04-30 08:07:12

+0

是的,我只需要使用JTextField – sanjeeda 2013-04-30 08:11:33

回答

2

我有一個JTextField具有預定義的不可編輯的文本。 用戶應該能夠附加其他文本,但不需要編輯 預定義文本。是否有任何方法可以獲得此解決方案或其他任何方法?

使用

  1. JComboBox (non_editable)

  2. JSpinnerSpinnerListModel

最初由@camickr

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

public class NavigationFilterPrefixWithBackspace extends NavigationFilter { 

    private int prefixLength; 
    private Action deletePrevious; 

    public NavigationFilterPrefixWithBackspace(int prefixLength, JTextComponent component) { 
     this.prefixLength = prefixLength; 
     deletePrevious = component.getActionMap().get("delete-previous"); 
     component.getActionMap().put("delete-previous", new BackspaceAction()); 
     component.setCaretPosition(prefixLength); 
    } 

    @Override 
    public void setDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias) { 
     fb.setDot(Math.max(dot, prefixLength), bias); 
    } 

    @Override 
    public void moveDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias) { 
     fb.moveDot(Math.max(dot, prefixLength), bias); 
    } 

    class BackspaceAction extends AbstractAction { 

     private static final long serialVersionUID = 1L; 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      JTextComponent component = (JTextComponent) e.getSource(); 
      if (component.getCaretPosition() > prefixLength) { 
       deletePrevious.actionPerformed(null); 
      } 
     } 
    } 

    public static void main(String args[]) throws Exception { 
     JTextField textField = new JTextField(" $ ", 20); 
     textField.setNavigationFilter(new NavigationFilterPrefixWithBackspace(textField.getDocument().getLength(), textField)); 
     JFrame frame = new JFrame("Navigation Filter Example"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(textField); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 
} 
  • 我建議使用OverlayLayout(JLabel的超過JTextField中),在JTextField中改變插圖(輸入區域)進行的JLabel區域,否則在JTextField中任何格式使代碼和建議,在此線程相當無用,並與奇怪的輸出到Swing GUI

  • eg JTextField.setHorizontalAlignment(JTextField.RIGHT);


編輯

  • 把JLabel的&的JTextField到JPanel的,很簡單,無副作用內置FlowLayout中的JPanel的

  • 需要

  • 變化調用revalidate()和重繪()的情況下,JLabel的文本改變

enter image description here

import java.awt.BorderLayout; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JTextField; 
import javax.swing.SwingUtilities; 

public class NavigationFilterBias { 

    private JFrame frame = new JFrame("Navigation Filter Example"); 
    private JPanel panel = new JPanel(); 
    private JLabel label = new JLabel(" $ "); 
    private JTextField textField = new JTextField(); 

    public NavigationFilterBias() { 
     panel.setBorder(textField.getBorder()); 
     panel.setBackground(textField.getBackground()); 
     panel.setLayout(new BorderLayout()); 
     panel.add(label,BorderLayout.WEST); 
     textField.setBorder(null); 
     panel.add(textField,BorderLayout.CENTER); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(panel); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String args[]) throws Exception { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       NavigationFilterBias exam = new NavigationFilterBias(); 
      } 
     }); 
    } 
} 
+1

我無法使用JComboBox,因爲它嚴格需要使用JTextField,其中包含一些文本「$」,我希望用戶在不編輯/刪除美元符號的情況下輸入數字。 – sanjeeda 2013-04-30 08:06:49

+0

已經在NavigationFilter上找到了,是否知道,你是否使用過這個... – mKorbel 2013-04-30 08:11:46

-1

替代解決方案:
1.將$ symbole JTextField中
2.拆下美元symbole當JTextField中獲得焦點
3。讓用戶修改全文
4.當他做打字(see here)添加$ symbole回

但它會比較容易的方式來下一個加標籤的JTextField的

2

您可以簡單地用一個DocumentFilter

import java.awt.FlowLayout; 

import javax.swing.JFrame; 
import javax.swing.JTextField; 
import javax.swing.SwingUtilities; 
import javax.swing.text.AbstractDocument; 
import javax.swing.text.AttributeSet; 
import javax.swing.text.BadLocationException; 
import javax.swing.text.DocumentFilter; 

public class TestDocumentFilter { 

    private static final String TEXT_NOT_TO_TOUCH = "You can't touch this!"; 

    private void initUI() { 
     JFrame frame = new JFrame(TestDocumentFilter.class.getSimpleName()); 
     frame.setLayout(new FlowLayout()); 
     final JTextField textfield = new JTextField(50); 
     textfield.setText(TEXT_NOT_TO_TOUCH); 
     ((AbstractDocument) textfield.getDocument()).setDocumentFilter(new DocumentFilter() { 
      @Override 
      public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException { 
       if (offset < TEXT_NOT_TO_TOUCH.length()) { 
        return; 
       } 
       super.insertString(fb, offset, string, attr); 
      } 

      @Override 
      public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException { 
       if (offset < TEXT_NOT_TO_TOUCH.length()) { 
        length = Math.max(0, length - TEXT_NOT_TO_TOUCH.length()); 
        offset = TEXT_NOT_TO_TOUCH.length(); 
       } 
       super.replace(fb, offset, length, text, attrs); 
      } 

      @Override 
      public void remove(FilterBypass fb, int offset, int length) throws BadLocationException { 
       if (offset < TEXT_NOT_TO_TOUCH.length()) { 
        length = Math.max(0, length + offset - TEXT_NOT_TO_TOUCH.length()); 
        offset = TEXT_NOT_TO_TOUCH.length(); 
       } 
       if (length > 0) { 
        super.remove(fb, offset, length); 
       } 
      } 
     }); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.add(textfield); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new TestDocumentFilter().initUI(); 
      } 
     }); 
    } 

} 
+1

這真是太神奇了,對於Java來說,儘管代碼可能長達100行,但使用單詞'simply'確實很好。 – 2013-04-30 08:16:55

+0

驚人+ 1vote up – 2013-04-30 08:21:21

+0

其實,我正在編輯一個已經存在的代碼。因此,長時間插入代碼可能有點冒險。有沒有像使用方法或其他方法的簡單解決方案? – sanjeeda 2013-04-30 08:23:43

1

雖然我相信的DocumentFilter是合乎邏輯的和通用的解決方案,在這裏很短的解決方案。它只是使JTextField具有一個內部左邊距,其中寫入了固定文本。

public class PrefixTextField extends JTextField { 
    private String prefix; 
    private JLabel label; 

    public PrefixTextField(String prefix) { 
     this.prefix = prefix; 
     label = new JLabel(prefix + '\u00a0'); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     int w = SwingUtilities.computeStringWidth(
       getFontMetrics(getFont()), prefix); 
     setMargin(new Insets(3, 3 + w, 3, 3)); 
     super.paintComponent(g); 
     SwingUtilities.paintComponent(g, label, this.getParent(), 
       2 + 3, 0, getWidth(), getHeight()); 
    } 
} 
+0

調用'setMargin(new Insets(3,3 + w,3,3));'paintComponent'內'是非常危險的。你應該在繪畫機制之外調用它。 – 2013-04-30 09:47:52

相關問題