Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: GUI и Java FX приложения > Собственный компонент и JScrollPane


Автор: JRoma 22.3.2008, 14:55
Хочу при добавлении своего компонента в JScrollPane добиться такого же поведения, как у JEditorPane. 
При уменьшении размера окна, собственный компонент будет стараться, также как и JEditorPane, 
уменьшить свой размер, и только при достижении минимального размера будет прокручиваться.


Пример 1 (JEditorPane):
Код

import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;

public class MyExample01 extends JFrame {

    /**
     * @param args
     */
    public static void main(String[] args) {

        MyExample01 окно = new MyExample01();
        окно.pack();
        окно.setVisible(true);
    }

    public MyExample01() {

        setDefaultCloseOperation(EXIT_ON_CLOSE);

        JEditorPane текст = new JEditorPane();
        текст.setContentType("text/html");
        текст.setEditable(false);

        String строка = "<html>aaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa<br>"
                + "bbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbb bbbbbbbbbb bbbbbbbbbb bbbbbbbbbb<br>"
                + "cccccccccccccccccccccccc cccccccccc cccccccccc cccccccccc cccccccccc<br>"
                + "dddddddddddddddddddddddddd dddddddddd dddddddddd dddddddddd dddddddddd<br>";

        текст.setText(строка);

        JScrollPane скролл = new JScrollPane(текст);

        getContentPane().add(скролл);

    }

}


Пример 2 (собственный компонент):
Код

import java.awt.Dimension;
import java.awt.Rectangle;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.Scrollable;
import javax.swing.border.BevelBorder;

public class MyExample02 extends JFrame {

    /**
     * @param args
     */
    public static void main(String[] args) {

        MyExample02 окно = new MyExample02();
        окно.pack();
        окно.setVisible(true);

    }

    public MyExample02() {

        setDefaultCloseOperation(EXIT_ON_CLOSE);

        MyComponent текст = new MyComponent();

        текст.setBorder(new BevelBorder(BevelBorder.RAISED));

        String строка = "<html>aaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa<br>"
                + "bbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbb bbbbbbbbbb bbbbbbbbbb bbbbbbbbbb<br>"
                + "cccccccccccccccccccccccc cccccccccc cccccccccc cccccccccc cccccccccc<br>"
                + "dddddddddddddddddddddddddd dddddddddd dddddddddd dddddddddd dddddddddd<br>";

        текст.setText(строка);

        JScrollPane скролл = new JScrollPane(текст);

        getContentPane().add(скролл);
    }

}

class MyComponent extends JLabel implements Scrollable {

    public Dimension getPreferredScrollableViewportSize() {

        return getPreferredSize();
    }

    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {

        return 1;
    }

    public boolean getScrollableTracksViewportHeight() {

        return false;
    }

    public boolean getScrollableTracksViewportWidth() {

        return true;
    }

    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {

        return 1;
    }

}


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

Автор: JRoma 22.3.2008, 17:05
Изменил метод getScrollableTracksViewportWidth() в собственном компоненте. 

Код

public boolean getScrollableTracksViewportWidth() {

        if (getParent() instanceof JViewport){
            return ((JViewport)getParent()).getWidth() > getMinimumSize().width; 
        }
        return false;
    }


В итоге получилось почти так как надо (если размер JViewport по горизонтали меньше чем MinimumSize
собственного компонента, то появляется скролл). Но почему-то компонент растягивается до своего оптимального размера.
Непонятно как заставить его не растягиваться.

Автор: JRoma 22.3.2008, 22:05
Нужно было сразу смотреть исходники JEditorPane  smile

После небольшой доработки методов getScrollableTracksViewportHeight(), getScrollableTracksViewportWidth()
и getPreferredSize() получаем желаемый результат.

Код

import java.awt.Dimension;
import java.awt.Rectangle;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.Scrollable;
import javax.swing.border.BevelBorder;

public class MyExample02 extends JFrame {

    /**
     * @param args
     */
    public static void main(String[] args) {

        MyExample02 окно = new MyExample02();
        окно.pack();
        окно.setVisible(true);

    }

    public MyExample02() {

        setDefaultCloseOperation(EXIT_ON_CLOSE);

        MyComponent текст = new MyComponent();

        текст.setBorder(new BevelBorder(BevelBorder.RAISED));

        String строка = "<html>aaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa<br>"
                + "bbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbb bbbbbbbbbb bbbbbbbbbb bbbbbbbbbb<br>"
                + "cccccccccccccccccccccccc cccccccccc cccccccccc cccccccccc cccccccccc<br>"
                + "dddddddddddddddddddddddddd dddddddddd dddddddddd dddddddddd dddddddddd<br>";

        текст.setText(строка);

        JScrollPane скролл = new JScrollPane(текст);

        getContentPane().add(скролл);
    }

}

class MyComponent extends JLabel implements Scrollable {

    public Dimension getPreferredScrollableViewportSize() {

        return getPreferredSize();
    }

    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {

        return 1;
    }

    public boolean getScrollableTracksViewportHeight() {

        if (getParent() instanceof JViewport) {
            JViewport port = (JViewport) getParent();
            // TextUI ui = getUI();
            int h = port.getHeight();
            Dimension min = getMinimumSize(); // ui.getMinimumSize(this);
            if (h >= min.height) {
                Dimension max = getMaximumSize(); // ui.getMaximumSize(this);
                if (h <= max.height) {
                    return true;
                }
            }
        }
        return false;
    }

    public boolean getScrollableTracksViewportWidth() {

        if (getParent() instanceof JViewport) {
            JViewport port = (JViewport) getParent();
            // TextUI ui = getUI();
            int w = port.getWidth();
            Dimension min = getMinimumSize(); // ui.getMinimumSize(this);
            Dimension max = getMaximumSize(); // ui.getMaximumSize(this);
            if ((w >= min.width) && (w <= max.width)) {
                return true;
            }
        }
        return false;
    }

    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {

        return 1;
    }

    @Override
    public Dimension getPreferredSize() {
        Dimension d = super.getPreferredSize();
        if (getParent() instanceof JViewport) {
            JViewport port = (JViewport) getParent();
            // TextUI ui = getUI();
            int prefWidth = d.width;
            int prefHeight = d.height;
            if (!getScrollableTracksViewportWidth()) {
                int w = port.getWidth();
                Dimension min = getMinimumSize(); // ui.getMinimumSize(this);
                if (w != 0 && w < min.width) {
                    // Only adjust to min if we have a valid size
                    prefWidth = min.width;
                }
            }
            if (!getScrollableTracksViewportHeight()) {
                int h = port.getHeight();
                Dimension min = getMinimumSize(); // ui.getMinimumSize(this);
                if (h != 0 && h < min.height) {
                    // Only adjust to min if we have a valid size
                    prefHeight = min.height;
                }
            }
            if (prefWidth != d.width || prefHeight != d.height) {
                d = new Dimension(prefWidth, prefHeight);
            }
        }
        return d;
    }

}


P.S. Получился неплохой монолог.  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)