您的位置:首页 > 编程语言 > C#

C#Windows窗体界面设计_攻击决策项目_03_数据绘图_01_绘制坐标轴_修订ParamsForm

2013-10-25 15:43 771 查看
Author: binzhouweichao@163.com

Copyright (c) 2013, Liu Xiaojian@BIT,  All Rights Reserved.

Date: 2013-10-23
声明:本程序供参考;允许二次开发,但不允许在毫无更改的情况下占为己有。

沿用前面的序号。

7. 绘制坐标轴

pictrueBox1的横纵大小为610*610。

实际的雷区大小,为中心结点到雷结点的距离(Communication Range),加上各雷点的探测距离(Detection Range),然后再乘以2。

也就是说,确定了通信距离和探测距离后,实际的雷区宽高Width和Height就已经确定了。所以,修订ParamsForm中,关于雷区宽高的限制。

打开ParamsForm.cs[设计]文件,将雷点的TextBox和雷区的宽高的TextBox的ReadOnly属性设置为True。



7.1 设置ParamsForm的通信距离和检测距离的TextBox的回车事件

这两个文本框,按回车时触发下方的仿真场景的宽高变化。

7.1.1 首先,设置这两个文本框只能输入数字

自定义一个判断只能输入数字的函数。为了在其他地方也能使用这个函数,我们为项目添加一个新类,用于定义存放这些自定义函数。

为项目AttackDecision添加一个新类,命名为MyFunctions.cs。

为了方便调用,将类声明为静态类。即在类前加static修饰符。

为此类添加第一个静态成员方法,用于限定TextBox输入文本只能是数字,命名为NumberOnly。入口形参为KeyPressEventArgs类型,所以需要在文件头添加包含这个类的库,即using System.Windows.Forms;

函数体参考:http://wenku.baidu.com/view/be25fb300b4c2e3f57276345.html

修改后的MyFunctions.cs如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace AttackDecision
{
static class MyFunctions
{
//7.1.1 限定TextBox只能输入数字,还包含退格和回车
public static void NumberOnly(ref KeyPressEventArgs e)
{
if ((e.KeyChar < 48 || e.KeyChar > 57) && (e.KeyChar != 13) && (e.KeyChar != 8))//数字0-9的ASCII码的范围,13为回车,8为退格
{ e.Handled = true; }
else
{ e.Handled = false; }
}
}
}


7.1.2 设置Communication Range文本框的KeyPress事件

选中CommunicationRange的TextBox,在右下方属性窗口中,选择事件属性,找到KeyPress事件,双击,自动生成mineCommunicationTextBox_KeyPress()事件函数,自动关联此文本框的回车按键触发事件。添加:

//7.1.2 通信距离文本框回车事件
private void mineCommunicationTextBox_KeyPress(object sender, KeyPressEventArgs e)
{
MyFunctions.NumberOnly(ref e);//判断输入是否为数字(包括退格和回车)
if (e.KeyChar == 13)//按回车执行下面的文本变换
{
if (mineCommunicationTextBox.Text != "")//前提是此文本非空
{
//仿真场景宽度为(通信距离+探测距离)*2
simulationWidthTextBox.Text = (2 * (int.Parse(mineCommunicationTextBox.Text) + int.Parse(mineDetectionTextBox.Text))).ToString();
//仿真场景高度与宽度相同
simulationHeightTextBox.Text = simulationWidthTextBox.Text;
}
}
}


这样,此文本框只能输入数字(包含退格和回车),在点击回车之后,如果此文本非空,则使得下面的仿真场景的宽高值跟随变化。

7.1.3 同理,设置DetectionRange文本框的回车事件

//7.1.3 检测距离文本框的回车事件
private void mineDetectionTextBox_KeyPress(object sender, KeyPressEventArgs e)
{
MyFunctions.NumberOnly(ref e);//判断输入是否为数字(包括退格和回车)
if (e.KeyChar == 13)//按回车执行下面的文本变换
{
if (mineDetectionTextBox.Text != "")//前提是此文本非空
{
//仿真场景宽度为(通信距离+探测距离)*2
simulationWidthTextBox.Text = (2 * (int.Parse(mineCommunicationTextBox.Text) + int.Parse(mineDetectionTextBox.Text))).ToString();
//仿真场景高度与宽度相同
simulationHeightTextBox.Text = simulationWidthTextBox.Text;
}
}
}


7.1.4 顺便,设置一下AttackRange的文本框的KeyPress事件,只能输入数字

//7.1.4 攻击距离文本框限定只能为数字
private void mineAttackTextBox_KeyPress(object sender, KeyPressEventArgs e)
{
MyFunctions.NumberOnly(ref e);//判断输入是否为数字(包括退格和回车)
}


7.1.5 再顺便,修订一下OK按钮

当上述三个文本框中,有一个文本框的内容为空时,OK按钮失效。

当上述三个文本框未做修改时,OK按钮默认失效。

当上述三个文本框中,有任意一个做出修改时,OK按钮生效。

这样,首先设置OK按钮的默认属性Enabled为False。

打开ParamsForm.cs[设计]文件,选中OK按钮,在右侧的属性中,将Enabled的值改为False。

然后,再在上述三个TextBox的TextChanged事件函数中,添加判决OK按钮是否生效的语句。

//7.1.5 判决OK按钮是否生效
private void mineCommunicationTextBox_TextChanged(object sender, EventArgs e)
{
if ((mineCommunicationTextBox.Text != "") && (mineDetectionTextBox.Text != "") && (mineAttackTextBox.Text != ""))
{ paramsSettingOkButton.Enabled = true; }//如果三个文本框均非空,使能OK按钮
else { paramsSettingOkButton.Enabled = false; }//否则,禁用OK按钮
}
//同上
private void mineDetectionTextBox_TextChanged(object sender, EventArgs e)
{
if ((mineCommunicationTextBox.Text != "") && (mineDetectionTextBox.Text != "") && (mineAttackTextBox.Text != ""))
{ paramsSettingOkButton.Enabled = true; }//如果三个文本框均非空,使能OK按钮
else { paramsSettingOkButton.Enabled = false; }//否则,禁用OK按钮
}
//同上
private void mineAttackTextBox_TextChanged(object sender, EventArgs e)
{
if ((mineCommunicationTextBox.Text != "") && (mineDetectionTextBox.Text != "") && (mineAttackTextBox.Text != ""))
{ paramsSettingOkButton.Enabled = true; }//如果三个文本框均非空,使能OK按钮
else { paramsSettingOkButton.Enabled = false; }//否则,禁用OK按钮
}


后面的运算中需要用到仿真场景的宽高Text,为了防止在更改上述三个文本框后为按回车修改仿真场景的值,直接按了OK按钮,需要在OK按钮的Click事件函数中,重新设置一下仿真场景的宽高值,并将OK按钮禁用

        //4.2 OK按钮功能
        private void paramsSettingOkButton_Click(object sender, EventArgs e)
        {
            this.Hide();//隐藏当前窗体
            GlobalVars.mainForm.paramsSettingEnabled = true;//使能菜单Params Setting

            //7.1.5 重新设置一下仿真场景的宽高值
            if(simulationWidthTextBox.Text != (2 * (int.Parse(mineCommunicationTextBox.Text) + int.Parse(mineDetectionTextBox.Text))).ToString())
            {
                simulationWidthTextBox.Text = (2 * (int.Parse(mineCommunicationTextBox.Text) + int.Parse(mineDetectionTextBox.Text))).ToString();
                simulationHeightTextBox.Text = simulationWidthTextBox.Text;
            }
            //7.1.5 禁用OK按钮
            paramsSettingOkButton.Enabled = false;
        }


7.2 设置坐标轴数据变量

在GlobalVars类中,设置绘制坐标轴使用的数据变量:

一个是绘图变量Bitmap bAxis,另一个是放大倍数float scaleTimes。

7.2.1 需要在GlobalVars.cs中,添加文件头using Drawings;。

//7.2.1 坐标轴全局变量
//坐标轴BMP变量
private static Bitmap baxis;
public static Bitmap bAxis
{
set { baxis = value; }
get { return baxis; }
}
//放大倍数
private static float scaletimes;
public static float scaleTimes
{
set { scaletimes = value; }
get { return scaletimes; }
}


7.2.2 自定义生成坐标轴BMP的函数

在MyFunctions.cs中,添加生成坐标轴BMP的函数,命名为CreateBAxis。

首先需要开放ParamsForm的仿真场景宽高TextBox的Text变量。

在ParamsForm.cs中,在构造函数下方添加开放部分私有控件属性:

//开放部分私有控件属性
//7.2.2 开放仿真场景宽高属性,只读
public string simulationWidth
{
get { return simulationWidthTextBox.Text; }
}
public string simulationHeight
{
get { return simulationHeightTextBox.Text; }
}


其次,开放MainForm的pictureBox1的宽高属性。

在MainForm.cs中,在构造函数下方添加开放PictureBox1的宽高的只读属性:

//7.2.2 开放pictureBox1的宽高只读属性
public int pictureWidth
{
get { return pictureBox1.Width; }
}
public int pictureHeight
{
get { return pictureBox1.Height; }
}


回到MyFunctions.cs的CreateBAxis,因为用到绘图类,所以与GlobalVars相似,添加头文件using System.Drawing;。

        //7.2.2 生成坐标轴BMP
        public static void CreateBAxis()
        {
            //初始化坐标轴BMP实例,宽高为仿真场景的宽高
            GlobalVars.bAxis = new Bitmap(GlobalVars.mainForm.pictureWidth, GlobalVars.mainForm.pictureHeight);
            //放大倍数
            GlobalVars.scaleTimes = (float)GlobalVars.mainForm.pictureWidth / int.Parse(GlobalVars.mainForm.paramsForm.simulationWidth); 
            //设置画板
            Graphics gBAxis = Graphics.FromImage(GlobalVars.bAxis);
            //转换坐标系,原点为画布中心,右向x正向,上方为y正向
            gBAxis.TranslateTransform((float)GlobalVars.mainForm.pictureWidth / 2, (float)GlobalVars.mainForm.pictureHeight / 2);//原点向右向下各平移图片大小的一半
            gBAxis.ScaleTransform(GlobalVars.scaleTimes, (-1) * GlobalVars.scaleTimes);//放大,并且y反向
            //设置画笔
            Pen pBAxis = new Pen(Color.Blue, 1 / GlobalVars.scaleTimes);
            //设置绘图数据
            PointF[] xAxis = new PointF[2];
            xAxis[0].X = (float)(-1) * int.Parse( GlobalVars.mainForm.paramsForm.simulationWidth) / 2;
            xAxis[0].Y = 0F;
            xAxis[1].X = (float)int.Parse(GlobalVars.mainForm.paramsForm.simulationWidth) / 2;
            xAxis[1].Y = 0F;
            PointF[] yAxis = new PointF[2];
            yAxis[0].X = 0F;
            yAxis[0].Y = (float)(-1) * int.Parse(GlobalVars.mainForm.paramsForm.simulationHeight) / 2;
            yAxis[1].X = 0F;
            yAxis[1].Y = (float)int.Parse(GlobalVars.mainForm.paramsForm.simulationHeight) / 2;
            PointF oAxis = new PointF();
            oAxis.X = 0F;
            oAxis.Y = 0F;
            //绘制x轴
            gBAxis.DrawLines(pBAxis, xAxis);
            //绘制y轴
            gBAxis.DrawLines(pBAxis, yAxis);
            //绘制原点
            //
            //释放资源
            pBAxis.Dispose();
            gBAxis.Dispose();
        }


7.2.3 然后,自定义显示坐标系函数

在MyFunctions中自定义函数AxisShow,用于显示生成的坐标轴。

需要开放MainForm的pictureBox1的Image写属性和Refresh()方法:

        //7.2.3 开放pictureBox1的Image的写属性
        public Image pictureImage
        {
            set { pictureBox1.Image = value; }
        }
        //7.2.3 开放pictureBox的Refresh()方法
        public void pictureRefresh()
        {
            pictureBox1.Refresh();
        }


回到自定义函数:

//7.2.3 显示坐标轴
public static void AxisShow()
{
GlobalVars.mainForm.pictureImage = GlobalVars.bAxis;
GlobalVars.mainForm.pictureRefresh();
}


7.2.4 修订MainForm的Load过程

在MainForm的Load过程中,就应当将坐标轴使用默认的值显示出来。

打开MainForm.cs[设计]文件,双击窗体,自动生成MainForm_Load()事件函数,自动关联MainForm的Load事件,添加:

//7.2.4 使用默认值显示坐标轴
private void MainForm_Load(object sender, EventArgs e)
{
MyFunctions.CreateBAxis();
MyFunctions.AxisShow();
}


7.2.5 修订ParamsForm的OK按钮

当点击OK按钮时,说明已经对宽高值做了修改(虽然AttackRange不影响),这时需要重绘坐标轴,在OK按钮的Click事件函数中,添加:

//4.2 OK按钮功能
private void paramsSettingOkButton_Click(object sender, EventArgs e)
{
this.Hide();//隐藏当前窗体
GlobalVars.mainForm.paramsSettingEnabled = true;//使能菜单Params Setting

//7.1.5 重新设置一下仿真场景的宽高值
if(simulationWidthTextBox.Text != (2 * (int.Parse(mineCommunicationTextBox.Text) + int.Parse(mineDetectionTextBox.Text))).ToString())
{
simulationWidthTextBox.Text = (2 * (int.Parse(mineCommunicationTextBox.Text) + int.Parse(mineDetectionTextBox.Text))).ToString();
simulationHeightTextBox.Text = simulationWidthTextBox.Text;
}
//7.1.5 禁用OK按钮
paramsSettingOkButton.Enabled = false;

//7.2.5 重绘坐标轴
MyFunctions.CreateBAxis();
MyFunctions.AxisShow();
}


7.2.6 修订ParamsForm的Cancel按钮

当点击Cancel按钮时,对当前窗体,也就是ParamsForm窗体上,各TextBox所做的修改不生效,也就是说,设置一个全局变量,保存原先的值,点击Cancel按钮时,三个TextBox的值还原。

在GlobalVars类中,声明三个用于保存ParamsForm的TextBox的string类型全局变量:

//7.2.6 ParamsForm上三个TextBox的生效值
private static string pcomrangetext;
public static string pComRangeText
{
set { pcomrangetext = value; }
get { return pcomrangetext; }
}
private static string pdetrangetext;
public static string pDetRangeText
{
set { pdetrangetext = value; }
get { return pdetrangetext; }
}
private static string pattrangetext;
public static string pAttRangeText
{
set { pattrangetext = value; }
get { return pattrangetext; }
}


这三个全局变量的初始值,应当在paramsForm初始化时就该赋上,我们把赋初值放在ParamsForm的Load事件函数中。

打开ParamsForm.cs[设计]文件,双击窗体,自动生成ParamsForm_Load()事件函数,自动关联此窗体的Load事件,添加初始化这三个值的代码:

//7.2.6 初始化赋值三个TextBox的默认值
private void ParamsForm_Load(object sender, EventArgs e)
{
GlobalVars.pComRangeText = this.mineCommunicationTextBox.Text;
GlobalVars.pDetRangeText = this.mineDetectionTextBox.Text;
GlobalVars.pAttRangeText = this.mineAttackTextBox.Text;
}


然后回到ParamsForm的Cancel按钮的Click事件函数,添加使得三个TextBox还原的代码:

//4.3 Cancel按钮功能
private void paramsSettingCancelButton_Click(object sender, EventArgs e)
{
this.Hide();//隐藏当前窗体
GlobalVars.mainForm.paramsSettingEnabled = true;//使能菜单Params Setting

//7.2.6 还原三个TextBox的值
this.mineCommunicationTextBox.Text = GlobalVars.pComRangeText;
this.mineDetectionTextBox.Text = GlobalVars.pDetRangeText;
this.mineAttackTextBox.Text = GlobalVars.pAttRangeText;
}


这样,当按OK按钮时,应当给这三个全局变量更新,在OK按钮的Click事件函数中,添加:

//4.2 OK按钮功能
private void paramsSettingOkButton_Click(object sender, EventArgs e)
{
this.Hide();//隐藏当前窗体
GlobalVars.mainForm.paramsSettingEnabled = true;//使能菜单Params Setting

//7.1.5 重新设置一下仿真场景的宽高值
if(simulationWidthTextBox.Text != (2 * (int.Parse(mineCommunicationTextBox.Text) + int.Parse(mineDetectionTextBox.Text))).ToString())
{
simulationWidthTextBox.Text = (2 * (int.Parse(mineCommunicationTextBox.Text) + int.Parse(mineDetectionTextBox.Text))).ToString();
simulationHeightTextBox.Text = simulationWidthTextBox.Text;
}
//7.1.5 禁用OK按钮
paramsSettingOkButton.Enabled = false;

//7.2.5 重绘坐标轴
MyFunctions.CreateBAxis();
MyFunctions.AxisShow();

//7.2.6 更新三个TextBox的缓存全局变量
GlobalVars.pComRangeText = this.mineCommunicationTextBox.Text;
GlobalVars.pDetRangeText = this.mineDetectionTextBox.Text;
GlobalVars.pAttRangeText = this.mineAttackTextBox.Text;
}


经过测试,当文本框文本改变时,TextChanged事件发生,会将OK按钮激活。所以在Cancel按钮的Click事件中,添加使得OK按钮失效的语句:

        //4.3 Cancel按钮功能
        private void paramsSettingCancelButton_Click(object sender, EventArgs e)
        {
            this.Hide();//隐藏当前窗体
            GlobalVars.mainForm.paramsSettingEnabled = true;//使能菜单Params Setting
            
            //7.2.6 还原三个TextBox的值
            this.mineCommunicationTextBox.Text = GlobalVars.pComRangeText;
            this.mineDetectionTextBox.Text = GlobalVars.pDetRangeText;
            this.mineAttackTextBox.Text = GlobalVars.pAttRangeText;
            //触发了TextChanged事件,需要修订OK按钮的失效属性
            this.paramsSettingOkButton.Enabled = false;
        }


视图效果:



项目代码:

http://yunpan.cn/Q9AmY6HbSBzaI

注:下节会修订坐标轴,添加原点及标识,添加坐标轴箭头及表示,坐标轴虚线化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息