【基於WinForm+Access局域網共享數據庫的項目總結】之篇一:WinForm開發總體概述與技術實現


篇一:WinForm開發總體概述與技術實現

篇二:WinForm開發扇形圖統計和Excel數據導出

篇三:Access遠程連接數據庫和窗體打包部署


【小記】:最近基於WinForm+Access數據庫完成一個法律咨詢管理系統。本系統要求類似網頁后台管理效果,並且基於局域網內,完成多客戶端操作同一數據庫,根據權限不同分別執行不同功能模塊。核心模塊為級聯統計類型管理、數據庫咨詢數據扇形統計、樹的操作、咨詢數據的管理、手寫分頁、Excel數據的導出、多用戶操作服務器數據等。並支持多用戶同時操作,遠程連接數據庫且對數據IP信息的修改。開發過程中特別對界面的要求和事后多用戶操作顯得略為麻煩。自此,本項目得以完善交付,然后對其進行小結。依舊采用整個框架認識,核心知識逐個梳理分析,以便於二次開發和需要之程序員共享。

 


篇一:WinForm開發總體概述與技術實現

【開篇】運行效果圖示和功能介紹


    1 登陸信息圖示和功能概述

   注解:本登陸界面可實現遠程連接數據庫,點擊:服務器設置窗體進行向下展開,在IP地址配置處輸入正確的IP地址(前提需要遠程連接服務器)。其原理為,App.config文件進行遠程連接數據庫配置,通過連接IP地址下共享文件夾中的Access數據文件訪問。具體遠程實現代碼在篇二進行展開。並且通過對App.config文件操作進行IP地址的本地保存。

2 主窗體功能模塊圖示與功能概述

注解:管理員登陸進入主頁面可以實現對系統的咨詢管理、打印用戶報表和咨詢報表、對多組合數據扇形圖的實現、用戶管理、咨詢類型級聯修改和刪除、以及個人信息的修改。律師進入頁面后只能對我要咨詢操作。整個數據控件的顯示效果和布局方式,手寫分頁、以及如何實現類似網頁版效果,后面逐步解析。

 

【總結】核心知識點梳理


1 如何實現窗體折疊效果?如何讀取連接字符串的IP地址?

            if (this.Height == 325)
            {
                button2.Text = "服務器設置 ↑";      
                this.Height = 465;
            }
            else
            {
                button2.Text = "服務器設置 ↓";
                this.Height = 325;
            }

 注:通過設置窗體高度和文本信息進行折疊     

                //把連接數據庫的字符串分割,並填充至文本框
                try
                {
                    XDocument doc = XDocument.Load(file);
                    //Provider=Microsoft.ACE.OLEDB.12.0;Data Source=//10.130.16.136/db/Legal.accdb
                    string connstring = doc.Elements("configuration").Elements("connectionStrings").Elements("add").Attributes("connectionString").FirstOrDefault().Value;
                    string[] array1 = connstring.Split(';');
                    string str = array1[1].Split('=')[1];//  ->//10.130.16.136/db/Legal.accdb
                    string[] newarray = str.Split('/');
                    this.textBox3.Text = newarray[2].Split('/')[0].ToString();
                }
                catch { }

  注:通過操作App.config文件,並且進行字符串截取獲取IP地址

------------------------------------------------------------------------------------------------------------------------------------------------------- 

2 如何進行連接遠程數據庫IP地址的設置與保存?

                if (textBox3.Text != "")
                {
string file = @"C:\db\App.config";
XDocument doc = XDocument.Load(file); //sql數據庫數據庫配置 //string connstring = "initial catalog=Highway;Data Source=" + this.textBox3.Text + ";uid=" + this.textBox4.Text + ";pwd=" + this.textBox5.Text + ";"; //access數據庫遠程配置 //Provider=Microsoft.ACE.OLEDB.12.0;Data Source=//10.130.16.136/db/Legal.accdb string connstring = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=//" + textBox3.Text.ToString()+ "/db/Legal.accdb"; doc.Elements("configuration").Elements("connectionStrings").Elements("add").Attributes("connectionString").FirstOrDefault().SetValue(connstring); doc.Save(file); //由於DBHelperSQL中的ConnectionString(公共靜態變量)未被修改引發的bug XDocument xdoc = XDocument.Load(file); string val = doc.Elements("configuration").Elements("connectionStrings").Elements("add").Attributes("connectionString").FirstOrDefault().Value; SQLHelper.connstr = val; }

    注:在文本框中修改IP地址,然后通過操作本地App.config文件,進行修改保存操作。但是保存后要及時修改配置連接字符串中的數據。

 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

3 如何進行窗體間傳值?

子窗體:
if (dt.Rows[0][1].ToString() == textBox1.Text.ToString() && dt.Rows[0][2].ToString() == textBox2.Text.ToString()) { int id = Convert.ToInt32(dt.Rows[0]["ID"].ToString()); string type = dt.Rows[0][3].ToString(); string name = this.textBox1.Text.ToString(); ; this.Hide(); Fm_Main fm = new Fm_Main(id, name, type); fm.Show(); this.Hide(); }
父窗體:
#region 構造函數接收用戶名、管理權限
private string Name;
private string Type;
private int ID;
public Fm_Main() { }
public Fm_Main(int id,string name, string type)
{
    InitializeComponent();
    this.Name = name;
    this.Type = type;
    this.ID = id;
}
#endregion

注:在服父窗體寫個構造函數,並且定義其屬性,然后傳參賦值即可。但是在構造函數中添加如下語句: InitializeComponent();否則運行不是自己預期的效果。


4 父窗體如何作為容器,顯示子窗體?

            //繪制的方式OwnerDrawFixed表示由窗體繪制大小也一樣
         this.tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
            this.tabControl1.Padding = new System.Drawing.Point(CLOSE_SIZE, CLOSE_SIZE);
            this.tabControl1.DrawItem +=new DrawItemEventHandler(tabControl1_DrawItem);
            this.tabControl1.MouseDown += new MouseEventHandler(tabControl1_MouseDown);

 

        #region  繪制tabControl的關閉按鈕,以及關閉功能的實現
        private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
        {      
            try
            {
                Rectangle myTabRect = this.tabControl1.GetTabRect(e.Index);
                //先添加TabPage屬性   
                e.Graphics.DrawString(this.tabControl1.TabPages[e.Index].Text, this.Font, SystemBrushes.ControlText, myTabRect.X + 4, myTabRect.Y + 4);
                //再畫一個矩形框
                using (Pen p = new Pen(Color.White))
                {
                    myTabRect.Offset(myTabRect.Width - (CLOSE_SIZE + 3), 2);
                    myTabRect.Width = CLOSE_SIZE;
                    myTabRect.Height = CLOSE_SIZE;
                    e.Graphics.DrawRectangle(p, myTabRect);
                }
                //填充矩形框
                Color recColor = e.State == DrawItemState.Selected ? Color.White : Color.White;
                using (Brush b = new SolidBrush(recColor))
                {
                    e.Graphics.FillRectangle(b, myTabRect);
                }
                //畫關閉符號
                using (Pen objpen = new Pen(Color.Black))
                {
                   
                    //使用圖片
                    Bitmap bt = new Bitmap(image);
                    Point p5 = new Point(myTabRect.X, 4);
                    e.Graphics.DrawImage(bt, p5);
                    //e.Graphics.DrawString(this.MainTabControl.TabPages[e.Index].Text, this.Font, objpen.Brush, p5);
                }
                e.Graphics.Dispose();
            }
            catch (Exception)
            { }
        }
       //鼠標作用事件設置
        void tabControl1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {

                int x = e.X, y = e.Y;
                //計算關閉區域   
                Rectangle myTabRect = this.tabControl1.GetTabRect(this.tabControl1.SelectedIndex);
                myTabRect.Offset(myTabRect.Width - (CLOSE_SIZE + 3), 2);
                myTabRect.Width = CLOSE_SIZE;
                myTabRect.Height = CLOSE_SIZE;
                //如果鼠標在區域內就關閉選項卡   
                bool isClose = x > myTabRect.X && x < myTabRect.Right && y > myTabRect.Y && y < myTabRect.Bottom;
                if (isClose == true)
                {
                    this.tabControl1.TabPages.Remove(this.tabControl1.SelectedTab);
                }
            }
        }
        const int CLOSE_SIZE = 15;

        //tabPage標簽圖片
      

        Bitmap image = new Bitmap(@"C:\db\btnClose.png");
      #endregion
View Code

注:首先在窗體加載方法加入以上事件,並且對選項卡關閉進行畫圖。


5  子窗體怎樣加載在父窗體的Panel面板中,且類似網頁效果?

            //用戶管理
        private void Moth_User()
        {
            if (ErgodicModiForm("tbuse", tabControl1) == true)
            {
                tbUser = new TabPage("用戶管理");
                tbUser.Name = "tbuse";
                tabControl1.Controls.Add(tbUser);

                UserManage form = new UserManage();
                form.TopLevel = false;
                form.FormBorderStyle = FormBorderStyle.None;
                form.WindowState = FormWindowState.Maximized;
                form.BackColor = Color.White;
                form.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
                form.Show();
                tbUser.Controls.Add(form);
            }
            tabControl1.SelectedTab = tbUser;
        }

        //判斷選項卡是否存在
        private Boolean ErgodicModiForm(string MainTabControlKey, TabControl objTabControl)
        {
            //遍歷選項卡判斷是否存在該子窗體  
            foreach (Control con in objTabControl.Controls)
            {
                TabPage tab = (TabPage)con;
                if (tab.Name == MainTabControlKey)
                {
                    return false;//存在  
                }
            }
            return true;//不存在  
        }
View Code

注:通過在父窗體有部分panel面板中,添加


6 視圖的平鋪、垂直、層疊效果的實現?

        #region 視圖顯示
        private void 平鋪ToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            LayoutMdi(MdiLayout.TileHorizontal);
        }

        private void 垂直ToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            LayoutMdi(MdiLayout.TileVertical);
        }

        private void 層疊ToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            LayoutMdi(MdiLayout.Cascade);
        }
        #endregion
View Code

7  樹節點如何導航到父窗體的panel面板?

        private void treeView1_AfterSelect_1(object sender, TreeViewEventArgs e)
        {
            try
            {
                switch (e.Node.Text.ToString())//字符串
                {
                    case "法律服務中心"://注意字符串夾引號,以下均是
                        Moth_Apply();
                        break;
                    case "我要咨詢"://注意字符串夾引號,以下均是
                        Moth_Apply();
                        break;
                    case "用戶報表導出"://注意字符串夾引號,以下均是
                            Moth_Print();
                        break;
                    case "咨詢報表導出"://注意字符串夾引號,以下均是
                        Moth_Print1();
                        break;

                    case "統計圖"://注意字符串夾引號,以下均是
                            Moth_Graph();
                        break;
                    case "二級統計圖"://注意字符串夾引號,以下均是
                        Moth_TwoGraph();
                        break;
                    case "三級統計圖"://注意字符串夾引號,以下均是
                        Moth_ThreeGraph();
                        break;
                    case "用戶查詢"://注意字符串夾引號,以下均是
                            Moth_User();
                        break;
                    case "律師"://注意字符串夾引號,以下均是
                            Moth_lvshi();
                        break;
                    case "管理員"://注意字符串夾引號,以下均是
                            Moth_guanli();
                        break;
                }
            }
            catch { return; }
        }
View Code

注:前面5中的方法,在7中遍歷調用即可!


8  如何隱藏樹中部分節點?

        public void HideNotes()
        {
            for (int i = 0; i < this.treeView1.Nodes.Count; i++)
            {
                FetchNode(this.treeView1.Nodes[i]);//遞歸根節點的所有子節點
            }
        }
        private void FetchNode(TreeNode node)
        {
            //nodeList.Add(node);
            for (int i = 0; i < node.Nodes.Count; i++)
            {
                if (node.Text == "報表")
                {
                    treeView1.Nodes.Remove(node.Nodes[0]);
                }
                if (node.Text == "法律服務中心")
                {
                    treeView1.Nodes.Remove(node.Nodes[2]);
                }

                if (node.Text == "統計圖")
                {
                    treeView1.Nodes.Remove(node);
                }

                else
                {
                    FetchNode(node.Nodes[i]);
                }
            }
        }
View Code

9 如何實現打包后的窗體類似qq效果,最小化可以在任務欄,點擊顯示原狀態?

        //類似qq最小化
        private void Fm_Main_SizeChanged(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.Hide();
                this.notifyIcon1.Visible = true;
            }
        }

        private void notifyIcon1_Click(object sender, EventArgs e)
        {
            this.Visible = true;
            this.WindowState = FormWindowState.Maximized;
        }
View Code

10  手寫窗體分頁效果?

           public int pageSize = 10;      //每頁記錄數
        public int recordCount = 0;    //總記錄數
        public int pageCount = 0;      //總頁數
        public int currentPage = 0;    //當前頁
        public DataTable dtSource = new DataTable();
     //加載窗體分頁顯示數據
        private void LoadPage()
        {
            //數據庫操作獲得DataTable,獲取總頁數
            string sql = "select * from L_consult order by ID desc";
            dtSource = SQLHelper.GetTableData(sql);
            recordCount = dtSource.Rows.Count;
            pageCount = (recordCount / pageSize);
            if ((recordCount % pageSize) > 0)
            {
                pageCount++;
            }
            //邏輯判斷頁數顯示
            if (currentPage < 1) currentPage = 1;
            if (currentPage > pageCount) currentPage = pageCount;
            int beginRecord;
            int endRecord;
            DataTable dtTemp;
            dtTemp = dtSource.Clone();
            beginRecord = pageSize * (currentPage - 1);
            if (currentPage == 1) beginRecord = 0;
            endRecord = pageSize * currentPage;
            if (currentPage == pageCount) endRecord = recordCount;
            for (int i = beginRecord; i < endRecord; i++)
            {
                dtTemp.ImportRow(dtSource.Rows[i]);
            }
            dataGridView2.DataSource = dtTemp;
            lblcount.Text = recordCount.ToString();
            lblpagecount.Text = pageCount.ToString();
            lblpage.Text = pageSize.ToString();
            txtindexpage.Text = currentPage.ToString();
        }

        //首頁
        private void bntfrist_Click(object sender, EventArgs e)
        {
            currentPage = 1;
            LoadPage();
        }
        //上一頁
        private void bntpriove_Click(object sender, EventArgs e)
        {
            currentPage--;
            LoadPage();
        }
        //下一頁
        private void bntnext_Click(object sender, EventArgs e)
        {
            currentPage++;
            LoadPage();
        }
        //尾頁
        private void bntlast_Click(object sender, EventArgs e)
        {
            currentPage = pageCount;
            LoadPage();
        }
        //跳轉
        private void bntGO_Click(object sender, EventArgs e)
        {
            if (txtgo.Text == "")
            {
                int pageN = 1;
            }
            else
            {
                int pageN = Convert.ToInt32(txtgo.Text);
                currentPage = pageN;
                LoadPage();
            }
        }
View Code

注:本功能初始想采用分頁控件,后來多次使用失敗,總是報錯。索性自己手寫一個分頁控件。需要五個button按鈕和2個文本框。


11   代碼事件 設置數據控件外觀?

        /// <summary>
        /// 用來記錄先前的顏色值
        /// </summary>
        Color colorTmp = Color.White;
        /// <summary>
        /// 記錄鼠標形狀
        /// </summary>
        Cursor cursorTmp = Cursor.Current;
        //設置數據控件外觀
        private void dataGridView2_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            
            for (int i = 0; i < dataGridView2.Rows.Count; i++)
            {
                if (i % 2 == 0)
                {
                    dataGridView2.Rows[i].DefaultCellStyle.BackColor = Color.Bisque; ;
                }
                else
                {
                    dataGridView2.Rows[i].DefaultCellStyle.BackColor = Color.White;
                }
            }
        }
        //鼠標划過
        private void dataGridView2_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0)
            {
                colorTmp = dataGridView2.Rows[e.RowIndex].DefaultCellStyle.BackColor;
                dataGridView2.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.Silver;
                if (e.ColumnIndex == 1)//改變第二列鼠標形狀
                {
                    cursorTmp = this.Cursor;
                    this.Cursor = Cursors.Hand;
                }
            }
        }
        //鼠標離開
        private void dataGridView2_CellMouseLeave(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0)
            {
                dataGridView2.Rows[e.RowIndex].DefaultCellStyle.BackColor = colorTmp;
                if (e.ColumnIndex == 1)
                {
                    this.Cursor = cursorTmp;
                }
            }
        }
     
View Code

 


12  執行刪改獲取當前數據主鍵?

            int index = dataGridView2.CurrentRow.Index;
            int EmpId = Convert.ToInt32(dataGridView2.Rows[index].Cells[0].Value.ToString());

 


13  數據類型管理,實現級聯刪除?

        //級聯刪除
        private void button2_Click(object sender, EventArgs e)
        {
            if (dataGridView1.SelectedRows.Count > 0)
            {
                if (dataGridView1.Rows.Count > 0)
                {
                    int index = dataGridView1.CurrentRow.Index;
                    int EmpId = Convert.ToInt32(dataGridView1.Rows[index].Cells[0].Value.ToString());

                    if (MessageBox.Show("刪除后將不能恢復!", "提示信息", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK)
                    {
                        //刪除A表
                        string asql = "delete  from A_type where ID=" + EmpId;//刪除父級別類型
                        //刪除B表
                        string sqlaname = "select name from A_type  where ID="+EmpId;//條件關聯刪除子表
                        DataTable dt = MYHelper.SQLHelper.GetTableData(sqlaname);
                        string aname = dt.Rows[0]["name"].ToString();
                        string sqlbname = "select bname from B_type  where aname='" + aname + "'";//條件關聯刪除子表
                        DataTable dtb = MYHelper.SQLHelper.GetTableData(sqlbname);
                        int c=0;
                        for (int i = 0; i < dtb.Rows.Count; i++)
                        {
                             string bname = dtb.Rows[i][0].ToString();
                             string csql = "delete  from C_type where bname='" + bname + "'";//刪除父級別類型
                             c = SQLHelper.ExecuteQuery(csql);
                        }
                        string bsql = "delete  from B_type where aname='" + aname+"'";//刪除父級別類型
                        //刪除C表
                      
                        int b = SQLHelper.ExecuteQuery(bsql);
                        int a = SQLHelper.ExecuteQuery(asql);
                        if (a > 0&&b>0&&c>0)
                        {
                            MessageBox.Show("刪除成功!");
                            this.LoadPage();
                        }
                    }
                }
            }
        }
View Code

 


14  數據類型管理,實現級聯修改?

        //級聯修改
        private void button4_Click(object sender, EventArgs e)
        {
            try
            {
                if (IsNull() == true)
                {
                     int index = dataGridView1.CurrentRow.Index;
                     int EmpId = Convert.ToInt32(dataGridView1.Rows[index].Cells[0].Value.ToString());
                    //修改a表
                    string asql = "update  A_type set name='" + txttype1.Text.ToString() + "' where ID=" + EmpId;
                  
                    string sqlaname = "select name from A_type  where ID=" + EmpId;//條件關聯子表
                    DataTable dt = MYHelper.SQLHelper.GetTableData(sqlaname);
                    string aname = dt.Rows[0]["name"].ToString();
                    int a = SQLHelper.ExecuteQuery(asql);
                    DataTable dta = MYHelper.SQLHelper.GetTableData(sqlaname);
                    string aaname = dta.Rows[0]["name"].ToString();
                   //修改b表
                    string bsql = "update  B_type set aname='" + aaname + "' where aname='" + aname + "'";
                  
                    int b = SQLHelper.ExecuteQuery(bsql);
                    if (a > 0&&b>0)
                    {
                        MessageBox.Show("添加成功!");
                        this.LoadPage();
                        this.Clear();
                    }
                    else
                    {
                        MessageBox.Show("添加失敗!");
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + ex.StackTrace);
            }
        }
View Code

15 Access數據庫連接語句,如何實現遠程連接?
App.config本地配置連接語句:

<add name="sql" connectionString="Provider=Microsoft.ACE.OLEDB.12.0;Data Source='C:\Users\bncPc\Desktop\Form_legal\Form_legal\db\Legal.accdb'" />

 App.config遠程配置連接語句:

<add name="sql" connectionString="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=//10.130.16.137/db/Legal.accdb" />

 


16  Access數據庫操作,封裝執行方法?

        //讀取配置文件中的連接字符串
        public   static string connstr = ConfigurationManager.ConnectionStrings["sql"].ConnectionString;
      // public   static string connstr =@"Provider=MS Remote; Remote Server=http://10.130.16.135; Remote Provider=Microsoft.ACE.OLEDB.12.0;Data Source='C:\Users\bncPc\Desktop\Form_legal\Form_legal\db\Legal.accdb'";
      
        //static string connstr = "data source=ORCL;User Id=system;Password=orcl";
        // static string connstr = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=//10.130.16.135/db2/Legal.accdb;Persist Security Info=False" ";

       //public static string connstr = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=//10.130.16.135/db2/Legal.accdb";
        public static bool TestConn()
        {
                OleDbConnection conn = new OleDbConnection(connstr);
                bool flag = true;
                if (conn != null)
                {
                    try
                    {
                        conn.Open();
                        flag = true;
                    }
                    catch
                    {
                        flag=false;
                        return flag;
                    }
                }
                else
                {
                   flag=false;
                }
                return flag;
        }
        public static DataSet GetSetData(string sql)
        {
            DataSet ds = new DataSet();
            using (OleDbConnection conn = new OleDbConnection(connstr))
            {
                using (OleDbCommand cmd = new OleDbCommand(sql, conn))
                {
                    //根據傳來的參數。決定是sql語句還是存儲過程
                    //cmd.CommandType = CommandType.StoredProcedure;
                    conn.Open();
                    using (OleDbDataAdapter sda = new OleDbDataAdapter(cmd))
                    {
                        sda.Fill(ds);
                    }
                }
            }
            return ds;
        }
        public static DataTable GetTableData(string sql)
        {
            DataTable dt = new DataTable();
            using (OleDbConnection conn = new OleDbConnection(connstr))
            {
                try
                {
                    using (OleDbCommand cmd = new OleDbCommand(sql, conn))
                    {
                        //根據傳來的參數。決定是sql語句還是存儲過程
                        //cmd.CommandType = CommandType.StoredProcedure;
                        conn.Open();
                        using (OleDbDataAdapter sda = new OleDbDataAdapter(cmd))
                        {
                            sda.Fill(dt);
                        }
                    }
                }
                catch (Exception ex)
                {
                    dt = null;
                    return dt;
                }
            }
            return dt;
        }
        public static int ExecuteQuery(string sql)
        {
            int res = -1;
            using (OleDbConnection conn = new OleDbConnection(connstr))
            {
                using (OleDbCommand cmd = new OleDbCommand(sql, conn))
                {
                    conn.Open();
                    res = cmd.ExecuteNonQuery();
                }
            }
            return res;
        }


        public static int ExecuteScalar(string sql)
        {
            int res = -1;
            using (OleDbConnection conn = new OleDbConnection(connstr))
            {
                using (OleDbCommand cmd = new OleDbCommand(sql, conn))
                {
                    conn.Open();
                    res = Convert.ToInt32(cmd.ExecuteScalar());
                }
            }
            return res;
        }
View Code

 

【篇末】項目小結


 本程序對數據控件的外觀設置、手寫分頁、樹操作、遠程數據庫配置等。特別是對父窗體Panel面板的頁面顯示略為復雜。其他基本事件操作和易錯點與忽略點做以總結。下章具體展開對數據信息的導出和扇形統計圖的繪制。最后一篇介紹整體配置和安裝需求等實施總結!

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM