Search code examples
javauser-interfacenetbeansgraphics2dgraphing

How to display Graphics2D object on JFrame


This is my first time trying to build a GUI and I've reached an impasse which I can't seem to find the solution to. Currently I have parts of my GUI set up but I want to insert a graph I've created on another class, however, I'm not sure how to link it with my current JFrame. I can get it to work as a separate entity, but not together.

MainDisplay Class:

public static void main(String args[]) {
    /* Set the Nimbus look and feel */
    //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
    /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
     * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
     */
    try {
        for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                javax.swing.UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    } catch (ClassNotFoundException ex) {
        java.util.logging.Logger.getLogger(MainDisplay.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (InstantiationException ex) {
        java.util.logging.Logger.getLogger(MainDisplay.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
        java.util.logging.Logger.getLogger(MainDisplay.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (javax.swing.UnsupportedLookAndFeelException ex) {
        java.util.logging.Logger.getLogger(MainDisplay.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    }
    //</editor-fold>
    //</editor-fold>

    /* Create and display the form */
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new MainDisplay().setVisible(true);
        }

    });
     float LvBTC;
    float LvLTC;
    float LvETH;

    float[] HBTC;
    float[] HLTC;
    float[] HETH;

    float CurETH;
    float CurBTC;
    float CurLTC;

    WebScraper WS1 = new WebScraper();
    LvBTC = WS1.LvScrapeBTC();
    LvLTC = WS1.LvScrapeLTC();
    LvETH = WS1.LvScrapeETH();

    HBTC = WS1.HScrapeBTC();
    HLTC = WS1.HScrapeLTC();
    HETH = WS1.HScrapeETH(); 

    System.out.println("Bitcoin's Current Price is: $"+LvBTC);
    System.out.println("Litecoin's Current Price is: $"+LvLTC);
    System.out.println("Ethereum's Current Price is: $"+LvETH);
    Graph G1 = new Graph();
    G1.CurrentValues(HBTC);

    for (int i = 0; 5 > i;) {
        System.out.println("Day " + (i + 1) + ": $" + G1.CurValues[i]);
        i++;
    }

   System.out.println("Index of largest value: " + G1.IndexLarge(G1.CurValues));
    System.out.println("Index of smallest value: " + G1.IndexSmall(G1.CurValues));

    Graph Graphing = new Graph();



}

Graph Class:

package comsci_ia;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Arrays;

import javax.swing.JFrame;

public class Graph extends JFrame {

int IndexL;
int IndexS;
int DistanceDay1;
int DistanceDay2;
int DistanceDay3;
int DistanceDay4;
int DistanceDay5;
float[] CurValues = new float[5];

ArrayList<Point> points = new ArrayList<>();

public float[] CurrentValues(float[] array) {
    DatabaseBrowser DB1 = new DatabaseBrowser();
    WebScraper WS1 = new WebScraper();

    float[] HBTC = WS1.HScrapeBTC();
    float[] HETH = WS1.HScrapeETH();
    float[] HLTC = WS1.HScrapeLTC();

    float CurHold = 0;

    boolean BTCCheck = false;
    BTCCheck = Arrays.equals(HBTC, array);

    boolean LTCCheck = false;
    LTCCheck = Arrays.equals(HLTC, array);

    boolean ETHCheck = false;
    ETHCheck = Arrays.equals(HETH, array);

    if (BTCCheck == true) {
        CurHold = DB1.RetriveBTC();
    }

    if (LTCCheck == true) {
        CurHold = DB1.RetriveLTC();
    }

    if (ETHCheck == true) {
        CurHold = DB1.RetriveETH();
    }

    float pick;

    for (int i = 0; 5 > i;) {
        for (int z = 0; z < array.length; z++) {
            pick = array[z];
            pick = pick * CurHold;
            CurValues[i] = pick;
            i++;
        }

    }
    return CurValues;
}

public int IndexLarge(float[] array) {
    float temp = 0;
    for (int i = 0; 5 > i;) { //Cycles through ArrayList and replaces temp with the Largest value
        if (array[i] > temp) {
            temp = array[i];
        }
        i++;
    }
    int IndexCheck = 0; //Searches and records the index of "temp" value (Largest value in array)
    for (IndexCheck = 0; 5 > IndexCheck;) {
        if (array[IndexCheck] == temp) {
            break;
        }
        IndexCheck++;
    }
    IndexL = IndexCheck;
    return IndexL;
}

public int IndexSmall(float[] array) {
    float temp = 1000000;
    for (int i = 0; 5 > i;) { //Cycles through ArrayList and replaces temp with the smallest value
        if (array[i] < temp) {
            temp = array[i];
        }
        i++;
    }
    int IndexCheck = 0; //Searches and records the index of "temp" value (smallest value in array)
    for (IndexCheck = 0; 5 > IndexCheck;) {
        if (array[IndexCheck] == temp) {
            break;
        }
        IndexCheck++;
    }
    IndexS = IndexCheck;
    return IndexS;
}

public void Plotter(float[] array) { 
  /*  int DayRefL = IndexL + 1;
    int DayRefS = IndexS + 1; */
    float ValRange;
    float ValPx;

    points = null;

    ValRange = array[IndexL] - array[IndexS];
    ValPx = (300f/ ValRange); //Number is the pixel distance between highest and lowest values
    DistanceDay1 = (int) ((int) 50 + ((array[IndexL] - array[0]) * ValPx));
    DistanceDay2 = (int) ((int) 50 + ((array[IndexL] - array[1]) * ValPx));
    DistanceDay3 = (int) ((int) 50 + ((array[IndexL] - array[2]) * ValPx));
    DistanceDay4 = (int) ((int) 50 + ((array[IndexL] - array[3]) * ValPx));
    DistanceDay5 = (int) ((int) 50 + ((array[IndexL] - array[4]) * ValPx));

}
public void paintComponent(Graphics g) {

    Graphics2D g2 = (Graphics2D) g;

    int DotSize = 10;

    int width = g2.getFontMetrics().stringWidth("Today");
    int middle = width / 2;

    g2.setColor(Color.BLACK);
    /* g2.drawLine(10, 10, 10, 410); //Frame Boundaries
    g2.drawLine(410, 10, 10, 10); //Frame Boundaries
    g2.drawLine(410, 10, 410, 410); //Frame Boundaries
    g2.drawLine(410, 410, 10, 410); //Frame Boundaries */

    //Axis
    g2.drawLine(30, 30, 30, 370);
    g2.drawLine(370, 370, 30, 370);

    //Points & Connections
    PlotPoints(g2, 98, DistanceDay1, DotSize);
    g2.drawLine(98, DistanceDay1, 166, DistanceDay2);
    PlotPoints(g2, 166, DistanceDay2, DotSize);
    g2.drawLine(166, DistanceDay2, 234, DistanceDay3);
    PlotPoints(g2, 234, DistanceDay3, DotSize);
    g2.drawLine(234, DistanceDay3, 302, DistanceDay4);
    PlotPoints(g2, 302, DistanceDay4, DotSize);
    g2.drawLine(302, DistanceDay4, 370, DistanceDay5);
    PlotPoints(g2, 370, DistanceDay5, DotSize);

    //Labels
    g2.drawString("Today", 370 - middle, 390);
  /*  g2.drawString("Test", 98 - middle, 40);
    g2.drawString("Test", 146, 25); */

}

private void PlotPoints(Graphics2D g, int x, int y, int r) {
    x = x - (r / 2);
    y = y - (r / 2);
    g.fillOval(x, y, r, r);
}

}

If I run the Graph class as a separate entity it'll result in this: Graph pop-up

Here's a separate version of the Graph code in which a frame will pop up displaying the graph:

package graphing;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Graphing extends JPanel {

@Override
public void paintComponent(Graphics g) {

    Graphics2D g2 = (Graphics2D) g;

    int DotSize = 10;

    int width = g2.getFontMetrics().stringWidth("Test");
    int middle = width / 2;

    g2.setColor(Color.BLACK);
    g2.drawLine(10, 10, 10, 390); //Frame Boundaries
    g2.drawLine(390, 10, 10, 10); //Frame Boundaries
    g2.drawLine(390, 10, 390, 390); //Frame Boundaries
    g2.drawLine(390, 390, 10, 390); //Frame Boundaries

    //Axis
    g2.drawLine(30, 30, 30, 370);
    g2.drawLine(370, 370, 30, 370);

    //Points & Connections
    PlotPoints(g2, 98, 55, DotSize);
    g2.drawLine(98, 55, 166, 40);
    PlotPoints(g2, 166, 40, DotSize);
    g2.drawLine(166, 40, 234, 100);
    PlotPoints(g2, 234, 100, DotSize);
    g2.drawLine(234, 100, 302, 332);
    PlotPoints(g2, 302, 332, DotSize);
    g2.drawLine(302, 332, 370, 40);
    PlotPoints(g2, 370, 40, DotSize);

    //Labels
    g2.drawString("Test", 98 - middle, 40);
    g2.drawString("Test", 146, 25);

}

private void PlotPoints(Graphics2D g, int x, int y, int r) {
    x = x - (r / 2);
    y = y - (r / 2);
    g.fillOval(x, y, r, r);
}

public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setSize(420, 420);
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    Graphing app = new Graphing();

    frame.setContentPane(app);

    frame.setVisible(true);
    frame.invalidate();
}

}

Solution

  • So, my immediate issue is, you're extending from JFrame, which isn't a good, as this locks the UI into in a single use case (it's not easily re-usable)

    My second issue is, you've created a method called paintComponent in JFrame, but since JFrame doesn't use this style of painting, it is never called

    So, the first thing I would do is change Graph so it extends from JPanel instead...

    public class Graph extends JPanel {
        //...
    

    I would then update your paintComponent so it supports the painting process properly...

    @Overrride
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        //...
    

    Now, the next problem is, you're going to need to provide some sizing hints so that the layout manager of the container you add it to has some idea about how best to layout the component...

    @Override
    public Dimension getPreferredSize() {
        // I've not been through your code in detail
        // so I've not calculated what the actual
        // preferred size might be and this is just an
        // example you'll have to update
        return new Dimension(200, 200);
    }
    

    Now, you can create an instance of Graph and add it to what ever container you want