Полосы прокрутки JScrollPane не прокручиваются

У меня есть класс, который рисует очень простую графику, такую ​​как линии, круги и прямоугольники. Линии динамически расширяются, и иногда, когда они расширяются за пределы разрешения, их невозможно увидеть без полосы прокрутки. Поэтому я добавил JScrollPane в свой JFrame, но, к сожалению, полоса прокрутки не прокручивается, несмотря на то, что уже вызывается диспетчер компоновки.

Вот что у меня есть: - Класс, который рисует компоненты (линии, прямоугольники, круги) - Класс, который устанавливает JFrame/JScrollPane

Вот фрагмент кода моего класса GUI:

    JFrame frame = new JFrame("GUIFrame");
    frame.setLayout(new BorderLayout()); // Layout already set
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    DrawComponent comp = new DrawComponent(); // Reference to class that draw components
    JScrollPane sp = new JScrollPane(comp, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
    sp.setPreferredSize(new Dimension(1000, 1000));

    frame.add(sp, BorderLayout.CENTER);
    frame.setSize(500,500);
    frame.setVisible(true);

С приведенным выше кодом у меня есть Java, чтобы показать мне JFrame с панелью прокрутки, содержащей мои jcomponents. Я настроил полосы прокрутки так, чтобы они всегда отображались, как показано выше, но они не прокручиваются, выделены серым цветом.

Как предложил Эндрю, мне потребовалось некоторое время, чтобы создать SSCCE, чтобы отразить то, что я пытаюсь сделать:

import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.util.Random;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;


public class DrawTest {
    public static void main(String[] args){
        JFrame frame = new JFrame("SSCCE");
        frame.setLayout(new BorderLayout());
        frame.setSize(1000, 1000);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);       

        DrawComp d = new DrawComp();
        JScrollPane sp = new JScrollPane(d, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);

        frame.add(sp);      
        frame.setVisible(true);
    }
}

class DrawComp extends JComponent {

    public void paintComponent(Graphics g){
        Graphics2D g2 = (Graphics2D)g;

        Random ran = new Random();
        int ranNum = ran.nextInt(10);
        System.out.println(ranNum);
        double length = 100 * ranNum;
        g2.draw(new Line2D.Double(10, 10, length, length));
    }
}

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


person James Riden    schedule 02.01.2013    source источник
comment
1) Чтобы быстрее получить помощь, опубликуйте SSCCE. 2) comp.setPreferredSize(new Dimension(1000, 1000)); sp.validate(); //sp.setPreferredSize(new Dimension(1000, 1000)); 3) frame.pack();   -  person Andrew Thompson    schedule 02.01.2013
comment
Я думаю, вам нужно взглянуть на как использовать области прокрутки чтобы лучше понять, как они работают. sp.setPreferredSize(new Dimension(1000, 1000)); повлияет не на прокручиваемую область, а на размер компонента. ViewPort отвечает за определение прокручиваемой области (по крайней мере, с точки зрения того, чего вы пытаетесь достичь   -  person MadProgrammer    schedule 02.01.2013
comment
Спасибо за помощь, но у меня сложилось впечатление, что использование setPreferredSize не рекомендуется?   -  person James Riden    schedule 02.01.2013
comment
У меня сложилось впечатление, что использование setPreferredSize не рекомендуется Это есть среди пять лучших в FAQ. Есть шанс увидеть этот SSCCE? Лучший совет исходит из кода, с которым можно поиграть.   -  person Andrew Thompson    schedule 02.01.2013
comment
Разработал простой класс, чтобы подумать о том, что я делаю, как предложил Эндрю.   -  person James Riden    schedule 02.01.2013


Ответы (2)


Мои извинения. Вы правильно используете JScrollPane. Я запустил ваш код и думаю, что понял причину, по которой JScrollPane не работает. Представьте себе это, когда вы установили фон jframe полностью красным (путем рисования красной точки везде), должна ли jscrollpane прокручиваться? Нет, потому что цвет фона находится в фоновом режиме. Фактический ВИД не меняется, и он не больше размера экрана, поэтому панель прокрутки не видит смысла прокрутки. Ваш метод компонента краски делает что-то подобное. Он просто рисует что-то на заднем плане. Фактический ВИД не изменился, поэтому панель прокрутки не будет работать.

public class DrawTest {
    public static void main(String[] args){
        JFrame frame = new JFrame("SSCCE");
        frame.setLayout(new BorderLayout());
        frame.setSize(500, 500);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);       

        final DrawComp d = new DrawComp();
        final JScrollBar hbar,vbar;
        hbar = new JScrollBar(JScrollBar.HORIZONTAL, 0, 1, 0, 500);
        vbar = new JScrollBar(JScrollBar.VERTICAL, 0, 1, 0, 500);

        frame.setLayout(null);
        frame.add(d);      
        frame.add(hbar);      
        frame.add(vbar);      
        d.setBounds(0, 0, 300, 300);
        vbar.setBounds(460, 0, 20, 480);
        frame.setVisible(true);

        vbar.addAdjustmentListener(new AdjustmentListener() 
        {
            public void adjustmentValueChanged(AdjustmentEvent e) 
            {
                d.setLocation(d.getX(), -vbar.getValue());
            }
        });
    }
}

Вот код для сдвига компонента по вертикали. Я внес некоторые изменения в ваш существующий код. DrawComp все тот же

person Community    schedule 02.01.2013
comment
Я добавил свои компоненты в панель прокрутки в JScrollPane sp = new JScrollPane(comp). Чтобы панель прокрутки отображалась в окне, мне нужно добавить панель прокрутки в рамку, не так ли? Я не мог понять, что я делаю неправильно - person James Riden; 02.01.2013
comment
Сначала задается размер компонента. Все рисование будет происходить в прямоугольнике размера этого компонента (область обрезки). Если вы попытаетесь нарисовать что-то сверх этого, это будет просто проигнорировано. Он не будет прокручиваться, как вы ожидаете. - person basiljames; 02.01.2013
comment
Мои извинения. Вы правильно используете JScrollPane. Я запустил ваш код и думаю, что понял причину, по которой JScrollPane не работает. - person ; 02.01.2013
comment
Я попробовал getPreferredSize() и, по-видимому, он вернул 0,0, что может быть причиной этой проблемы. Теоретически менеджер компоновки должен был справиться с этим - и я настроил менеджер компоновки, но по какой-то причине он просто не работает. @Xiaoerge, не могли бы вы просветить меня, где ошибка, из-за которой он не работает? - person James Riden; 02.01.2013
comment
@Xiaoerge Я должен признать, что это немного сбивает с толку. Как тогда изменить фактический вид, а не просто рисовать на заднем плане? - person James Riden; 02.01.2013
comment
Прости. Я мог бы сказать яснее. Я думаю, что это может быть обходной метод. Нарисуйте композицию так же, как вы это делаете. Но не устанавливайте тип макета для jframe. Вместо этого используйте Null. (Это позволит вам установить размер и положение). И не используйте панель прокрутки. Используйте 2 полосы прокрутки, и когда пользователь двигает полосу прокрутки, Переместите нарисованный компонент влево вправо вверх вниз, чтобы показать эффект скольжения. - person ; 02.01.2013
comment
frame.setLayout(ноль); frame.add (окрашенный ком); scrollbar.addActionListener(//..... коды действий) переместите нарисованный ком, выполнив Painted-com.setLocation(scrollbar.getvalue.....) - person ; 02.01.2013
comment
@Xiaoerge - Спасибо за вашу помощь! Очень ценится. Хотя в итоге я не пошел по вашему пути, теперь я понимаю, в чем заключалась основная проблема. Получил удовольствие от обучения! - person James Riden; 02.01.2013

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

Относительно SSCCE, о котором я писал выше, я добавил setPreferredSize(new Dimension(length, length) в paintComponent(), чтобы при ее вызове привилегированный размер всегда был конечной точкой строки. Это удостоверяется, что я покрыл всю область картины и все же могу прокручивать, если в этом есть необходимость.

person James Riden    schedule 02.01.2013
comment
Вместо этого переопределите getPreferredSize(), как предлагается здесь. - person trashgod; 02.01.2013
comment
добавлен setPreferredSize(new Dimension(length, length) в paintComponent(), который чрезвычайно вонючий, одновременно нарушающий два основных правила: а) никогда не изменять состояние компонента во время цикла рисования б) вообще не вызывать setPreferredSize. - person kleopatra; 30.03.2013