【问题标题】:JFreeChart not appearing on JPanel - may be something to do with my code's logicJFreeChart 未出现在 JPanel 上 - 可能与我的代码逻辑有关
【发布时间】:2013-05-30 01:18:17
【问题描述】:

这个问题与几天前的a similar question I posted on here有关......

这是显示我希望图表出现在哪里的界面:

我想在右侧的大 JPanel 上显示图表。该图表的目的是将特定球员的统计数据与他们国家的平均水平和整体平均水平(三个条形图)进行比较。图表(应该)通过从文本框中获取玩家的名字(其中已经有“getPlayerName”的那个)知道要显示比较的玩家。就像我之前提到的类似问题一样,我创建了一个类(这次称为 PlayerVsCountryVsOverallChart) - 它将处理为此特定统计数据构建图表。

“PlayerVsCountryVsOverallChart”类的代码非常相似,但我认为其中有一些逻辑会阻止图表显示(甚至无法制作)。由于我的逻辑仍在开发中(与 JFreeCharts 相关),如果有人能帮我研究一下,我将不胜感激。

这是 PlayerVsCountryVsOverallChart 类的代码 - 减去必要的导入:

/**
 * This class is responsible for displaying the chart for 
 * the "Player vs Country vs Overall" functionality in the 
 * "Single Player" tab.
 * @author attfire1
 */
public class PlayerVsCountryVsOverallChart extends JPanel
{
    private static final long serialVersionUID = 1L;
    private ArrayList<Player> players;
    private StatUtilities stats;
    public String yAxisLabel = "";
    private String chosenPlayer;
    public String[] compareStatsOptions = new String[] { "Average Balls Bowled", "Average of Bowling Averages", "Average Career Length", "Average Economy Rate", "Average Number of Five Wicket Innings", "Average Innings Played", "Average Matches Played", "Average Runs Conceded", "Average Strike Rate", "Average Wickets Taken" };
    ;

    /**
     * This constructor is responsible for producing the stats bar chart in 
     * the "Single Player Stats" tab in AppInterface.
     * @param applicationTitle
     * @param chartTitle
     * @param players The list of players to iterate through
     * @param option The option which determines what statistics to display
     * @param chosenPlayer The chosen player's name
     */
    public PlayerVsCountryVsOverallChart(String applicationTitle, String chartTitle, ArrayList<Player> players, int option, String chosenPlayer) {
        //super(applicationTitle);

        this.players = players;
        this.chosenPlayer = chosenPlayer;
        stats = new StatUtilities();

        final CategoryDataset dataset = createDataset(option, chosenPlayer);

        // based on the dataset we create the chart
        final JFreeChart chart = createChart(dataset, applicationTitle);

        // we put the chart into a panel
        final ChartPanel chartPanel = new ChartPanel(chart);
        chartPanel.setPreferredSize(new Dimension(500, 270));

        // Don't forget me...
        setLayout(new BorderLayout());
        add(chartPanel); 
    }

    /**
     * This method returns the nth occurrence of a 
     * character in a given string.
     * 
     * Sourced from https://stackoverflow.com/questions/3976616/how-to-find-nth-occurrence-of-character-in-a-string.
     * @param str The string to get the index of a character from.
     * @param c The character to get the index of.
     * @param n What occurrence of character to retrieve.
     * @return The nth occurrence of a character.
     */
    public static int nthOccurrence(String str, char c, int n) {
        int pos = str.indexOf(c, 0);
        while (n-- > 0 && pos != -1)
            pos = str.indexOf(c, pos+1);
        return pos;
    }



/** * Creates a sample dataset */

    private  CategoryDataset createDataset(int graphDisplayOption, String playerChosen) {

        // row keys... "series"
        final String player = "Player";
        final String country = "Country";
        final String overall = "Overall";



        ArrayList<String> countries = new ArrayList<String>();
        for (Player p : players) {
            countries.add(p.getCountryName());
        }

        //these are also the "column keys"
        Set<String> countryNames = new HashSet<String>(countries);

        final DefaultCategoryDataset dataset = new DefaultCategoryDataset();

        /*
         * The below code block uses a switch statement to determine
         * which type of stats to display in the graph (country by country).
         * 
         * Options for the switch statement are as follows:
         * 
         * 1 = Average Balls Bowled
         * 2 = Average of Bowling Averages
         * 3 = Average Career Lengths
         * 4 = Average Economy Rates
         * 5 = Average Number of 5 Wicket Innings
         * 6 = Average Innings Played
         * 7 = Average Matches Played
         * 8 = Average Runs Conceded
         * 9 = Average Strike Rates
         * 10 = Average WicketsTaken
         */
        for(int i = 0; i < players.size(); i++)
        {
            //if the player's name in iteration i equals the chosen player's name
            if(players.get(i).getPlayerName().equals(playerChosen))
            {
            switch(graphDisplayOption)
                {
                    case 1:
                        yAxisLabel = compareStatsOptions[0];
                        dataset.addValue(players.get(i).getBallsBowled(), player, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveBallsBowled(players, players.get(i).getCountryName()), country, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveBallsBowled(players), overall, players.get(i).getPlayerName());
                        break;
                    case 2:
                        yAxisLabel = compareStatsOptions[1];
                        dataset.addValue(players.get(i).getBowlingAverage(), player, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveBowlingAverage(players, players.get(i).getCountryName()), country, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveBowlingAverage(players), overall, players.get(i).getPlayerName());
                        break;
                    case 3:
                        yAxisLabel = compareStatsOptions[2];
                        dataset.addValue(players.get(i).calcCareerSpan(), player, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveCareerLength(players, players.get(i).getCountryName()), country, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveCareerLength(players), overall, players.get(i).getPlayerName());
                        break;
                    case 4:
                        yAxisLabel = compareStatsOptions[3];
                        dataset.addValue(players.get(i).getEconomyRate(), player, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveEconRate(players, players.get(i).getCountryName()), country, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveEconRate(players), overall, players.get(i).getPlayerName());
                        break;
                    case 5:
                        yAxisLabel = compareStatsOptions[4];
                        dataset.addValue(players.get(i).getFiveWicketsInnings(), player, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveFiveWicketsInns(players, players.get(i).getCountryName()), country, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveFiveWicketsInns(players), overall, players.get(i).getPlayerName());
                        break;
                    case 6:
                        yAxisLabel = compareStatsOptions[5];
                        dataset.addValue(players.get(i).getInningsPlayed(), player, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveInningsPerCountry(players, players.get(i).getCountryName()), country, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveInningsPerPlayer(players), overall, players.get(i).getPlayerName());
                        break;
                    case 7:
                        yAxisLabel = compareStatsOptions[6];
                        dataset.addValue(players.get(i).getMatchesPlayed(), player, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveMatchesPerPlayer(players, players.get(i).getCountryName()), country, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveMatchesPerPlayer(players), overall, players.get(i).getPlayerName());
                        break;
                    case 8:
                        yAxisLabel = compareStatsOptions[7];
                        dataset.addValue(players.get(i).getRunsConceded(), player, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveRunsConceded(players, players.get(i).getCountryName()), country, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveRunsConceded(players), overall, players.get(i).getPlayerName());
                        break;
                    case 9:
                        yAxisLabel = compareStatsOptions[8];
                        dataset.addValue(players.get(i).getStrikeRate(), player, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveStrikeRate(players, players.get(i).getCountryName()), country, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveStrikeRate(players), overall, players.get(i).getPlayerName());
                        break;
                    case 10:
                        yAxisLabel = compareStatsOptions[9];
                        dataset.addValue(players.get(i).getWicketsTaken(), player, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveWickets(players, players.get(i).getCountryName()), country, players.get(i).getPlayerName());
                        dataset.addValue(stats.aveWickets(players), overall, players.get(i).getPlayerName());
                        break;
                }


            }
        }
        return dataset;

    }


/** * Creates a chart */

    private JFreeChart createChart(CategoryDataset dataset, String title) {

        // create the chart...
        final JFreeChart chart = ChartFactory.createBarChart(
            title,         // chart title
            "Countries",               // domain axis label
            yAxisLabel,                  // range axis label
            dataset,                  // data
            PlotOrientation.VERTICAL, // orientation
            true,                     // include legend
            true,                     // tooltips?
            false                     // URLs?
        );

        // NOW DO SOME OPTIONAL CUSTOMISATION OF THE CHART...

        // set the background color for the chart...
        chart.setBackgroundPaint(Color.white);

        // get a reference to the plot for further customisation...
        final CategoryPlot plot = chart.getCategoryPlot();
        plot.setBackgroundPaint(Color.lightGray);
        plot.setDomainGridlinePaint(Color.white);
        plot.setRangeGridlinePaint(Color.white);

        // set the range axis to display integers only...
        final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

        // disable bar outlines...
        final BarRenderer renderer = (BarRenderer) plot.getRenderer();
        renderer.setDrawBarOutline(false);

        // set up gradient paints for series...
        final GradientPaint gp0 = new GradientPaint(
            0.0f, 0.0f, Color.blue, 
            0.0f, 0.0f, Color.lightGray
        );
        final GradientPaint gp1 = new GradientPaint(
            0.0f, 0.0f, Color.green, 
            0.0f, 0.0f, Color.lightGray
        );
        final GradientPaint gp2 = new GradientPaint(
            0.0f, 0.0f, Color.red, 
            0.0f, 0.0f, Color.lightGray
        );
        renderer.setSeriesPaint(0, gp0);

        final CategoryAxis domainAxis = plot.getDomainAxis();
        domainAxis.setCategoryLabelPositions(
            CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / 6.0)
        );
        // OPTIONAL CUSTOMISATION COMPLETED.

        return chart;

    }
}

我不确定该课程的 SSCCE 应该发布什么 - 我感觉问题可能出在“CategoryDataset createDataset”方法中的 switch-case 语句中......

这里是“Go”按钮的按钮监听器代码,当它被点击时应该会生成图表(连同在它旁边的 JComboBox 中选择的选项,以及文本框中的玩家姓名):

private void confirmGraphBtnActionPerformed(java.awt.event.ActionEvent evt) {                                                
        String selectedOption = String.valueOf(chooseGraphOption.getSelectedItem()).toString();
        int statsOption = options.indexOf(selectedOption);

        processCvPvOchart(statsOption);
    } 

最后,这里是 processCvPvOchart 方法的代码:

/**
     * This method processes the chart for the "Player vs Country vs Overall" 
     * player stats, in the "Single Player Stats" tab.
     * @param option The option for which stats to display.
     */
    public void processCvPvOchart(int option)
    {
        //pVcVo = "Player vs Country vs Overall"
        String title = pVcVo.get(option);
        PlayerVsCountryVsOverallChart chart = new PlayerVsCountryVsOverallChart(title, "", players, option + 1, getPlayerName.getText());
        displayGraphPanel.add(chart);
        repaint();

    }

我已将此代码提交到我在 GitHub 上的项目存储库 https://github.com/rattfieldnz/Java_Projects/tree/master/PCricketStats。运行它并测试它可能对想要帮助我的人有益。一旦我了解了有关剖析 SSCCE 代码的更多信息,我将包含更小的代码片段。

【问题讨论】:

  • 您是否尝试在将字符添加到面板后添加repaint...就像上次一样;)。如果重绘容器不起作用,您可能需要确保重绘父容器
  • 是的,这次我没有忘记……我稍微重构了我的代码,并将 repaint() 放在了一个方法中,以减少代码的重复……

标签: java swing jfreechart gui-builder


【解决方案1】:

图表本身在很大程度上是无关紧要的,除了它

  1. 有一些首选尺寸。

  2. 已添加到具有合适布局的Container

在下面的sscce 中,模拟播放器面板和图表面板添加到GridLayout(1, 0)。通过覆盖getPreferredSize()ChartPanel 被赋予任意大小。

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.util.Random;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

/**
 * @see http://stackoverflow.com/a/16828209/230513
 */
public class Test {

    private static final int N = 128;
    private static final Random random = new Random();

    private void display() {
        JFrame f = new JFrame("Test");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel p = new JPanel(new GridLayout(1, 0));
        p.add(createPlayerPanel());
        p.add(createChartPanel());
        f.add(p);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private ChartPanel createChartPanel() {
        final XYSeries series = new XYSeries("Data");
        for (int i = 0; i < random.nextInt(N) + N / 2; i++) {
            series.add(i, random.nextGaussian());
        }
        XYSeriesCollection dataset = new XYSeriesCollection(series);
        JFreeChart chart = ChartFactory.createXYLineChart("Test", "Domain",
            "Range", dataset, PlotOrientation.VERTICAL, false, false, false);
        return new ChartPanel(chart) {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(N * 2, N * 2);
            }
        };
    }

    private Box createPlayerPanel() {
        Box b = new Box(BoxLayout.Y_AXIS);
        b.setBorder(new EmptyBorder(10, 10, 10, 10));
        for (int i = 0; i < 16; i++) {
            JLabel label = new JLabel();
            label.setAlignmentX(0.5f);
            String s = String.valueOf(label.hashCode());
            label.setText(s + ": " + s);
            b.add(label);
        }
        return b;
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Test().display();
            }
        });
    }
}

【讨论】:

    【解决方案2】:

    尝试在自己的 JPanel 上创建图表,然后将其添加到您现有的项目中。

    还要查看 jpanel 布局,确保您使用的是最合适的。

    【讨论】:

    • 很高兴看到您注册了 Stack Overflow Adam 哈哈。 JPanel 布局很好 - 它与我设法开始的图形相同(除了有点大)。问题出在我图表类文件的逻辑中。不应该这么难 - 这个图表与我成功实施的图表几乎相同。
    猜你喜欢
    • 1970-01-01
    • 2013-06-20
    • 1970-01-01
    • 2020-07-25
    • 2015-06-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-12
    • 2021-09-25
    相关资源
    最近更新 更多