5

I am trying to create a graph that will show the progress of a workout. Every five button clicks a tick should be added to the graph. This is a example of how it should look.

1

For demonstration purposes I am using a button click, In production the clicks will be every twenty revolutions of a wheel.

    private int counter = 0;
    private void button1_Click(object sender, EventArgs e)
    {
        counter++;
        // code will go here
    }

Thanks in advance

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
user973671
  • 1,620
  • 6
  • 27
  • 39
  • 2
    So you are looking for the `//code will go here`? ;) Have you managed to built your barchart at all? [Here is a sample in ASP.NET for getting an idea](http://www.codeproject.com/Articles/8760/Generating-Bar-Chart-in-ASP-NET) – bonCodigo Dec 22 '12 at 15:30
  • yes, or any ideas of how it should work, tutorials, etc. Thanks – user973671 Dec 22 '12 at 15:32
  • No, I am trying to think of what would be best to use. I could use the .net chart or possibly make a custom chart. – user973671 Dec 22 '12 at 15:36
  • 2
    And you may also use `shapes` in a `winform` using `paint` method to [draw the desired shape](http://www.codeproject.com/Articles/11208/NET-Shape-Control). Another post that could help you on [drawing charts in C#](http://stackoverflow.com/questions/1248135/c-paint-own-bar-chart). You could go ahead with `MS Charts` but `paint()` seems to much easier. – bonCodigo Dec 22 '12 at 15:37
  • The examples you gave are good, but I need help getting the graph to add a tick every five clicks. Thanks – user973671 Dec 22 '12 at 16:16
  • Why do you have asp.net AND winforms as tags? – Steve Wellens Dec 22 '12 at 16:23
  • Because it is going in a winforms application. – user973671 Dec 22 '12 at 16:28
  • @user973671 validating every five tick as 1 can be done within your button click event. e.g. `counter/5 = 1` you may call the paint method to draw a square from earlier position to the new position. Keep track of the positions for next use. – bonCodigo Dec 22 '12 at 16:33
  • 1
    @user973671 "Because it is going in a winforms application" OK, I removed the asp.net tag. – Steve Wellens Dec 22 '12 at 16:36
  • 1
    Before worrying about adding a tick mark, you should begin with having a chart at all (be it a custom control or a standard control). – Olivier Jacot-Descombes Dec 22 '12 at 16:42

3 Answers3

3

You can use either a Bitmap Buffer or a panel to draw on. Here is a headstart: Just a sample. reference.

This solution is based on WinForms & Panel_Paint(). You may try to add vertical Progress Label and Chart's Y Axis value labeling.

Code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1(){
            InitializeComponent();
        }

        private int counter = 0;
        private int px = 10;
        private int py = 180;
        private int total5Clicks = 0;

        private void button1_Click(object sender, EventArgs e)
        {
            counter++;
            label1.Text = "Total Clicks = " + counter.ToString();
            if (Math.Abs(counter % 5) == 0){
                if (Math.Abs(counter / 5) > 0){
                    total5Clicks = total5Clicks + 1;
                    PaintOnChartPanel(total5Clicks);}
             }
         }

      private void panel1_Paint(object sender, PaintEventArgs e){           
      }

      private void PaintOnChartPanel(int total5Times)
      {            
        //Add a new Panel Paint EventHandler
        panel1.Paint += new PaintEventHandler(panel1_Paint);

        using (Graphics g = this.panel1.CreateGraphics())
        {
            Brush brush = new SolidBrush(Color.Green);
            g.FillRectangle(brush, px, py, 20, 20);                           
            Pen pen = new Pen(new SolidBrush(Color.White));
            g.DrawRectangle(pen, px, py, 20, 20);                    

            //add each total5Click into chart block
            g.DrawString((total5Times).ToString(), new Font("Arial", 7), 
            new SolidBrush(Color.AntiqueWhite),
            px + 1, py+8, StringFormat.GenericDefault);
            pen.Dispose();}

            if (py > 20){
                py = py - 20;}
            else{
                MessageBox.Show("Reached Top of the Panel");
                if (px < 200){
                    px = px + 20;
                    py = 180;}
                else{
                    MessageBox.Show("Reached Right of the Panel");
                }
            }
        }
    }
}

Output Form:

enter image description here

bonCodigo
  • 14,268
  • 1
  • 48
  • 91
  • @user973671 Please give this code a go. It adds each square block from `Bottm to Top` as you would do it in a usual Bar Chart :) not Top to Bottom... Happy to explain the code if you have further questions. – bonCodigo Dec 22 '12 at 20:37
  • This is perfect, exactly what I needed,I appreciate your help. There were a lot of good answers, but I am marking this one because it was the most complete, Thanks – user973671 Dec 22 '12 at 22:04
  • @user973671 glad you got it worked :) please provide any further comments to improve the code or if you have more questions. – bonCodigo Dec 22 '12 at 22:07
1

You can determine if you have a multiple of five with

bool drawTickMark = clicks % 5 == 0;

% is the modulo operator which returns the remainder of an integer division. E.g. 13 % 5 = 3 and 13 / 5 = 2 because 2 * 5 + 3 = 13.

clicks % 5 will be zero for clicks = 0, 5, 10, 15, ...

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
1

I'm not much of an ASP.NET guy but here's an algorithm you can use to draw the squares

        int perColumn = Height / squareSize;
        int totalColumns = (squareCount / perColumn) + 1;

        for (int y = 0; y <= totalColumns - 1; y++)
        {
            int itemCount = squareCount - (y * perColumn);
            if (itemCount > perColumn)
                itemCount = perColumn;

            for (int x = 0; x <= itemCount - 1; x++)
                e.Graphics.FillRectangle(RandomBrush, New Rectangle((column * SquareSize) + 3, (i * SquareSize) + 3, SquareSize - 2, SquareSize - 2))

enter image description here

public sealed class ClickGraph : Control
{
    private int squareCount = 1;
    public int SquareCount
    {
        get
        {
            return squareCount;
        }
        set
        {
            squareCount = value;
            Invalidate();
        }
    }

    private int squareSize = 25;
    public int SquareSize
    {
        get
        {
            return squareSize;
        }
        set
        {
            squareSize = value;
            Invalidate();
        }
    }

    public ClickGraph()
    {
        SetStyle(ControlStyles.ResizeRedraw, true);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        e.Graphics.Clear(BackColor);

        int perColumn = Height / squareSize;
        int totalColumns = (squareCount / perColumn) + 1;

        for (int y = 0; y <= totalColumns - 1; y++)
        {
            int itemCount = squareCount - (y * perColumn);
            if (itemCount > perColumn)
                itemCount = perColumn;

            for (int x = 0; x <= itemCount - 1; x++)
                e.Graphics.FillRectangle(RandomBrush, New Rectangle((column * SquareSize) + 3, (i * SquareSize) + 3, SquareSize - 2, SquareSize - 2))

        }
    }

}
Caster Troy
  • 2,796
  • 2
  • 25
  • 45