Редактировать выбранный элемент в JComboBox - PullRequest
0 голосов
/ 12 июня 2019

Моя цель - создать список с длиной, контролируемой другим компонентом, где можно редактировать значение каждого элемента.

В моей попытке используется редактируемый JComboBox, содержащий определенное количество элементов. В моем коде ниже, однако, выбранный индекс продолжает меняться на -1, что не позволяет мне изменять элемент. Есть ли способ выбрать и отредактировать элемент, используя JComboBox?

//cb is a JComboBox with elements of type ComboItem. idx is defined elsewhere.
cb.addItemListener(new ItemListener() {
    @SuppressWarnings("unchecked")
    @Override
    public void itemStateChanged(ItemEvent e) {
        if(e.getStateChange() == ItemEvent.SELECTED)
            idx = ((JComboBox<ComboItem>) e.getSource()).getSelectedIndex();
        System.out.println("idx:"+idx);
    }
});
//Pressing enter should commit changes.
cb.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() {
    @Override
    public void keyReleased(KeyEvent e) {
        if(e.getKeyChar() == KeyEvent.VK_ENTER) {
            String parse = ((JTextComponent) cb.getEditor().getEditorComponent()).getText();
            parse = parse.substring(parse.lastIndexOf(":")+1).replaceAll("[^0-9]+", ""); //Processes edits.
            cb.getItemAt(idx).change("Layer "+idx, Integer.parseInt(parse)); //This method should change the
            System.out.println("selected item:"+cb.getSelectedItem());      // data for each item.
        }
    }
});
//Editing the text in the JComboBox and pressing the enter key should update the selected item.

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

1 Ответ

0 голосов
/ 13 июня 2019

После дня проб и ошибок я наконец-то нашел рабочее решение. Вместо использования JComboBox, который, вероятно, не предназначен для выполнения желаемой задачи, я создал JScrollPane, который добавляет дочерний элемент JPanel при каждом нажатии кнопки. Каждая панель имеет объект текстового поля, который можно настроить, и кнопку для его удаления. В моем случае я добавил DocumentFilter, который допускает положительные <5-значные целые числа. </p>

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

Панель прокрутки

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.JLabel;

@SuppressWarnings("serial")
public class TestScrollPane extends JPanel {

    private int w,h;
    private JPanel content;
    private JScrollPane scroll;
    private JButton add;
    private JLabel getTextLabel;
    private JButton getTextBtn;

    /**
     * Create the panel.
     */
    public TestScrollPane(int width, int height) {
        setLayout(null);

        w = width; h = height;

        scroll = new JScrollPane();
        scroll.setBounds(0, 0, w, h);
        scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        add(scroll);

        content = new JPanel();
        scroll.setViewportView(content);
        content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));

        add = new JButton("+");
        add.setBounds(0, h, 89, 23);
        add(add);

        getTextLabel = new JLabel("");
        getTextLabel.setBounds(10, 425, 215, 14);
        add(getTextLabel);

        getTextBtn = new JButton("Get Text");
        getTextBtn.setBounds(225, 425, 215, 14);
        getTextBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String a[] = getText(),
                       b = "";
                b += "[";
                for(int i = 0; i < a.length - 1; i++)
                    b += a[i]+", ";
                b += a[a.length-1]+"]";
                System.out.println(b);
                getTextLabel.setText(b);
            }
        });
        add(getTextBtn);

        add.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("adding "+content.getComponentCount());
                content.add(new ScrollItem(content.getComponentCount()));
                validate();
                repaint();
            }
        });
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(w, h);
    }

    public String[] getText() {
        String out[] = new String[content.getComponentCount()],s;
        for(int i = 0; i < out.length; i++)
            out[i] = (s = ((ScrollItem) content.getComponent(i)).out) == null ? "0" : s;
        return out;
    }

    private class ScrollItem extends JPanel {

        private JTextField text;
        private JButton del;
        private int idx;
        private String out;

        public ScrollItem(int id) {
            idx = id;
            setBounds(0, idx*20, w-5, 20);
            setLayout(null);
            text = new JTextField();
            text.setBounds(0, 0, (w-5)*3/4, 20);
            text.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    out = text.getText();
                }
            });

            AbstractDocument d = (AbstractDocument) text.getDocument();
            d.setDocumentFilter(new TextFilter(4));

            del = new JButton("X");
            del.setBounds((w-5)*3/4, 0, (w-5)/4, 20);
            del.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    content.remove(idx);
                    for(int i = idx; i < content.getComponentCount(); i++)
                        ((ScrollItem) content.getComponent(i)).moveUp();
                    content.validate();
                    content.repaint();
                    System.out.println("Removed "+idx);
                }
            });
            add(text);
            add(del);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(w-5, 20);
        }

        public void moveUp() {
            idx--;
            content.validate();
            content.repaint();
        }
    }

    private class TextFilter extends DocumentFilter {
        private int max;

        public TextFilter(int maxChars) {
            max = maxChars;
        }

        @Override
        public void insertString(FilterBypass fb, int offs, String str, AttributeSet a) throws BadLocationException {
            System.out.println("insert");
            if ((fb.getDocument().getLength() + str.length()) <= max && str.matches("\\d+"))
                super.insertString(fb, offs, str, a);
            else
                showError("Length: "+((fb.getDocument().getLength() + str.length()) <= max)+" | Text: "+str.matches("\\d+")+" | Str: "+str);
        }

        @Override
        public void replace(FilterBypass fb, int offs, int length, String str, AttributeSet a) throws BadLocationException {
            System.out.println("replace");
            if ((fb.getDocument().getLength() + str.length() - length) <= max && str.matches("\\d+"))
                super.replace(fb, offs, length, str, a);
            else
                showError("Length: "+((fb.getDocument().getLength() + str.length() - length) <= max)+" | Text: "+str.matches("\\d+")+" | Str: "+str);
        }

        private void showError(String cause) {
            JOptionPane.showMessageDialog(null, cause);
        }
    }
}

Тестовое окно

import java.awt.EventQueue;
import javax.swing.JFrame;

public class TestWindow {
    private JFrame frame;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    TestWindow window = new TestWindow();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public TestWindow() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 435, 500);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new TestScrollPane(430, 247));
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...