Перенос слов JLabel с тегом <html>внутри JScrollPane - удаление функциональности / логики горизонтальной полосы - PullRequest
2 голосов
/ 11 февраля 2020

Мое требование - сделать перенос слов (точно так же, как это делает JTextArea) с JLabel.

. Рассмотрим следующий код:

public class WrapTest extends JFrame {

    public WrapTest() {
        super("test");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        setLayout(new BorderLayout());

        JLabel label = new JLabel("Lorem <b>ipsum</b> dolor sit amet, consectetur adipiscing elit. "
                + "Aliquam non pellentesque enim. Donec nec nisl tortor."
                + " Curabitur rutrum molestie est eget varius. Nullam ut lacinia est."
                + " Phasellus hendrerit sollicitudin justo, vitae malesuada dolor vestibulum at."
                + " Integer pharetra purus sed ipsum pulvinar, et pretium odio volutpat. Donec vitae varius metus."
                + " Cras sagittis vulputate erat, at faucibus lectus faucibus id. Cras varius nunc eu felis tristique dapibus."
                + " Aenean enim eros, dapibus pellentesque nibh ut, efficitur malesuada sapien. Nullam imperdiet nunc velit,"
                + "sed laoreet massa mattis eget. Morbi id justo quis sapien aliquet bibendum sed at leo. In mi felis, consectetur"
                + " sed orci eget, tempus maximus turpis. Curabitur sed felis id nisl vehicula sollicitudin sed eget erat.Ut sagittis at nisi sed facilisis."
                + " Morbi vel felis ac diam molestie consequat. Sed nisl lectus, sollicitudin at neque in, "
                + "placerat aliquet nunc. Maecenas quis enim vitae nunc fermentum congue. Sed posuere quam a ultricies fringilla."
                + " Vivamus aliquam nunc lacus, vitae consectetur tortor consequat ut. Cras viverra mi sit amet magna auctor eleifend."
                + " Morbi in risus nisl. Praesent nunc dolor, lobortis nec ultricies aliquet, sollicitudin eu sapien. Fusce interdum ac leo non suscipit."
                + "Vivamus at viverra elit, ut vestibulum elit. Sed bibendum, lorem et ornare sagittis, erat nulla ultricies odio, quis iaculis lacus nisl "
                + "vel ligula. Sed iaculis elit eu felis consectetur dignissim. ");

        add(label, BorderLayout.CENTER);

        setLocationByPlatform(true);
        setSize(500, 200);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            new WrapTest().setVisible(true);
        });
    }
}

Текст уродлив и не удобочитаемый. Чтобы сделать его лучше и добавить перенос слов, давайте добавим тег <html>.

String wrap = "<html>";
label.setText(wrap + label.getText());

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

Теперь давайте попробуем добавить JScrollPane и метку внутри него:

String wrap = "<html>";
label.setText(wrap + label.getText());

JScrollPane sp = new JScrollPane(label);
add(sp, BorderLayout.CENTER);

У нас есть следующий результат:

preview2

Что снова делает текст нечитаемым. Использование sp.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); заставит полосу прокрутки исчезнуть, а текст останется горизонтально ориентированным.

Есть ли способ в этой ситуации удалить всю функциональность горизонтальной панели? Я хочу, чтобы ярлык можно было прокручивать вертикально с помощью функции переноса слов. Так же, как JTextArea, который ведет себя как:

textarea

Причина, по которой я настаиваю на использовании JLabel, заключается в простоте рендеринга тегов HTML .

Я пытался решить эту проблему путем изменения preferredSize и / или maximumSize компонентов, но у меня не было желаемого результата. Я также пытался использовать <body style='width:100%'> или Xpx, но у них есть и другие проблемы. Поскольку это имеет смысл, они не корректируются, когда размер кадра увеличивается.

Ответы [ 3 ]

1 голос
/ 12 февраля 2020

Я полагаю, что вы можете использовать JEditorPane или JTextArea, который вы можете отключить редактирование и использовать их в качестве контейнера для отображения текста с нужной переносом строк.

Но если вы настаиваете на использовании строки -пакетирование JLabel и поддержка вертикальной прокрутки. Я считаю, что вам нужно рассчитать размер прокручиваемого контейнера области просмотра, когда пользователь изменяет размер фрейма:

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

public class WrappedLabel implements Runnable {

    public static void main( String[] args ){
        SwingUtilities.invokeLater( new WrappedLabel() );
    }

    @Override
    public void run(){
        final JPanel panel = new JPanel( new BorderLayout() );

        String text = "Lorem <b>ipsum</b> dolor sit amet, consectetur adipiscing elit. "
                + "Aliquam non pellentesque enim. Donec nec nisl tortor."
                + " Curabitur rutrum molestie est eget varius. Nullam ut lacinia est."
                + " Phasellus hendrerit sollicitudin justo, vitae malesuada dolor vestibulum at."
                + " Integer pharetra purus sed ipsum pulvinar, et pretium odio volutpat. Donec vitae varius metus."
                + " Cras sagittis vulputate erat, at faucibus lectus faucibus id. Cras varius nunc eu felis tristique dapibus."
                + " Aenean enim eros, dapibus pellentesque nibh ut, efficitur malesuada sapien. Nullam imperdiet nunc velit,"
                + "sed laoreet massa mattis eget. Morbi id justo quis sapien aliquet bibendum sed at leo. In mi felis, consectetur"
                + " sed orci eget, tempus maximus turpis. Curabitur sed felis id nisl vehicula sollicitudin sed eget erat.Ut sagittis at nisi sed facilisis."
                + " Morbi vel felis ac diam molestie consequat. Sed nisl lectus, sollicitudin at neque in, "
                + "placerat aliquet nunc. Maecenas quis enim vitae nunc fermentum congue. Sed posuere quam a ultricies fringilla."
                + " Vivamus aliquam nunc lacus, vitae consectetur tortor consequat ut. Cras viverra mi sit amet magna auctor eleifend."
                + " Morbi in risus nisl. Praesent nunc dolor, lobortis nec ultricies aliquet, sollicitudin eu sapien. Fusce interdum ac leo non suscipit."
                + "Vivamus at viverra elit, ut vestibulum elit. Sed bibendum, lorem et ornare sagittis, erat nulla ultricies odio, quis iaculis lacus nisl "
                + "vel ligula. Sed iaculis elit eu felis consectetur dignissim. ";
        JLabel label = new JLabel("<html>" +text+ "</html>");
        panel.add( label, BorderLayout.CENTER );

        final JFrame frame = new JFrame();
        frame.add( new WrappingScrollPane( panel ) );
        frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
        frame.setSize( 256, 256 );
        frame.setVisible( true );
    }
}

class WrappingScrollPane extends JScrollPane implements ComponentListener {

    WrappingScrollPane( Container view ){
        super( view );
        this.viewport.addComponentListener( this );
    }

    @Override
    public void componentHidden( ComponentEvent ce ){
    }

    @Override
    public void componentMoved( ComponentEvent ce ){
    }

    /** calculating required height is a 3 step process
      * 1. sync width of client and viewport, set height of client to high value
      * 2. let LayoutManager calculate required minimum size
      * 3. set preferredSize and revalidate
     **/
    @Override
    public void componentResized( ComponentEvent ce ){
        final Container view = (Container) this.viewport.getView();
        final int width = this.viewport.getExtentSize().width;
        view.setPreferredSize( new Dimension( width, Integer.MAX_VALUE ) );
        final int height = view.getLayout().preferredLayoutSize( view ).height;
        view.setPreferredSize( new Dimension( width, height ) );
        view.revalidate();
    }

    @Override
    public void componentShown( ComponentEvent ce ){
    }
}
1 голос
/ 12 февраля 2020

Что вам нужно сделать, это реализовать интерфейс Scrollable в компоненте, добавляемом в область прокрутки.

Затем вы можете принудительно заставить компонент соответствовать ширине области просмотра.

Самый простой способ сделать это - использовать прокручиваемую панель 1007 *, которая реализует методы интерфейса Scrollable и позволяет настраивать поведение.

Затем вы добавляете свою метку в ScrollablePanel и панель на панели прокрутки:

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


public class WrapTest extends JFrame {

    public WrapTest() {
        super("test");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        setLayout(new BorderLayout());

        JLabel label = new JLabel("<html>Lorem <b>ipsum</b> dolor sit amet, consectetur adipiscing elit. "
                + "Aliquam non pellentesque enim. Donec nec nisl tortor."
                + " Curabitur rutrum molestie est eget varius. Nullam ut lacinia est."
                + " Phasellus hendrerit sollicitudin justo, vitae malesuada dolor vestibulum at."
                + " Integer pharetra purus sed ipsum pulvinar, et pretium odio volutpat. Donec vitae varius metus."
                + " Cras sagittis vulputate erat, at faucibus lectus faucibus id. Cras varius nunc eu felis tristique dapibus."
                + " Aenean enim eros, dapibus pellentesque nibh ut, efficitur malesuada sapien. Nullam imperdiet nunc velit,"
                + "sed laoreet massa mattis eget. Morbi id justo quis sapien aliquet bibendum sed at leo. In mi felis, consectetur"
                + " sed orci eget, tempus maximus turpis. Curabitur sed felis id nisl vehicula sollicitudin sed eget erat.Ut sagittis at nisi sed facilisis."
                + " Morbi vel felis ac diam molestie consequat. Sed nisl lectus, sollicitudin at neque in, "
                + "placerat aliquet nunc. Maecenas quis enim vitae nunc fermentum congue. Sed posuere quam a ultricies fringilla."
                + " Vivamus aliquam nunc lacus, vitae consectetur tortor consequat ut. Cras viverra mi sit amet magna auctor eleifend."
                + " Morbi in risus nisl. Praesent nunc dolor, lobortis nec ultricies aliquet, sollicitudin eu sapien. Fusce interdum ac leo non suscipit."
                + "Vivamus at viverra elit, ut vestibulum elit. Sed bibendum, lorem et ornare sagittis, erat nulla ultricies odio, quis iaculis lacus nisl "
                + "vel ligula. Sed iaculis elit eu felis consectetur dignissim. ");


        ScrollablePanel panel = new ScrollablePanel( new BorderLayout() );
        panel.setScrollableWidth( ScrollablePanel.ScrollableSizeHint.FIT );
        panel.add( label );

        JScrollPane sp = new JScrollPane(panel);
        add(sp, BorderLayout.CENTER);

        setLocationByPlatform(true);
        setSize(500, 200);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            new WrapTest().setVisible(true);
        });
    }
}
0 голосов
/ 11 февраля 2020

Вы пробовали: sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);?

В противном случае вы можете попробовать использовать JEditorPane, поддерживающий контент HTML. Это может быть помещено в JScrollPane.

...