Лучший выбор: TextLayout или JTextComponent для эллипса с редактируемым текстовым компонентом?

Если вы когда-либо использовали Visio или редактор диаграмм классов UML, вы понимаете, чего я пытаюсь добиться: в JFrame пользователи могут добавлять многоточия, окружающие небольшое редактируемое текстовое поле. Эти эллипсы можно перемещать внутри кадра, когда пользователь перетаскивает их. Щелчок по эллипсу приводит к тому, что текст становится редактируемым: появляется карат, возможно выделение подстроки и т. д.

У меня настроена базовая структура: «эллипс» — это автономный компонент с методами, вызываемыми для него из содержащего JFrame и его слушателей. Я пробовал два подхода:

  1. в методе draw() компонента используйте TextLayout, чтобы найти границы, расположить содержащийся текст внутри эллипса и нарисовать его во фрейме с помощью draw() TextLayout. Это быстро. Перетаскивание компонентов в JFrame, наведение мыши и щелчок мышью — все это просто. Однако для функциональности редактирования, похоже, мне нужно будет написать много пользовательского кода для обработки проверки попадания, позиционирования в каратах, выделения текста, переноса строк и т. д.

  2. наличие компонента, содержащего ссылку на содержащий JFrame, и добавление или изменение положения TextComponent в этом JFrame после рисования эллипса. Это имеет преимущество перед всем встроенным поведением TextComponent для редактирования и переноса строк. Но логистика действительно неаккуратна, и позиционирование TextComponent тоже становится беспорядочным, особенно когда пользователь перетаскивает компонент.

Я вполне возможно думаю об этом все неправильно. Может ли кто-нибудь предложить простой способ сделать это, на который я еще не наткнулся?


person Orolo    schedule 16.06.2011    source источник


Ответы (1)


Почему бы вам не объединить оба ваших подхода. Пока вы редактируете, отображайте текстовый компонент, в противном случае рисуйте весь текст с помощью TextLayout. В следующем примере кода показан такой подход, расширяющий простой JComponent. Он рисует прямоугольную форму с текстом внутри, и если щелкнуть внутри, появляется возможность редактирования. Как только вы снова щелкнете снаружи, компонент исчезнет. Обратите внимание, что в этом базовом примере отсутствуют все функции обработки редактирования.

class TestComponent extends JComponent {
    JTextArea jta = new JTextArea("12345");

    public TestComponent() {
        setPreferredSize(new Dimension(400, 400));
        setLayout(null);
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(final MouseEvent e) {
                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        if (e.getX() >= 40 && e.getX() <= 200 && e.getY() >= 40 && e.getY() <= 80) {
                            TestComponent.this.add(jta);
                            jta.setBounds(42, 42, 156, 36);
                        } else {
                            TestComponent.this.remove(jta);
                        }
                        repaint();
                    }
                });
            }
        });
    }

    @Override
    public void paintComponent(Graphics _g) {
        Graphics2D g = (Graphics2D) _g;
        g.drawRect(40, 40, 160, 40);
        TextLayout layout = new TextLayout("12345", g.getFont(), g.getFontRenderContext());
        layout.draw(g, 42, 42 + layout.getAscent());
    }
}
person Howard    schedule 16.06.2011
comment
Спасибо, Говард, я попробую этот подход! - person Orolo; 16.06.2011