A trendline is another denomination given to a regression line. The previous topic illustrates the use
of a linear regression line, whose slope is automatically calculated with respect to the values of a
series it is associated with.
Trendlines can also be manually drawn. A few methods are implemented in the Graph and GraphSet classes to enable manual
trendlines and specify their properties, as thickness and color.
Manual trendlines belong to GraphSet objects and are enabled with the method Graph.setTrendLinesDrawingEnabled(boolean isTrendLinesDrawingEnabled).
Trendlines belonging to distinct GraphSet objects may differ in color and thickness. To specify the color and thickness of trendlines use the methods
GraphSet.setTrendLinesColor(Color trendLinesColor) and GraphSet.setTrendLinesThickness(int trendLineThickness),
respectively.
The example below displays a candlestick series and a line series, belonging to different GraphSet objects and
stacked one above the other. To start drawing a trendline click on an area of a GraphSet and drag mouse. The trendline is
drawn while mouse is dragged. Release mouse button to permanently add the trendline.
To add more flexibility, one checkbox and one button are displayed in a top panel, the former toggling chart state between normal and a
'trendline drawing' state, and the latter removing all trendlines.
import java.awt.*; import java.awt.event.*; import javax.swing.*; import com.jinsight.jetchart.*; public class Main extends JFrame implements ActionListener { JCheckBox cb; JButton jb; Graph graph; public Main() { addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent evt) { System.exit(0); } }); JPanel topPanel=new JPanel(new FlowLayout(FlowLayout.LEFT)); cb=new JCheckBox("Draw trendlines"); cb.addActionListener(this); jb=new JButton("Remove trendlines"); jb.addActionListener(this); topPanel.add(cb); topPanel.add(jb); Container ct=getContentPane(); ct.add("North",topPanel); graph=new Graph(); // Specifies a start date to automatically display x axis labels as months. graph.setStartDate("01012003"); graph.setMonthLabelsEnabled(true); // Enables the scrolling label running on top of the primary GraphSet. graph.getScrollingLabel().setEnabled(true); graph.setTitle(new String[]{"The JetChart Library","Manually drawing trendlines"}); ct.add("Center",graph); // Creates the candlestick series. CandleStickSerie cs=new CandleStickSerie(); cs.setMultipleValues(getMultipleValues()); // Creates the line series. LineSerie ls=new LineSerie(); ls.setValues(getValues()); ls.setColor(Color.blue); ls.setMarksEnabled(false); // remove marks. graph.addSerie(cs); graph.addSerie(ls); // Creates a secondary GraphSet to which the line series is added. GraphSet graphSet=new GraphSet(); graphSet.addSerie(ls); // Adds the secondary GraphSet to the chart context. graph.addGraphSet(graphSet); // Enables the scrolling bar to help distinguish the data point the // scrolling label refers to while sliding horizontally. GraphSet primaryGraphSet=graph.getGraphSet(0); primaryGraphSet.getScrollingBar().setEnabled(true); graphSet.getScrollingBar().setEnabled(true); // Specifies the thickness and color of the trendlines to be painted // on each GraphSet object. primaryGraphSet.setTrendLinesColor(Color.blue); primaryGraphSet.setTrendLinesThickness(2); graphSet.setTrendLinesColor(Color.magenta); graphSet.setTrendLinesThickness(3); // Enables automatic scale positioning, arranging the GraphSet objects // vertically. The primary GraphSet object is always positioned at the // top of the stack. The candlestick series was not added to the // secondary GraphSet, therefore it belongs to the primary GraphSet // and is displayed above the line series. graph.setAutoScalePositioningEnabled(true); setSize(500,400); setVisible(true); } public void actionPerformed(ActionEvent evt) { if (evt.getSource()==cb) { graph.setTrendLinesDrawingEnabled(cb.isSelected()); // Changes the cursor shape to a cross if trend line drawing // is enabled. graph.setDefaultCursor(cb.isSelected() ? Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR) : Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } else { graph.removeAllTrendLines(); // A call to graph.repaint is required to refresh chart and // remove trendlines. graph.repaint(); } } private double[][] getMultipleValues() { double[][] values={{185.00,178.00,179.00,182.50},{196.00,183.50,183.95,192.90}, {196.95,189.20,194.00,190.00},{195.50,186.55,191.00,187.25}, {195.60,190.00,192.00,192.00},{207.35,190.10,191.10,207.35}, {214.00,193.10,211.25,196.15},{202.80,189.50,196.00,196.45}, {206.35,194.30,197.00,199.00},{208.00,197.00,204.00,198.10}, {205.00,182.30,199.00,182.95},{189.70,182.80,184.00,184.50}, {188.00,180.00,185.00,182.60},{184.45,173.15,184.00,174.10}, {180.00,173.00,178.00,174.25},{178.00,167.05,175.00,169.00}, {173.80,159.10,170.00,160.90},{165.50,160.00,163.00,163.75}, {173.00,161.10,163.00,163.20},{174.50,167.00,168.00,174.10}, {179.50,160.20,174.60,160.20},{163.90,154.00,160.10,161.30}, {163.20,148.40,161.95,148.40},{146.50,136.55,144.60,136.55}, {147.45,146.10,147.45,147.45},{159.20,141.50,155.10,154.00}, {153.00,142.10,153.00,143.10},{146.00,136.00,146.00,138.50}, {139.10,130.00,139.00,131.35},{137.70,125.75,134.00,128.45}, {138.25,127.00,128.50,134.90},{144.20,134.00,134.00,135.70}, {136.30,128.00,134.50,128.00},{132.50,126.30,132.00,128.85}, {139.10,129.40,129.40,139.10},{143.00,135.00,141.90,135.00}, {137.00,132.10,136.75,133.70},{139.90,130.25,137.00,131.85}, {137.50,127.00,130.95,137.40},{138.40,129.05,137.80,130.45}, {132.85,127.00,130.00,131.50},{142.00,128.00,129.15,140.40}, {151.60,140.00,141.00,151.60},{159.85,139.50,155.00,143.95}, {155.45,140.00,145.80,155.45},{163.90,150.00,161.40,154.75}, {167.10,155.90,156.50,167.10},{175.00,164.00,169.80,166.00}, {165.00,157.05,165.00,160.00},{162.00,154.20,159.00,154.80}, {154.00,143.75,154.00,145.25},{156.85,134.10,135.10,155.00}, {160.00,149.00,155.25,152.00},{156.00,144.65,153.50,148.50}, {148.00,139.00,148.00,143.85},{152.85,143.50,149.90,144.95}, {144.20,135.00,144.20,139.90},{150.75,139.90,142.00,149.00}, {149.00,140.55,149.00,142.70},{143.50,138.60,143.45,139.00}, {144.80,128.00,142.15,128.70},{131.45,124.50,128.00,129.70}, {130.25,122.60,129.00,125.85},{128.40,120.00,126.50,124.10}, {127.30,122.65,125.00,123.00},{128.95,115.50,123.00,126.95}, {128.85,120.10,127.00,120.65},{122.85,116.00,120.00,120.20}, {122.00,111.75,120.50,112.60},{118.35,108.50,118.35,111.50}, {114.40,110.25,112.00,110.50},{113.90,109.10,112.00,110.80}, {112.50,107.20,111.00,108.60},{108.50,105.75,107.35,106.20}, {107.35,95.50,105.00,96.80},{102.50,96.00,97.50,99.50}, {108.00,97.00,99.00,106.45},{115.50,106.75,106.90,114.40}, {126.00,113.00,114.00,125.50},{130.00,123.00,128.40,124.00}, {125.00,118.50,125.00,120.90},{123.85,112.20,122.00,113.50}, {113.20,103.00,112.25,109.20},{112.00,107.00,107.00,110.70}, {117.95,112.60,113.00,113.05},{114.35,110.00,114.00,112.00}, {114.45,111.20,111.70,112.30},{118.00,112.20,113.00,117.15}, {122.20,116.50,118.00,117.65},{123.40,118.55,120.00,119.65}, {122.00,118.30,119.00,120.30},{126.80,120.50,120.50,123.10}, {124.80,121.15,123.30,121.60},{123.00,119.10,121.50,122.70}, {126.70,121.50,124.95,122.50},{125.00,118.00,123.90,119.55}, {120.80,115.50,119.90,115.90},{117.30,114.00,116.40,116.80}, {119.50,115.10,116.00,116.00},{117.75,114.00,114.60,116.20}, {121.00,116.00,116.60,118.15},{120.00,117.30,118.85,117.95}, {123.50,118.20,118.75,122.00},{122.80,117.50,122.10,117.95}, {125.00,118.60,120.00,120.70},{128.00,120.75,121.10,127.00}, {133.25,127.00,127.75,127.30},{128.70,124.80,126.15,125.20}, {131.25,125.00,125.90,129.45},{134.40,128.70,131.80,129.85}, {132.15,128.00,130.40,130.35},{136.80,130.05,130.90,136.15}, {138.40,132.00,136.90,132.25},{135.85,130.60,133.00,134.00}, {139.90,134.50,136.00,139.30},{140.90,136.40,139.00,137.55}, {137.50,129.55,136.50,132.10},{133.60,123.05,132.30,126.10}, {128.50,120.60,127.20,121.35},{120.00,107.00,117.00,110.10}, {117.40,106.10,109.00,114.85},{119.00,106.25,116.00,107.45}, {109.80,103.00,106.20,107.85},{109.50,104.35,107.50,106.50}, {110.05,105.10,105.10,108.00},{115.40,104.00,107.35,113.05}, {118.85,110.10,112.50,116.70},{119.40,112.25,117.50,112.80}, {116.00,111.55,113.70,114.65},{115.75,107.50,114.40,109.05}, {115.90,106.15,109.70,115.20},{119.50,115.50,115.90,117.40}, {117.90,114.00,117.00,115.95},{121.00,113.25,115.00,120.65}, {126.00,119.75,121.25,125.00},{126.90,120.10,126.00,121.45}, {121.30,112.20,121.00,113.15},{115.25,113.05,113.90,113.95}, {117.00,114.10,115.50,115.70},{117.80,115.20,115.95,116.40}, {119.80,116.00,116.25,116.65},{117.70,113.00,117.40,116.10}, {124.80,115.00,116.50,121.80},{128.10,122.10,123.25,124.70}, {126.50,122.70,124.10,124.20},{125.45,121.60,125.00,123.30}, {126.75,122.50,123.80,124.50},{127.50,122.10,126.00,123.55}, {125.50,121.35,122.30,121.55},{121.20,117.55,121.20,118.40}}; return values; } private double[] getValues() { double[] values={131.90,132.80,130.50,131.00,136.75,135.00,131.50,130.50, 132.40,133.30,130.90,123.40,122.25,118.00,120.00,116.10, 115.00,103.45,107.50,103.80,99.00,96.75,94.00,95.90,97.50, 98.40,100.20,102.00,110.40,104.50,108.70,107.75,107.45, 103.00,100.90,99.25,93.80,99.25,103.00,100.25,102.70, 107.15,106.00,107.15,109.00,104.00,96.50,97.95,99.70, 97.70,91.00,87.45,86.80,88.60,85.40,85.90,84.85, 76.55, 68.00,67.45,61.90,60.90,60.75,53.60,58.50, 57.20,51.25,48.50,45.75,46.90,52.55,51.40,54.00, 51.70,41.20,38.75,34.00,33.50,33.25,34.25,33.90, 30.00,33.50,34.95,31.45,26.95,28.40,30.90,28.90, 29.90,29.80,33.25,34.50,34.00,36.90,37.00,36.40, 34.70,37.50,38.30,39.40,43.50,45.80,48.70,46.45, 47.85,49.40,54.90,55.50,56.95,58.75,61.80,58.50, 59.90,61.20,65.50,67.50,66.75,65.45,66.50,68.10, 64.80,57.70,59.80,57.80,57.00,55.25,61.30,66.90, 66.00,61.00,57.90,59.50,55.90,55.75,56.00,59.40, 58.85,55.40,50.05,49.50,49.80,59.00,57.40,60.00, 68.50,73.60,77.50,80.90,79.90}; return values; } public static void main(String[] args) { new Main(); } }