• [C#]窗体切换--避免开启多个线程


    先说说这个多窗体的界面的解决的办法:

    用到的方法很简单,就是程序运行就建立一个MainForm,在这个MainForm中设立一个Panel,同时设立几个按钮,按下每个按钮都在这个Panel中载入不同的窗体,这样就解决了多窗体的切换。

     提示:

    在Panel的子窗体可以通过设置Form的FormBorderStyle为none,去掉它的最大化最小化和关闭按钮。但是一旦设置这个属性就必须手动的调用这个窗体的close方法来关闭这个窗体,因为调用这个方法和鼠标点击窗体的x按钮是一样的效果,都会调用窗体的close函数。同时这个函数的调用也会触发窗体的formclosing等事件。

    下面看一下第一次写的代码:

    //MainForm的代码
    public class RobotArrounding : Form
    {
    	private int curSelect = 0;
    
    	public RobotArrounding()
    	{
    		InitializeComponent();
    
    
    		this.pnlMain.Controls.Clear();
    		MonitorForm monitorFrm = new MonitorForm();
    
    		monitorFrm.TopLevel = false;
    		monitorFrm.Dock = DockStyle.Fill;
    		monitorFrm.Show();
    
    		this.pnlMain.Controls.Add(monitorFrm);
    
    	}
    
    	private void btnMonitor_Click(object sender, EventArgs e)
    	{
    		if (curSelect != 0)
    		{
    			this.pnlMain.Controls.Clear();
    			MonitorForm monitorFrm = new MonitorForm();
    
    			monitorFrm.TopLevel = false;
    			monitorFrm.Dock = DockStyle.Fill;
    			monitorFrm.Show();
    
    			this.pnlMain.Controls.Add(monitorFrm);
    		}
    
    		curSelect = 0;
    
    	}
    
    	private void btnPlane_Click(object sender, EventArgs e)
    	{
    		if (curSelect != 1)
    		{
    			this.pnlMain.Controls.Clear();
    
    			CheckingPlane planeFrm = new CheckingPlane();
    
    			planeFrm.TopLevel = false;
    			planeFrm.Dock = DockStyle.Fill;
    			planeFrm.Show();
    
    			this.pnlMain.Controls.Add(planeFrm);
    		}
    		curSelect = 1;
    	}
    
    	private void btnHistoryChecking_Click(object sender, EventArgs e)
    	{
    		if (curSelect != 2)
    		{
    			this.pnlMain.Controls.Clear();
    			HistoryChecking historyFrm = new HistoryChecking();
    
    			historyFrm.TopLevel = false;
    			historyFrm.Dock = DockStyle.Fill;
    			historyFrm.Show();
    
    			this.pnlMain.Controls.Add(historyFrm);
    		}
    		curSelect = 2;
    	}
    
    	private void bntExit_Click(object sender, EventArgs e)
    	{
    		this.Close();
    		//退出整个程序
    		Application.Exit();
    	}
    }

      代码很简单,每次点击按钮都new一个新的窗体并显示。但是后来发现这样有问题,那就是多次按按钮,切换界面以后,原本new出来的窗体并没有销毁,没有被垃圾回收器收回。而是在整个程序退出的时候才调用了窗体的close方法,验证的方法就是在每一个窗体中增加formclosing事件,验证这个事件触发的时间,代码:

    //其中的一个界面的类
    public partial class CheckingPlane : Form
    {
    	public CheckingPlane()
    	{
    		InitializeComponent();
    	}
    
    	private void CheckingPlane_FormClosing(object sender, FormClosingEventArgs e)
    	{
    		int a = 0;
    		a = 10;
    	}
    }
    

      在MainForm调用application.Exit()方法得时候,发现这个窗体类的FormClosing事件执行了好多次,这个原因就是切换好多次的窗体之后,new出来了好多的窗体的实例。

    解决的办法:

    如果一个窗体没有被要求显示,那么这个窗体就不用new一个实例,如果这个窗体要求显示,那么就new一个窗体的实例,然后一直保持一个窗体的单例模式,直到整个程序退出时才销毁这个窗体。

    public partial class RobotArrounding : Form
    {
    	private int curSelect = 0;
    	private Form[] selectFrm = null;
    
    	public RobotArrounding()
    	{
    		InitializeComponent();
    		selectFrm = new Form[3];
    
    		this.pnlMain.Controls.Clear();
    
    		selectFrm[0] = new MonitorForm();
    
    		selectFrm[0].TopLevel = false;
    		selectFrm[0].Dock = DockStyle.Fill;
    		selectFrm[0].Show();
    
    		this.pnlMain.Controls.Add(selectFrm[0]);
    
    	}
    
    	private void btnMonitor_Click(object sender, EventArgs e)
    	{
    		if (curSelect != 0)
    		{
    			this.pnlMain.Controls.Clear();
    			if (selectFrm[0] == null || selectFrm[0].IsDisposed)
    			{
    				selectFrm[0] = new MonitorForm();
    
    				selectFrm[0].TopLevel = false;
    				selectFrm[0].Dock = DockStyle.Fill;
    				
    			}
    			else 
    			{
    				selectFrm[0].Activate();
    			}
    
    			selectFrm[curSelect].Hide();
    			selectFrm[0].Show();
    
    
    			this.pnlMain.Controls.Add(selectFrm[0]);
    		}
    		curSelect = 0;
    
    	}
    
    	private void btnPlane_Click(object sender, EventArgs e)
    	{
    		if (curSelect != 1)
    		{
    			this.pnlMain.Controls.Clear();
    
    			if (selectFrm[1] == null || selectFrm[1].IsDisposed)
    			{
    				selectFrm[1] = new CheckingPlane();
    
    				selectFrm[1].TopLevel = false;
    				selectFrm[1].Dock = DockStyle.Fill;
    			}
    			else
    			{
    				selectFrm[1].Activate();
    			}
    
    			selectFrm[curSelect].Hide();
    			selectFrm[1].Show();
    
    			this.pnlMain.Controls.Add(selectFrm[1]);
    		}
    		curSelect = 1;
    	}
    
    	private void btnHistoryChecking_Click(object sender, EventArgs e)
    	{
    		if (curSelect != 2)
    		{
    			this.pnlMain.Controls.Clear();
    
    			if (selectFrm[2] == null || selectFrm[2].IsDisposed)
    			{
    				selectFrm[2] = new HistoryChecking();
    
    				selectFrm[2].TopLevel = false;
    				selectFrm[2].Dock = DockStyle.Fill;
    			}
    			else
    			{
    				selectFrm[2].Activate();
    			}
    
    			selectFrm[curSelect].Hide();
    			selectFrm[2].Show();
    
    			this.pnlMain.Controls.Add(selectFrm[2]);
    		}
    		curSelect = 2;
    	}
    
    	private void bntExit_Click(object sender, EventArgs e)
    	{
    		for (int i = 0; i < 3; i++ )
    		{
    			if (selectFrm[i] != null)
    			{
    				selectFrm[i].Close();
    			}
    		}
    
    		this.Close();
    
    		Application.Exit();
    	}
    
    }
    

      这样写还有一个小的问题,那就是我自己的继承自Form的窗体类,如果有自己定义的函数,利用多态访问这个窗体的时候就不能访问到这个函数。其实这个也很简单,在需要访问子类自定义的函数的时候,强制转换一下类型就可以了。

     这样一来,不管你切换多少次窗体,都只有一个窗体的实例了,这样就能防止new很多的窗体实例了。

  • 相关阅读:
    李超线段树 (Li-Chao Segment Tree)
    NowCoder Contest 894
    AtCoder Beginning Contest 126
    华工软院IBM LinuxONE Community Cloud云计算实验文档
    Codeforces Round #561 (div. 2)
    Comet OJ Contest #3
    Codeforces Edu Round 65 (Rated for Div. 2)
    莫队算法 (Mo's Algorithm)
    Codeforces Round #559 (Div. 2)
    GDCPC2019 广东省赛总结
  • 原文地址:https://www.cnblogs.com/stemon/p/4557504.html
Copyright © 2020-2023  润新知