PDA

View Full Version : سوال: خطای گرفتن مقادیر x از نمودار در هنگام حرکت موس



hamed.re
چهارشنبه 03 خرداد 1402, 18:48 عصر
سلام یه برنامه دارم که اطلاعات رو روی نمودار نمایش میده قسمت Y عدد و قسمت X تاریخ شمسی هست. وقتی اطلاعات X رو به صورت String وارد نمودار میکنم شکل نمودار درست ولی نمیتونم مقدارشو موقع حرکت موس بدست بیارم چون نوعش String از طرف دیگه وقتی وقتی اطلاعات X رو به صورت DateTime وارد نمودار میکنم شکل نمودار به هم میریزه و به اصطلاح کشیده میشه. دیگه نمیدونم چیکار کنم خواهشا اگر کسی اطلاعی داره بگه چیکار کنم. در ضمن نمودار هم MSChart هست.
private void chart1_MouseMove(object sender, MouseEventArgs e) {
if (ismiddlebuttonclick)
{
label_VE.Visible = true;
label_HO.Visible = true;
label_VAL.Visible = true;


label_HO.Location = new Point(76, e.Y);
label_VE.Location = new Point(e.X, 21);


if (e.X <= 83 || e.Y >= 435 || e.Y <= 27 || e.X >= 852)
{
label_VE.Visible = false;
label_HO.Visible = false;
label_VAL.Visible = false;
}
else
{
label_VE.Visible = true;
label_HO.Visible = true;
label_VAL.Visible = true;
}


try
{
double yValue = chart1.ChartAreas[0].AxisY.PixelPositionToValue(e.Y);
double xPixel = chart1.ChartAreas[0].AxisX.ValueToPixelPosition(chart1.ChartAreas[0].AxisX.PixelPositionToValue(e.X));
double xValue = chart1.ChartAreas[0].AxisX.PixelPositionToValue(xPixel);

label_VAL.Text = string.Concat(Math.Round(yValue, 1).ToString(), " , ", xValue.ToString());
label_VAL.Location = new Point(863, e.Y - 5);
}
catch (Exception ex)
{
MessageBox.Show("خطا در نشانگر" + ex.Message, "خطا", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
else
{
label_VE.Visible = false;
label_HO.Visible = false;
label_VAL.Visible = false;
return;
}




}

پرستو پارسایی
پنج شنبه 04 خرداد 1402, 21:59 عصر
سلام یه برنامه دارم که اطلاعات رو روی نمودار نمایش میده قسمت Y عدد و قسمت X تاریخ شمسی هست. وقتی اطلاعات X رو به صورت String وارد نمودار میکنم شکل نمودار درست ولی نمیتونم مقدارشو موقع حرکت موس بدست بیارم چون نوعش String از طرف دیگه وقتی وقتی اطلاعات X رو به صورت DateTime وارد نمودار میکنم شکل نمودار به هم میریزه و به اصطلاح کشیده میشه. دیگه نمیدونم چیکار کنم خواهشا اگر کسی اطلاعی داره بگه چیکار کنم. در ضمن نمودار هم MSChart هست.


در مورد مشکلی که در نمودار خود دارید، دلیل آن ممکن است این باشد که شما مقدار X را به عنوان یک رشته String به نمودار می‌دهید در حالی که محور X باید به عنوان یک محور زمانی (DateTime) تعریف شود. به همین دلیل، شکل نمودار شما به هم می‌ریزد. برای رفع احتمالی مشکل در پروژه شما این کد را تست نمائید.
private void chart1_MouseMove(object sender, MouseEventArgs e)
{
if (ismiddlebuttonclick)
{
label_VE.Visible = true;
label_HO.Visible = true;
label_VAL.Visible = true;


label_HO.Location = new Point(76, e.Y);
label_VE.Location = new Point(e.X, 21);


if (e.X <= 83 || e.Y >= 435 || e.Y <= 27 || e.X >= 852)
{
label_VE.Visible = false;
label_HO.Visible = false;
label_VAL.Visible = false;
}
else
{
label_VE.Visible = true;
label_HO.Visible = true;
label_VAL.Visible = true;
}


try
{
double yValue = chart1.ChartAreas[0].AxisY.PixelPositionToValue(e.Y);
string xString = chart1.Series[0].Points[(int)Math.Round(chart1.ChartAreas[0].AxisX.PixelPositionToValue(e.X))].AxisLabel;
DateTime xValue = DateTime.ParseExact(xString, "yyyy-MM-dd", CultureInfo.InvariantCulture);
chart1.Series[0].Points.AddXY(xValue, yValue);
label_VAL.Text = string.Concat(Math.Round(yValue, 1).ToString(), " , ", xValue.ToString());
label_VAL.Location = new Point(863, e.Y - 5);
}
catch (Exception ex)
{
MessageBox.Show("خطا در نشانگر: " + ex.Message, "خطا", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
else
{
label_VE.Visible = false;
label_HO.Visible = false;
label_VAL.Visible = false;
return;
}
}

hamed.re
شنبه 06 خرداد 1402, 17:02 عصر
در مورد مشکلی که در نمودار خود دارید، دلیل آن ممکن است این باشد که شما مقدار X را به عنوان یک رشته String به نمودار می‌دهید در حالی که محور X باید به عنوان یک محور زمانی (DateTime) تعریف شود. به همین دلیل، شکل نمودار شما به هم می‌ریزد. برای رفع احتمالی مشکل در پروژه شما این کد را تست نمائید.

private void chart1_MouseMove(object sender, MouseEventArgs e)
{
if (ismiddlebuttonclick)
{
label_VE.Visible = true;
label_HO.Visible = true;
label_VAL.Visible = true;


label_HO.Location = new Point(76, e.Y);
label_VE.Location = new Point(e.X, 21);


if (e.X <= 83 || e.Y >= 435 || e.Y <= 27 || e.X >= 852)
{
label_VE.Visible = false;
label_HO.Visible = false;
label_VAL.Visible = false;
}
else
{
label_VE.Visible = true;
label_HO.Visible = true;
label_VAL.Visible = true;
}


try
{
double yValue = chart1.ChartAreas[0].AxisY.PixelPositionToValue(e.Y);
string xString = chart1.Series[0].Points[(int)Math.Round(chart1.ChartAreas[0].AxisX.PixelPositionToValue(e.X))].AxisLabel;
DateTime xValue = DateTime.ParseExact(xString, "yyyy-MM-dd", CultureInfo.InvariantCulture);
chart1.Series[0].Points.AddXY(xValue, yValue);
label_VAL.Text = string.Concat(Math.Round(yValue, 1).ToString(), " , ", xValue.ToString());
label_VAL.Location = new Point(863, e.Y - 5);
}
catch (Exception ex)
{
MessageBox.Show("خطا در نشانگر: " + ex.Message, "خطا", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
else
{
label_VE.Visible = false;
label_HO.Visible = false;
label_VAL.Visible = false;
return;
}
}





ممنون از پاسخگویی شما ولی من داخل متد دیگه ای اطلاعات رو به نمودار فرستادم و درست هم فرستادم مشکل من اینه که اگر اطلاعات یه صورت String باشه شکل نمودار درسته ولی اگه بصورت DateTime باشه نمودار به هم میریزه


private void Draw_chart()
{
try
{
foreach (DataGridViewColumn column in dataGridView1.Columns)
{
column.SortMode = DataGridViewColumnSortMode.NotSortable;
}


double xmax = chart1.ChartAreas["ChartArea1"].AxisX.Maximum;


foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.Cells[1].Value != null)
{
string a = row.Cells[1].Value.ToString();
string xValue = row.Cells[0].Value.ToString();
//xValue = xValue.Replace("/", "");
string yValue = row.Cells[2].Value.ToString();


string[] dateParts = xValue.Split('/');
int year = int.Parse(dateParts[0]);
int month = int.Parse(dateParts[1]);
int day = int.Parse(dateParts[2]);


PersianCalendar pc = new PersianCalendar();
DateTime date = pc.ToDateTime(year, month, day, 0, 0, 0, 0);
//double x = date.ToOADate();


string a1 = "ورود نقدینگی";
string a2 = "خروج نقدینگی";


if (a == a1)
{
chart1.Series["ورود نقدینگی"].Points.AddXY(date, yValue);
}
if (a == a2)
{
chart1.Series["خروج نقدینگی"].Points.AddXY(date, yValue);
}
}
}


chart1.ChartAreas["ChartArea1"].AxisX.ScaleView.Zoom(0, xmax);
}
catch (Exception ex)
{
MessageBox.Show("خطا در هنگام کشیدن نمودار" + ex.Message, "خطا", MessageBoxButtons.OK, MessageBoxIcon.Error);
this.Close();
return;
}
}

پرستو پارسایی
شنبه 06 خرداد 1402, 20:15 عصر
private void DrawChart(){
try
{
foreach (DataGridViewColumn column in dataGridView1.Columns)
{
column.SortMode = DataGridViewColumnSortMode.NotSortable;
}


double xmax = chart1.ChartAreas["ChartArea1"].AxisX.Maximum;


foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.Cells[1].Value != null)
{
string a = row.Cells[1].Value.ToString();
DateTime date = DateTime.Parse(row.Cells[0].Value.ToString());
double x = date.ToOADate(); // تبدیل تاریخ به عددی قابل استفاده در نمودار
string yValue = row.Cells[2].Value.ToString();


// افزودن داده‌ها به سری‌های مربوطه در نمودار
if (a == "ورود نقدینگی")
{
chart1.Series["ورود نقدینگی"].Points.AddXY(x, yValue);
}
if (a == "خروج نقدینگی")
{
chart1.Series["خروج نقدینگی"].Points.AddXY(x, yValue);
}
}
}


// اعمال زوم بر روی محور افقی نمودار
chart1.ChartAreas["ChartArea1"].AxisX.ScaleView.Zoom(0, xmax);
}
catch (Exception ex)
{
MessageBox.Show("خطا در هنگام کشیدن نمودار" + ex.Message, "خطا", MessageBoxButtons.OK, MessageBoxIcon.Error);
this.Close();
return;
}
}

تست بفرمائید

hamed.re
یک شنبه 07 خرداد 1402, 17:56 عصر
private void DrawChart(){
try
{
foreach (DataGridViewColumn column in dataGridView1.Columns)
{
column.SortMode = DataGridViewColumnSortMode.NotSortable;
}


double xmax = chart1.ChartAreas["ChartArea1"].AxisX.Maximum;


foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.Cells[1].Value != null)
{
string a = row.Cells[1].Value.ToString();
DateTime date = DateTime.Parse(row.Cells[0].Value.ToString());
double x = date.ToOADate(); // تبدیل تاریخ به عددی قابل استفاده در نمودار
string yValue = row.Cells[2].Value.ToString();


// افزودن داده‌ها به سری‌های مربوطه در نمودار
if (a == "ورود نقدینگی")
{
chart1.Series["ورود نقدینگی"].Points.AddXY(x, yValue);
}
if (a == "خروج نقدینگی")
{
chart1.Series["خروج نقدینگی"].Points.AddXY(x, yValue);
}
}
}


// اعمال زوم بر روی محور افقی نمودار
chart1.ChartAreas["ChartArea1"].AxisX.ScaleView.Zoom(0, xmax);
}
catch (Exception ex)
{
MessageBox.Show("خطا در هنگام کشیدن نمودار" + ex.Message, "خطا", MessageBoxButtons.OK, MessageBoxIcon.Error);
this.Close();
return;
}
}

تست بفرمائید

متاسفانه این روش تست شده و الان هم با کد شما تست کردم ولی شکل نمودار به هم میریزه. روش دیگه ای به نظرتون میرسه؟

پرستو پارسایی
یک شنبه 07 خرداد 1402, 23:54 عصر
می‌توانم یک کد با استفاده از روش Data Binding برای رسم نمودار پیشنهاد دهم که با روش شما متفاوت هست :



private void BindDataToChart()
{
// تعریف منبع داده
DataTable dt = new DataTable();
dt.Columns.Add("Date", typeof(DateTime));
dt.Columns.Add("Type", typeof(string));
dt.Columns.Add("Value", typeof(double));
dt.Rows.Add(DateTime.Parse("2022-01-01"), "ورود نقدینگی", 5000);
dt.Rows.Add(DateTime.Parse("2022-01-02"), "ورود نقدینگی", 2000);
dt.Rows.Add(DateTime.Parse("2022-01-03"), "خروج نقدینگی", 1000);
dt.Rows.Add(DateTime.Parse("2022-01-04"), "ورود نقدینگی", 3000);
dt.Rows.Add(DateTime.Parse("2022-01-05"), "خروج نقدینگی", 500);
dt.Rows.Add(DateTime.Parse("2022-01-06"), "خروج نقدینگی", 1000);


// تنظیم منبع داده برای نمودار
chart1.DataSource = dt;


// تعریف ناحیه نمودار
ChartArea chartArea1 = new ChartArea("ChartArea1");
chart1.ChartAreas.Add(chartArea1);


// تعریف سری‌ها برای هر نوع داده
Series seriesIn = new Series("ورود نقدینگی");
Series seriesOut = new Series("خروج نقدینگی");


// تنظیم نقاط داده برای هر سری
seriesIn.Points.DataBindXY(dt.Select("Type = 'ورود نقدینگی'"), "Date", "Value");
seriesOut.Points.DataBindXY(dt.Select("Type = 'خروج نقدینگی'"), "Date", "Value");


// افزودن سری‌ها به نمودار
chart1.Series.Add(seriesIn);
chart1.Series.Add(seriesOut);


// فرمت بندی نمودار
chartArea1.AxisX.LabelStyle.Format = "dd/MM/yyyy";
chartArea1.AxisX.Interval = 1;
chartArea1.AxisY.LabelStyle.Format = "{0:C0}";
}

در این کد، ابتدا یک DataTable به عنوان منبع داده تعریف شده و برای آن چندین سطر داده افزوده شده است. سپس منبع داده برای نمودار تنظیم شده و سه بخش اصلی نمودار (Chart Area و Series) تعریف شده است. در نهایت، داده‌های مربوط به هر نوع از داده‌ها (ورود و خروج نقدینگی) از جدول داده به صورت مستقیم به نمودار منتقل شده و سپس نمودار با استفاده از تنظیمات مختلف به صورت نهایی فرمت بندی می‌شود . تست بفرمائید اگر مشکلی بود مطرح کنید

hamed.re
دوشنبه 08 خرداد 1402, 15:39 عصر
می‌توانم یک کد با استفاده از روش Data Binding برای رسم نمودار پیشنهاد دهم که با روش شما متفاوت هست :



private void BindDataToChart()
{
// تعریف منبع داده
DataTable dt = new DataTable();
dt.Columns.Add("Date", typeof(DateTime));
dt.Columns.Add("Type", typeof(string));
dt.Columns.Add("Value", typeof(double));
dt.Rows.Add(DateTime.Parse("2022-01-01"), "ورود نقدینگی", 5000);
dt.Rows.Add(DateTime.Parse("2022-01-02"), "ورود نقدینگی", 2000);
dt.Rows.Add(DateTime.Parse("2022-01-03"), "خروج نقدینگی", 1000);
dt.Rows.Add(DateTime.Parse("2022-01-04"), "ورود نقدینگی", 3000);
dt.Rows.Add(DateTime.Parse("2022-01-05"), "خروج نقدینگی", 500);
dt.Rows.Add(DateTime.Parse("2022-01-06"), "خروج نقدینگی", 1000);


// تنظیم منبع داده برای نمودار
chart1.DataSource = dt;


// تعریف ناحیه نمودار
ChartArea chartArea1 = new ChartArea("ChartArea1");
chart1.ChartAreas.Add(chartArea1);


// تعریف سری‌ها برای هر نوع داده
Series seriesIn = new Series("ورود نقدینگی");
Series seriesOut = new Series("خروج نقدینگی");


// تنظیم نقاط داده برای هر سری
seriesIn.Points.DataBindXY(dt.Select("Type = 'ورود نقدینگی'"), "Date", "Value");
seriesOut.Points.DataBindXY(dt.Select("Type = 'خروج نقدینگی'"), "Date", "Value");


// افزودن سری‌ها به نمودار
chart1.Series.Add(seriesIn);
chart1.Series.Add(seriesOut);


// فرمت بندی نمودار
chartArea1.AxisX.LabelStyle.Format = "dd/MM/yyyy";
chartArea1.AxisX.Interval = 1;
chartArea1.AxisY.LabelStyle.Format = "{0:C0}";
}

در این کد، ابتدا یک DataTable به عنوان منبع داده تعریف شده و برای آن چندین سطر داده افزوده شده است. سپس منبع داده برای نمودار تنظیم شده و سه بخش اصلی نمودار (Chart Area و Series) تعریف شده است. در نهایت، داده‌های مربوط به هر نوع از داده‌ها (ورود و خروج نقدینگی) از جدول داده به صورت مستقیم به نمودار منتقل شده و سپس نمودار با استفاده از تنظیمات مختلف به صورت نهایی فرمت بندی می‌شود . تست بفرمائید اگر مشکلی بود مطرح کنید

متاسفانه این کد هم عمل نمیکنه قبلا مستقیما از خود دیتابیس هم اطلاعات رو لود کردم داخل نمودار ولی باز هم همون مشکل