Позвольте JTextField изменить размер автоматически - PullRequest
0 голосов
/ 06 апреля 2019

Я хочу показать двумерный массив JTextFields для редактирования пользователем. После инициализации (с текстом) они появляются в хорошем размере. Когда Text является editet, они не меняют размер. Я помещаю их в JPanel с GridbagLayout внутри JSrolePane. Попытка изменить их размер «вручную», поэтому при получении события вызывается .setPrefferedSize, но трудно получить точную причину TextLength для различных letterSize. И все JTextFields отображаются в одной строке, поэтому я, вероятно, что-то не так с GridBagConstraints. (раньше использовал JTable, но не понравилось).

GridBagConstraints c = new GridBagConstraints();
    c.gridx = 0;
    c.gridy = 0;
    c.weighty = 0.1;
    c.weightx = 0.1;
    c.fill = GridBagConstraints.BOTH;
    for(int row=0; row<initText.length; row++) {
        for(int col=0; col<initText[row].length; col++) {
            jTextFields[row][col] = new JTextField(initText[row][col]);
            jTextFields[row][col].getDocument().addDocumentListener(new DocumentListener() {
                @Override
                public void removeUpdate(DocumentEvent arg0) {
                }
                @Override
                public void insertUpdate(DocumentEvent dE) {
                    int row = -1;
                    int col = -1;
                    for(int i=0; i<jTextFields.length; i++) {
                        for(int ii=0; ii<jTextFields[i].length; ii++) {
                            if(jTextFields[i][ii].getDocument()==dE.getDocument()) {
                                row=i;
                                col=ii;
                                break;
                            }
                        }
                        if(col!=-1) {
                            break;
                        }
                    }
                    //Tried it so to make resize "by Hand" but initalisation size is better
                    jTextFields[row][col].setPreferredSize(new Dimension(jTextFields[row][col].getText().length()*jTextFields[row][col].getPreferredSize().height, jTextFields[row][col].getPreferredSize().height));
                    System.out.println("insertUpdate in cell "+row+" "+col);
                    Main.gui.frame.repaint();
                }
                @Override
                public void changedUpdate(DocumentEvent arg0) {
                    // TODO Auto-generated method stub
                }
            });
            c.gridx = col;
            c.gridy = row;
            innerContentPane.add(jTextFields[row][col], c);
        }
    }
    contentPane = new JScrollPane(innerContentPane);
    frame.repaint();

1 Ответ

1 голос
/ 06 апреля 2019

Вы не хотите продолжать сбрасывать предпочтительный размер компонента. Пусть каждый компонент определяет свой предпочтительный размер.

Вместо этого вы хотите вызвать менеджер макетов, чтобы можно было пересчитать размер каждого компонента и настроить макет панели. Простой способ сделать это - revalidate() панель с текстовыми полями.

Я не большой поклонник нескольких уровней зацикливания кода с несколькими уровнями зацикливания кода. Вы можете упростить свой код, создав общий DocumentListener для общего доступа ко всем документам.

Кроме того, ваш код обрабатывает только тот случай, когда добавляется текст. Что делать, если текст удален, не должно ли текстовое поле уменьшиться в размере?

Применяя все вышеперечисленные предложения, логика будет выглядеть примерно так:

//  Create shared DocumentListener

DocumentListener dl = new DocumentListener()
{
    @Override
    public void removeUpdate(DocumentEvent de)
    {
        resizeTextField(de);
    }

    @Override
    public void insertUpdate(DocumentEvent de)
    {
        resizeTextField(de);
    }

    @Override
    public void changedUpdate(DocumentEvent de) {}

    private void resizeTextField(DocumentEvent de)
    {
        innerContentPane.revalidate();
    }
};

GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
//c.weighty = 0.1;
//c.weightx = 0.1;
//c.fill = GridBagConstraints.BOTH;

//  Create text fields and add listener to the Document

for(int row = 0; row < 3; row++)
{
    for(int col = 0; col <3; col++)
    {
            JTextField textField = new JTextField("0");
            textFields[row][col] = textField;
            textField.getDocument().addDocumentListener(dl);
            c.gridx = col;
            c.gridy = row;
            innerContentPane.add(textField, c);
    }
}

Обратите внимание, что DocumentListener также должен быть создан как внутренний класс, чтобы сделать код еще чище.

И все JTextFields отображаются в одной строке, так что я, вероятно, что-то не так с GridBagConstraints

Менеджер макетов по умолчанию для JPanel - FlowLayout. Вам нужно установить макет на GridBagLayout, если вы хотите использовать это:

innerContentPane.setLayout( new GridBagLayout() );
GridBagConstraints c = new GridBagConstraints();

в противном случае GridBagConstraints ничего не значат для FlowLayout.

Для получения дополнительной информации прочитайте раздел из учебника по Swing на Layout Manager .

...