Проблема с обрезкой jfreechart в Java

Я пытаюсь создать класс, который делает циферблат похожим на тот, что в демонстрациях jfreechart. Однако я хочу, чтобы рамка с циферблатами была прокручиваемой, если окно становится меньше, чем необходимо для печати циферблата. Я добился этого с помощью области прокрутки, но происходит то, что из-за того, что на циферблате есть тяжелые компоненты, они печатаются за пределами порта просмотра и над полосой прокрутки, а у меня этого не может быть.

Код, который я написал для проверки этой функции:

РЕДАКТИРОВАТЬ: я сделал код меньше, пытаясь сделать его SSCCE (это первый раз, когда я публикую вопрос, извините, если он все еще слишком большой)

РЕДАКТИРОВАТЬ 2: Я понял, что это проблема в дистрибутиве jfreechart, который я использую (и должен использовать), а именно 1.0.9. Эта ошибка не воспроизводится с текущей версией jfreechart.

import java.awt.*;
import javax.swing.JPanel;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.dial.*;
import org.jfree.data.general.DefaultValueDataset;
import org.jfree.ui.*;

public class DialDoubleNeedle extends JPanel{

    private DefaultValueDataset dataset1;
    private DefaultValueDataset dataset2;
    private JFreeChart chart;
    public DialDoubleNeedle() {
        super();

        this.dataset1 = new DefaultValueDataset(0.10);
        this.dataset2 = new DefaultValueDataset(0.50);

        // get data for diagrams
        DialPlot plot = new DialPlot();
        plot.setView(0.0, 0.0, 1.0, 1.0);
        plot.setDataset(0, this.dataset1);
        plot.setDataset(1, this.dataset2);
        StandardDialFrame dialFrame = new StandardDialFrame();
        dialFrame.setBackgroundPaint(Color.lightGray);
        dialFrame.setForegroundPaint(Color.darkGray);        
        plot.setDialFrame(dialFrame);

        GradientPaint gp = new GradientPaint(new Point(), 
                new Color(255, 255, 255), new Point(), 
                new Color(170, 170, 220));

        DialBackground db = new DialBackground(gp);
        db.setGradientPaintTransformer(new StandardGradientPaintTransformer(GradientPaintTransformType.VERTICAL));
        plot.setBackground(db);
        DialTextAnnotation annotation1 = new DialTextAnnotation("m/s");
        annotation1.setFont(new Font("Dialog", Font.BOLD, 14));
        annotation1.setRadius(0.7);

        plot.addLayer(annotation1);

        DialValueIndicator dvi = new DialValueIndicator(0);
        dvi.setFont(new Font("Dialog", Font.PLAIN, 10));
        dvi.setOutlinePaint(Color.darkGray);
        dvi.setRadius(0.60);
        dvi.setAngle(-103.0);
        dvi.setNumberFormat(new java.text.DecimalFormat("0.00"));
        plot.addLayer(dvi);

        DialValueIndicator dvi2 = new DialValueIndicator(1);
        dvi2.setFont(new Font("Dialog", Font.PLAIN, 10));
        dvi2.setOutlinePaint(Color.red);
        dvi2.setRadius(0.60);
        dvi2.setAngle(-77.0);
        dvi2.setNumberFormat(new java.text.DecimalFormat("0.00"));
        plot.addLayer(dvi2);

        StandardDialScale scale = new StandardDialScale(0, 1, -120, -300, 0.1, 5);
        scale.setTickRadius(0.88);
        scale.setTickLabelOffset(0.15);
        scale.setTickLabelFont(new Font("Dialog", Font.PLAIN, 14));
        plot.addScale(0, scale);

        StandardDialScale scale2 = new StandardDialScale(0, 1, -120, -300, 0.1, 5);
        scale2.setTickRadius(0.50);
        scale2.setTickLabelOffset(0.15);
        scale2.setTickLabelFont(new Font("Dialog", Font.PLAIN, 10));
        scale2.setMajorTickPaint(Color.red);
        plot.addScale(1, scale2);
        plot.mapDatasetToScale(1, 1);

        DialPointer needle2 = new DialPointer.Pin(1);
        needle2.setRadius(0.55);
        plot.addLayer(needle2);

        DialPointer needle = new DialPointer.Pointer(0);
        plot.addLayer(needle);

        DialCap cap = new DialCap();
        cap.setRadius(0.10);
        plot.setCap(cap);

        chart = new JFreeChart(plot);
        chart.setTitle("Title");
        ChartPanel cp1 = new ChartPanel(chart);
        add(cp1);


    }

    void setTitle(String title){
        chart.setTitle(title);
        return;
    }


    public static void main(final String args[]) {
        final javax.swing.JFrame test = new javax.swing.JFrame();
        test.addWindowListener(new java.awt.event.WindowAdapter() {
            @Override
            public void windowClosing(final java.awt.event.WindowEvent e) {
                System.exit(0);
            }
        });

        final JPanel jpanel1 = new JPanel();

        DialDoubleNeedle app1 = new DialDoubleNeedle();
        app1.setTitle("Tittle 1");

        jpanel1.add(app1);

        final javax.swing.JScrollPane scrollPane = new javax.swing.JScrollPane();

        scrollPane.setViewportView(jpanel1);

        test.getContentPane().add(scrollPane);
        test.pack();
        test.setVisible(true);


        int i;
        Number v;   
        for(i=0; i<1000000000; i++){
            if(i==(1000000000-1)){
                i=0;
                v=app1.dataset1.getValue();
                app1.dataset1.setValue(v.doubleValue()+0.01);
            }
        }

    }
}

Если вы скомпилируете приведенный выше код, вы увидите, что когда он запускается, он выглядит нормально, но если вы его уменьшите, в конечном итоге некоторые части циферблата (тяжелые) окажутся поверх полос прокрутки. Что я могу сделать, чтобы это исправить?


person jonny    schedule 24.10.2013    source источник
comment
Используйте SSCCE: sscce.org   -  person StormeHawke    schedule 24.10.2013
comment
+1 за sscce, хотя @StormeHawke прав в том, что это могло быть немного короче. :-)   -  person trashgod    schedule 25.10.2013
comment
правда, я учусь. И отчасти проблема связана с тем, что визуальная ошибка, которую я получаю, связана не со всеми компонентами, а только с некоторыми, поэтому я публикую почти всю графическую часть своего кода.   -  person jonny    schedule 25.10.2013


Ответы (1)


Насколько мне известно, ни JFreechart, ни org.jfree.chart.plot.dial.* не содержат тяжелых компонентов. Ваш пример меняет размер нормально. Несколько примечаний:

  • Не используйте setPreferredSize(), когда вы действительно хотите переопределить getPreferredSize(), как показано здесь и обсуждалось здесь.

  • Объекты графического интерфейса Swing должны создаваться и управляться только на поток отправки событий.

  • Вместо того, чтобы зацикливаться на начальном потоке, используйте _ 5_ для ускорения анимации.

  • Ваше использование GridBagConstraints неуместно. Простая вертикальная GridLayout работает хорошо и избавляет от необходимости использовать set*Size() на панели или в области прокрутки.

    final JPanel jpanel1 = new JPanel(new GridLayout(0, 1));
    
  • JFrame может установить операцию закрытия по умолчанию, что устраняет необходимость в WindowListener.

    test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
person trashgod    schedule 24.10.2013
comment
Я действительно думаю, что в нем есть тяжелые компоненты, а именно такие вещи, как градиентный фон и форма циферблата. Обратите внимание: если вы его уменьшите, у вас получится перекрытие только некоторых вещей. Спасибо за все предложения. Я должен добавить, что main в приведенном выше коде - это просто быстрый и грязный тестовый main, никоим образом не связанный с тем, как он используется, за исключением того, что визуальная ошибка остается - person jonny; 25.10.2013
comment
Извините, я не могу воспроизвести описанный вами эффект, который способствует проблеме синхронизации; попробуйте invokeLater() на своей платформе. - person trashgod; 25.10.2013
comment
Ну, я пытаюсь заработать достаточно репутации, чтобы размещать фотографии, тогда должно быть легко показать проблему. Для меня это не зависит от платформы, которую я выбираю. Я не пробовал использовать самый последний дистрибутив JFreeChart, так как это коммерческий продукт, у нас есть лицензия только на немного старую версию jfreechart. - person jonny; 25.10.2013
comment
Проблема действительно была в старой версии JFreechart. Я попрошу, чтобы мы могли обновиться до новой версии, иначе мне придется повторно попросить предоставить эту дополнительную информацию. В настоящее время у нас есть лицензия на использование JFreechart версии 1.0.9. - person jonny; 25.10.2013
comment
Ах, приятно знать. Лицензия LGPL; вы всегда можете обновить его бесплатно, но вы захотите повторно протестировать и выполнить управление конфигурацией. - person trashgod; 25.10.2013