[收藏轉載]C# GDI+ 簡單繪圖(一)

最近對GDI+這個東西接觸的比較多,也做了些簡單的實例,比如繪圖板,仿QQ截圖等.

  廢話不多說了,我們先來認識一下這個GDI+,看看它到底長什么樣.

  GDI+:Graphics Device Interface Plus也就是圖形設備接口,提供了各種豐富的圖形圖像處理功能;在C#.NET中,使用GDI+處理二維(2D)的圖形和圖像,使用DirectX處理三維(3D)的圖形圖像,圖形圖像處理用到的主要命名空間是System . Drawing:提供了對GDI+基本圖形功能的訪問,主要有Graphics類、Bitmap類、從Brush類繼承的類、Font類、Icon類、Image類、Pen類、Color類等.

  大概了解了什么是GDI+后,我們來看一下繪圖要用到的主要工具,要畫圖,肯定要畫板吧,在C#中畫板可以通過Graphics這個類來創建,有了畫板,總得弄個筆什么之類的吧,不然怎么畫呀,難不成我們用手指畫.筆又可以分好多種類,比如鉛筆,畫刷等.它們的區別主要是鉛筆可以用來畫線條,而畫刷呢,嘿嘿,自己考慮下.在c#中我們可以用Pen,Brush類來實現類似功能.顏料則自然是用Color類了.

  有了工具,我們就可以開始動手了!(所需命名空間:using System.Drawing;)

  實現效果:在空白窗體中畫基本圖形

  準備一個畫板:

  創建一個畫板主要有3種方式:

  A: 在窗體或控件的Paint事件中直接引用Graphics對象

  B: 利用窗體或某個控件的CreateGraphics方法

  C: 從繼承自圖像的任何對象創建Graphics對象

  這次我們就先以A為例:

private void Form1_Paint(object sender, PaintEventArgs e)
    {
      Graphics g = e.Graphics; //創建畫板,這里的畫板是由Form提供的.
    }

  然后,我們要只筆:

private void Form1_Paint(object sender, PaintEventArgs e)
    {
      Graphics g = e.Graphics; //創建畫板,這里的畫板是由Form提供的.
      Pen p = new Pen(Color.Blue, 2);//定義了一個藍色,寬度為的畫筆
    }

  接下來我們就可以來畫畫了.

private void Form1_Paint(object sender, PaintEventArgs e)
    {
      Graphics g = e.Graphics; //創建畫板,這里的畫板是由Form提供的.
      Pen p = new Pen(Color.Blue, 2);//定義了一個藍色,寬度為的畫筆
      g.DrawLine(p, 10, 10, 100, 100);//在畫板上畫直線,起始坐標為(10,10),終點坐標為(100,100)
      g.DrawRectangle(p, 10, 10, 100, 100);//在畫板上畫矩形,起始坐標為(10,10),寬為,高為
      g.DrawEllipse(p, 10, 10, 100, 100);//在畫板上畫橢圓,起始坐標為(10,10),外接矩形的寬為,高為
    }

  效果圖如下:

  c# GDI+簡單繪圖(一)

  在上一片里已經向大家介紹了如何使用GDI+繪制簡單的圖像,這一片繼續向大家介紹其它一些繪圖知識.

  1.首先我們來看下上一片中我們使用過的Pen.

  Pen的屬性主要有: Color(顏色),DashCap(短劃線終點形狀),DashStyle(虛線樣式),EndCap(線尾形狀), StartCap(線頭形狀),Width(粗細)等.我們可以用Pen 來畫虛線,帶箭頭的直線等

Pen p = new Pen(Color.Blue, 5);//設置筆的粗細為,顏色為藍色
Graphics g = this.CreateGraphics();
//畫虛線
p.DashStyle = DashStyle.Dot;//定義虛線的樣式為點
g.DrawLine(p, 10, 10, 200, 10);
//自定義虛線
p.DashPattern = new float[] { 2, 1 };//設置短劃線和空白部分的數組
g.DrawLine(p, 10, 20, 200, 20);
//畫箭頭,只對不封閉曲線有用
p.DashStyle = DashStyle.Solid;//實線
p.EndCap = LineCap.ArrowAnchor;//定義線尾的樣式為箭頭
g.DrawLine(p, 10, 30, 200, 30);
g.Dispose();
p.Dispose();

  以上代碼運行結果:

c# GDI+簡單繪圖(二)

  2.接下來我們來看下Brush的使用

  作用:我們可以用畫刷填充各種圖形形狀,如矩形、橢圓、扇形、多邊形和封閉路徑等,主要有幾種不同類型的畫刷:

  ?     SolidBrush:畫刷最簡單的形式,用純色進行繪制

  ?     HatchBrush:類似于 SolidBrush,但是可以利用該類從大量預設的圖案中選擇繪制時要使用的圖案,而不是純色

  ?     TextureBrush:使用紋理(如圖像)進行繪制

  ?     LinearGradientBrush:使用沿漸變混合的兩種顏色進行繪制

  ?     PathGradientBrush :基于編程者定義的唯一路徑,使用復雜的混合色漸變進行繪制

  我們這里只是簡單介紹使用其中的幾種:

Graphics g = this.CreateGraphics();
Rectangle rect = new Rectangle(10, 10, 50, 50);//定義矩形,參數為起點橫縱坐標以及其長和寬
//單色填充
SolidBrush b1 = new SolidBrush(Color.Blue);//定義單色畫刷     
g.FillRectangle(b1, rect);//填充這個矩形
//字符串
g.DrawString("字符串", new Font("宋體", 10), b1, new PointF(90, 10));
//用圖片填充
TextureBrush b2 = new TextureBrush(Image.FromFile(@"e:picture1.jpg"));
rect.Location = new Point(10, 70);//更改這個矩形的起點坐標
rect.Width = 200;//更改這個矩形的寬來
rect.Height = 200;//更改這個矩形的高
g.FillRectangle(b2, rect);
//用漸變色填充
rect.Location = new Point(10, 290);
LinearGradientBrush b3 = new LinearGradientBrush(rect, Color.Yellow , Color.Black , LinearGradientMode.Horizontal);
g.FillRectangle(b3, rect);

  運行效果圖:

c# GDI+簡單繪圖(二)

  3.坐標軸變換

  在winform中的坐標軸和我們平時接觸的平面直角坐標軸不同,winform中的坐標軸方向完全相反:窗體的左上角為原點(0,0),水平向左則X增大,垂直下向則Y增大

?

c# GDI+簡單繪圖(二)

  接下來,我們來實際操作下,通過旋轉坐標軸的方向來畫出不同角度的圖案,或通過更改坐標原點的位置來平衡坐標軸的位置.

Graphics g = this.CreateGraphics();
//單色填充
//SolidBrush b1 = new SolidBrush(Color.Blue);//定義單色畫刷     
Pen p = new Pen(Color.Blue,1);
//轉變坐標軸角度
for (int i = 0; i < 90; i++)
{
  g.RotateTransform(i);//每旋轉一度就畫一條線
  g.DrawLine(p, 0, 0, 100, 0);
  g.ResetTransform();//恢復坐標軸坐標
}
//平移坐標軸
g.TranslateTransform(100, 100);
g.DrawLine(p, 0, 0, 100, 0);
g.ResetTransform();
//先平移到指定坐標,然后進行度旋轉
g.TranslateTransform(100,200);
for (int i = 0; i < 8; i++)
{
g.RotateTransform(45);
g.DrawLine(p, 0, 0, 100, 0);
}
g.Dispose();

  運行效果圖:

c# GDI+簡單繪圖(二)

  4.最后我們來看下Graphics這個畫板上我們還可以畫什么

  其實我們上面用到的都是在畫一些簡單的圖形,直線,矩形,扇形,圓孤等,我們還可以用它來繪制圖片,這可以用它的DrawImage方法.這里我不詳細講解,大家有興趣可以自己去MSDN了解下.我們后面會講到的截圖就會用到這個方法.

 感謝大家的支持,這幾天從早忙到晚,一個字累呀!!!現在挺困的,但是又不習慣這么早睡覺,哎~~還是利用這個時間繼續來寫第三篇吧.

  前兩篇已經基本向大家介紹了繪圖的基本知識.那么,我就用我們上兩篇所學的,做幾個例子.

  我們先來做一個簡單的----仿QQ截圖關于這個的例子其實網上已經有這方面的資料了,但是為了文章的完整性,還是覺得有必要講解.

  我們先來看一下效果:

C# GDI+ 簡單繪圖 (三)

  (圖1)

C# GDI+ 簡單繪圖 (三)

  (圖2)

  接下來看看這是如何做到的. 

  思路:聊天窗體上有一個截圖按鈕,點擊按鈕后,程序將整個屏幕畫在一個新的全屏窗體上,然后顯示這個窗體.因為是全屏的窗體,并且隱藏了菜單欄、工具欄等,所以在我們看來就好像是一個桌面的截圖,然后在這個新窗體上畫矩形,最后保存矩形中的內容并顯示在原來的聊天窗體中.

  步驟:

  A.新建一個窗體.命名為Catch.然后設置這個窗體的FormBorderStyle為None,WindowState為Maximized.

  B.我們對代碼進行編輯:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace Client
{
  public partial class Catch : Form
  {
    public Catch()
    {
      InitializeComponent();
    }

  用戶變量#region 用戶變量

    private Point DownPoint = Point.Empty;//記錄鼠標按下坐標,用來確定繪圖起點
    private bool CatchFinished = false;//用來表示是否截圖完成
    private bool CatchStart = false;//表示截圖開始
    private Bitmap originBmp;//用來保存原始圖像
    private Rectangle CatchRect;//用來保存截圖的矩形
    #endregion
    //窗體初始化操作
    private void Catch_Load(object sender, EventArgs e)
    {
      this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);
      this.UpdateStyles();
      //以上兩句是為了設置控件樣式為雙緩沖,這可以有效減少圖片閃爍的問題,關于這個大家可以自己去搜索下
      originBmp = new Bitmap(this.BackgroundImage);//BackgroundImage為全屏圖片,我們另用變量來保存全屏圖片
    }
    //鼠標右鍵點擊結束截圖
    private void Catch_MouseClick(object sender, MouseEventArgs e)
    {
      if (e.Button == MouseButtons.Right)
      {
        this.DialogResult = DialogResult.OK;
        this.Close();
      }
    }
    //鼠標左鍵按下時動作
    private void Catch_MouseDown(object sender, MouseEventArgs e)
    {
      if (e.Button == MouseButtons.Left)
      {
        if (!CatchStart)
        {//如果捕捉沒有開始
          CatchStart = true;
          DownPoint = new Point(e.X, e.Y);//保存鼠標按下坐標
        }
      }
    }
    private void Catch_MouseMove(object sender, MouseEventArgs e)
    {
      if (CatchStart)
      {//如果捕捉開始
        Bitmap destBmp = (Bitmap)originBmp.Clone();//新建一個圖片對象,并讓它與原始圖片相同
        Point newPoint = new Point(DownPoint.X, DownPoint.Y);//獲取鼠標的坐標
        Graphics g = Graphics.FromImage(destBmp);//在剛才新建的圖片上新建一個畫板
        Pen p = new Pen(Color.Blue,1);
        int width = Math.Abs(e.X - DownPoint.X), height = Math.Abs(e.Y - DownPoint.Y);//獲取矩形的長和寬
        if (e.X < DownPoint.X)
        {
          newPoint.X = e.X;
        }
        if (e.Y < DownPoint.Y)
        {
          newPoint.Y = e.Y;
        }
        CatchRect = new Rectangle(newPoint,new Size(width,height));//保存矩形
        g.DrawRectangle(p,CatchRect);//將矩形畫在這個畫板上
        g.Dispose();//釋放目前的這個畫板
        p.Dispose();
        Graphics g1 = this.CreateGraphics();//重新新建一個Graphics類
        //如果之前那個畫板不釋放,而直接g=this.CreateGraphics()這樣的話無法釋放掉第一次創建的g,因為只是把地址轉到新的g了.如同string一樣
        g1 = this.CreateGraphics();//在整個全屏窗體上新建畫板
        g1.DrawImage(destBmp,new Point(0,0));//將剛才所畫的圖片畫到這個窗體上
        //這個也可以屬于二次緩沖技術,如果直接將矩形畫在窗體上,會造成圖片抖動并且會有無數個矩形.
        g1.Dispose();
        destBmp.Dispose();//要及時釋放,不然內存將會被大量消耗
      }
    }
    private void Catch_MouseUp(object sender, MouseEventArgs e)
    {
      if (e.Button == MouseButtons.Left)
      {
        if (CatchStart)
        {
          CatchStart = false;
          CatchFinished = true;
        }
      }
    }
    //鼠標雙擊事件,如果鼠標位于矩形內,則將矩形內的圖片保存到剪貼板中
    private void Catch_MouseDoubleClick(object sender, MouseEventArgs e)
    {
      if (e.Button == MouseButtons.Left&&CatchFinished)
      {
        if (CatchRect.Contains(new Point(e.X, e.Y)))
        {
          Bitmap CatchedBmp = new Bitmap(CatchRect.Width, CatchRect.Height);//新建一個于矩形等大的空白圖片
          Graphics g = Graphics.FromImage(CatchedBmp);
          g.DrawImage(originBmp, new Rectangle(0, 0, CatchRect.Width, CatchRect.Height), CatchRect, GraphicsUnit.Pixel);
          //把orginBmp中的指定部分按照指定大小畫在畫板上
          Clipboard.SetImage(CatchedBmp);//將圖片保存到剪貼板
          g.Dispose();
          CatchFinished = false;
          this.BackgroundImage = originBmp;
          CatchedBmp.Dispose();
          this.DialogResult = DialogResult.OK;
          this.Close();
        }
      }
    }
  }
}

?

 C.創建了Catch窗體后,我們在截圖按鈕(位于聊天窗體上)上加入以下事件:

    private void bCatch_Click(object sender, EventArgs e)
    {
      if (bCatch_HideCurrent.Checked)
      {
        this.Hide();//隱藏當前窗體
        Thread.Sleep(50);//讓線程睡眠一段時間,窗體消失需要一點時間
        Catch CatchForm = new Catch();
        Bitmap CatchBmp = new Bitmap(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height);//新建一個和屏幕大小相同的圖片    
        Graphics g = Graphics.FromImage(CatchBmp);
        g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height));//保存全屏圖片
        CatchForm.BackgroundImage = CatchBmp;//將Catch窗體的背景設為全屏時的圖片
        if (CatchForm.ShowDialog() == DialogResult.OK)
        {//如果Catch窗體結束,就將剪貼板中的圖片放到信息發送框中
          IDataObject iData = Clipboard.GetDataObject();
          DataFormats.Format myFormat = DataFormats.GetFormat(DataFormats.Bitmap);
          if (iData.GetDataPresent(DataFormats.Bitmap))
          {
            richtextbox1.Paste(myFormat);
            Clipboard.Clear();//清除剪貼板中的對象
          }
          this.Show();//重新顯示窗體
        }
      }
    }

?

  這樣我們的截圖功能便完成了.

  我想對于初學者來說如何消去第一次繪制的圖片是個比較困難的問題.如果沒有采取措施,你會發現只要你鼠標移動,就會畫一個矩形,這樣便會出現N多的矩形,而我們只是要最后的那一個.

  一般解決這種問題的方法有兩種:

  1.就是在繪制第二個圖形時,我們先用與底色相同的顏色將上次繪制的圖形重新繪制一下.但這往往需要底色為純色時使用.

  2.我們并不直接將圖形畫在畫板上,我們用一個圖片A來保存原畫板上的圖片.然后再新建一個與圖片A相同的圖片B,將我們要繪制的圖形畫在該圖片B上,然后再將該圖片B畫在畫板上.這樣圖片A并沒有被改變.于是第二次畫的時候我們還是同樣新建一個與圖片A相同的圖片進行繪制.那么上一次的圖形就不會被保留下來.問題也就解決了.

  下一次,向大家介紹如何做一個仿windows畫板的程序.

  前幾篇我已經向大家介紹了如何使用GDI+來繪圖,并做了一個截圖的實例,這篇我向大家介紹下如何來做一個類似windows畫圖的工具.

  個人認為如果想做一個功能強大的繪圖工具,那么單純掌握GDI還遠遠不夠,我的目前也只能做一個比較簡單的繪圖工具了.不足之處,歡迎大家討論!

  先來看一下最終效果吧:

c# GDI+簡單繪圖(四)

  主要實現功能:畫直線,矩形,橡皮,圓形,切換顏色,打開圖片,保存圖片,清除圖片,手動調節畫布大小;軟件剛啟動時,為一張空白畫布,我們可以直接在畫布上繪圖,也可以通過菜單中的“打開”,導入一張圖片,然后我們就可以在這張圖片上進行繪制。

  平臺:VS2005 WINFORM

  由于代碼過多,在這里只簡要介紹下制作步驟,提供大家工程下載.

  1.對整個界面進行布局.

  2.實現繪圖工具的功能

  3.實現顏色拾取的功能,這里我們直接拿上次寫的自定義控件來用.

  4.實現菜單功能

  5.實現手動調節畫布大小的功能

  6.測試

  實現繪圖工具的功能

  為了讓代碼藕合度小點,稍許用了些設計模式,因為不是很會,所以代碼還是有點亂亂的,繪圖工具的這些功能塊全部寫在了DrawTools這個類里.那么在主窗體中,只需要調用這個類來完成繪制就行了,而不需要過多的涉及到具體的繪圖代碼。繪圖工具這個類提供的主要工具就是:鉛筆、橡皮、直線、矩形、圓形、實心矩形、實心圓形。關于這些功能塊的代碼,并不難,只要大家對認真看過前幾篇內容,那應該都看得懂。

  這里有幾點要注意:

  1.如何防止記錄不必要的繪圖過程中的痕跡?

  這個問題在第三篇中有提到過,大家不妨先去看看那一篇。為了讓代碼看起來可讀性高點,我設置了兩個Image變量,finishingImg用來保存繪圖過程中的痕跡,orginalImg用來保存已完成的繪圖過程和初始時的背景圖片。

  2.這個類如何與主窗體進行通信?

  當然如果直接將這些功能塊寫在主窗體中自然沒有這個問題。但是那樣代碼會顯得很混雜,如果只是工具代碼出現問題就需要改整個項目。我在這里通過定義方法和屬性,讓主窗體通過給屬性賦值將畫板畫布以及顏色什么的信息傳給這個工具類,然后通過調用相應的工具方法來使用這些工具。

  3.關鍵屬性

  要想讓這些工具能正常使用,必須傳遞給他以下幾樣東西:目標畫板(也就是picturebox),繪圖顏色,原始畫布。

  實現菜單功能

c# GDI+簡單繪圖(四)

  這里就需要我們對文件的操作有一點了解,大家可以去查一下相關資料。

  難點主要就是“打開”這個菜單項的實現

  我們要實現將打開后的圖片在修改后重新保存就必須讓文件在打開后就能關閉,否則就會因為文件打開而無法覆蓋原文件。就會導致編譯時彈出“GDI  一般性錯誤”。所以根據網上其它朋友的做法就是先將打開的圖片通過GDI+將圖片畫到另一個畫布上,然后及時關閉打開的圖片和用來繪制該圖片的畫板。詳見http://www.wanxin.org/redirect.php?tid=3&goto=lastpost

private void openPic_Click(object sender, EventArgs e)
    {
      OpenFileDialog ofd = new OpenFileDialog();//實例化文件打開對話框
      ofd.Filter = "JPG|*.jpg|Bmp|*.bmp|所有文件|*.*";//設置對話框打開文件的括展名
      if (ofd.ShowDialog() == DialogResult.OK)
      {
        Bitmap bmpformfile = new Bitmap(ofd.FileName);//獲取打開的文件
        panel2.AutoScrollPosition = new Point(0,0);//將滾動條復位
        pbImg.Size = bmpformfile.Size;//調整繪圖區大小為圖片大小
        reSize.Location = new Point(bmpformfile.Width, bmpformfile.Height);//reSize為我用來實現手動調節畫布大小用的
        //因為我們初始時的空白畫布大小有限,"打開"操作可能引起畫板大小改變,所以要將畫板重新傳入工具類
        dt.DrawTools_Graphics = pbImg.CreateGraphics();
        Bitmap bmp = new Bitmap(pbImg.Width, pbImg.Height);
        Graphics g = Graphics.FromImage(bmp);
        g.FillRectangle(new SolidBrush(pbImg.BackColor), new Rectangle(0, 0, pbImg.Width, pbImg.Height));//不使用這句話,那么這個bmp的背景就是透明的
        g.DrawImage(bmpformfile, 0, 0,bmpformfile.Width,bmpformfile.Height);//將圖片畫到畫板上
        g.Dispose();//釋放畫板所占資源
        //不直接使用pbImg.Image = Image.FormFile(ofd.FileName)是因為這樣會讓圖片一直處于打開狀態,也就無法保存修改后的圖片
        bmpformfile.Dispose();//釋放圖片所占資源
        g = pbImg.CreateGraphics();
        g.DrawImage(bmp, 0, 0);
        g.Dispose();
        dt.OrginalImg = bmp;
        bmp.Dispose();
        sFileName = ofd.FileName;//儲存打開的圖片文件的詳細路徑,用來稍后能覆蓋這個文件
        ofd.Dispose();
      }
    }

  清除圖像其實就是用白色填充整個畫布,其它的都比較簡單,這就不具體講了。

  實現手動調節畫布大小

  網上有人說使用API,但是個人覺得還是使用其它控件幫忙比較簡單,至少我們還看得懂。

  思路:放置一個picturebox1(尺寸為5*5),將它固定在主畫板的右下角,然后改變鼠標進入時的Cursor為箭頭形狀,設置鼠標按下移動時的事件,讓該picturebox1 跟隨鼠標移動。當鼠標松開時,將主畫板的右下角坐標調整為picturebox1的坐標。

  下面來看下代碼:

  其中的reSize就是我們用來幫忙的picturebox控件 

    private bool bReSize = false;//是否改變畫布大小
    private void reSize_MouseDown(object sender, MouseEventArgs e)
    {
      bReSize = true;//當鼠標按下時,說明要開始調節大小
    }
    private void reSize_MouseMove(object sender, MouseEventArgs e)
    {
      if (bReSize)
      {
        reSize.Location = new Point(reSize.Location.X + e.X, reSize.Location.Y + e.Y);
      }
    }
    private void reSize_MouseUp(object sender, MouseEventArgs e)
    {
      bReSize = false;//大小改變結束
      //調節大小可能造成畫板大小超過屏幕區域,所以事先要設置autoScroll為true.
      //但是滾動條的出現反而增加了我們的難度,因為滾動條上下移動并不會自動幫我們調整圖片的坐標。
      //這是因為GDI繪圖的坐標系不只一個,好像有三個,沒有仔細了解,一個是屏幕坐標,一個是客戶區坐標,還個是文檔坐標。
      //滾動條的上下移動改變的是文檔的坐標,但是客戶區坐標不變,而location屬性就屬于客戶區坐標,所以我們直接計算會出現錯誤
      //這時我們就需要知道文檔坐標與客戶區坐標的偏移量,這就是AutoScrollPostion可以提供的
      pbImg.Size = new Size(reSize.Location.X - (this.panel2.AutoScrollPosition.X), reSize.Location.Y - (this.panel2.AutoScrollPosition.Y));
      dt.DrawTools_Graphics = pbImg.CreateGraphics();//因為畫板的大小被改變所以必須重新賦值
      //另外畫布也被改變所以也要重新賦值
      Bitmap bmp = new Bitmap(pbImg.Width, pbImg.Height);
      Graphics g = Graphics.FromImage(bmp);
      g.FillRectangle(new SolidBrush(Color.White), 0, 0, pbImg.Width, pbImg.Height);
      g.DrawImage(dt.OrginalImg, 0, 0);
      g.Dispose();
      g = pbImg.CreateGraphics();
      g.DrawImage(bmp, 0, 0);
      g.Dispose();
      dt.OrginalImg = bmp;
      bmp.Dispose();
    }

?

  效果如下圖(仔細看白色區域的右下角):

c# GDI+簡單繪圖(四)

  此時就可以通過拖動那個小方塊來調節圖片大小了。

  這樣,主要的問題差不多已經解決了,但還是有不足這處,歡迎大家提出寶貴的意見。

轉載于:https://www.cnblogs.com/zhili/archive/2013/05/24/3096101.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/392086.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/392086.shtml
英文地址,請注明出處:http://en.pswp.cn/news/392086.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mybaties總結+hibernate總結

一、對原生態jdbc程序中問題總結 1.1 jdbc程序 需求&#xff1a;使用jdbc查詢mysql數據庫中用戶表的記錄 statement:向數據庫中發送一個sql語句 預編譯statement&#xff1a;好處&#xff1a;提高數據庫性能。 預編譯statement向數據庫中發送一個sql語句&#xff0c;數據庫編譯…

客戶旅程_我如何充分利用freeCodeCamp的旅程

客戶旅程by Catherine Vassant (aka Codingk8)由凱瑟琳瓦森(Catherine Vassant)(又名Codingk8) 我如何充分利用freeCodeCamp的旅程 (How I made the most out of my freeCodeCamp journey) 我的路線圖&#xff1f; ?超越課程范圍的reeCodeCamp (My road map ?? to freeCode…

Python14 函數

函數 面向對象編程&#xff1a; 類----class 面向過程編程&#xff1a;過程---def 函數式編程&#xff1a;函數---def def test(x):描述x 1return x#def是定義函數的關鍵字#test是函數名稱#&#xff08;x&#xff09;是參數#x1是 函數體&#xff0c;是一段邏輯代碼#return 定義…

學習sql注入:猜測數據庫_面向數據科學家SQL:學習簡單方法

學習sql注入:猜測數據庫We don’t pick a hammer and look for nails — that would be an unusual way of solving problems. The usual way of doing business is to identify the problem first, then look for appropriate tools.我們不用錘子找釘子&#xff0c;那是解決問…

android 百度地圖3.0,android 百度地圖3.0

一&#xff1a;為地圖設置事件注意新版本中要有一個getMapmMapView.getMap().setOnMapStatusChangeListener(listener);OnMapStatusChangeListener listener newOnMapStatusChangeListener() {/*** 手勢操作地圖&#xff0c;設置地圖狀態等操作導致地圖狀態開始改變。* param s…

(摘錄)sockaddr與sockaddr_in,sockaddr_un結構體詳細講解

struct sockaddr { unsigned short sa_family; /* address family, AF_xxx */ char sa_data[14]; /* 14 bytes of protocol address */ }; sa_family是地址家族&#xff0c;一般都是“AF_xxx”的形式。好像通常大多用的是都是AF_INET。 sa_data是14字節協議…

數據挖掘—K-中心點聚類算法(Java實現)

K-中心點聚類算法 &#xff08;1&#xff09;任意選擇k個對象作為初始的簇中心點 &#xff08;2&#xff09;指派每個剩余對象給離他最近的中心點所表示的簇 &#xff08;3&#xff09;選擇一個未被選擇的中心點直到所有的中心點都被選擇過 &#xff08;4&#xff09;選擇一個…

使用akka構建高并發程序_如何使用Akka Cluster創建簡單的應用程序

使用akka構建高并發程序If you read my previous story about Scalachain, you probably noticed that it is far from being a distributed system. It lacks all the features to properly work with other nodes. Add to it that a blockchain composed by a single node is…

pandas之數值計算與統計

數值計算與統計 對于DataFrame來說&#xff0c;求和、最大、最小、平均等統計方法&#xff0c;默認是按列進行統計&#xff0c;即axis 0&#xff0c;如果添加參數axis 1則會按照行進行統計。 如果存在空值&#xff0c;在統計時默認會忽略空值&#xff0c;如果添加參數skipna …

python自動化數據報告_如何:使用Python將實時數據自動化到您的網站

python自動化數據報告This tutorial will be helpful for people who have a website that hosts live data on a cloud service but are unsure how to completely automate the updating of the live data so the website becomes hassle free. For example: I host a websit…

一顆站在技術邊緣的土豆

2012年開始上專業課&#xff0c;2013年打了一年游戲&#xff0c;年底專業課忘光了&#xff0c;但是蒙混過關沒掛科&#xff0c;2014年7月份畢業&#xff0c;對這個社會充滿向往。2014年9月份——方正代理商做網絡安全公司。2015年3月份跳槽到一家vmware代理商公司。2016年6月&a…

leetcode 839. 相似字符串組(并查集)

如果交換字符串 X 中的兩個不同位置的字母&#xff0c;使得它和字符串 Y 相等&#xff0c;那么稱 X 和 Y 兩個字符串相似。如果這兩個字符串本身是相等的&#xff0c;那它們也是相似的。 例如&#xff0c;“tars” 和 “rats” 是相似的 (交換 0 與 2 的位置)&#xff1b; “r…

android intent參數是上次的結果,【Android】7.0 Intent向下一個活動傳遞數據、返回數據給上一個活動...

1.0 可以利用Intent吧數據傳遞給上一個活動&#xff0c;新建一個叫“hellotest01”的項目。新建活動FirstActivity&#xff0c;勾選“Generate Layout File”和“Launcher Activity”。image修改AndroidMainifest.xml中的內容&#xff1a;android:name".FirstActivity&quo…

實習一年算工作一年嗎?_經過一年的努力,我如何找到軟件工程工作

實習一年算工作一年嗎?by Andrew Ngo通過安德魯恩戈 經過一年的努力&#xff0c;我如何找到軟件工程工作 (How I landed a software engineering job after a year of hard work) Many of us think the path to becoming a software engineer requires years of education an…

學習深度學習需要哪些知識_您想了解的有關深度學習的所有知識

學習深度學習需要哪些知識有關深層學習的FAU講義 (FAU LECTURE NOTES ON DEEP LEARNING) Corona was a huge challenge for many of us and affected our lives in a variety of ways. I have been teaching a class on Deep Learning at Friedrich-Alexander-University Erlan…

參加開發競賽遇到的問題【總結】

等比賽完就寫。 轉載于:https://www.cnblogs.com/jiangyuanjia/p/11261978.html

html5--3.16 button元素

html5--3.16 button元素 學習要點 掌握button元素的使用button元素 用來建立一個按鈕從功能上來說&#xff0c;與input元素建立的按鈕相同button元素是雙標簽&#xff0c;其內部可以配置圖片與文字&#xff0c;進行更復雜的樣式設計不僅可以在表單中使用&#xff0c;還可以在其…

如何注冊鴻蒙id,鴻蒙系統真機調試證書 和 設備ID獲取

鴻蒙系統真機調試創建項目創建項目創建應用創建鴻蒙應用(注意&#xff0c;測試階段需要發郵件申請即可)關聯應用項目進入關聯 添加引用準備調試使用的 p12 和證書請求 csr使用以下命令// 別名"test"可以修改&#xff0c;但必須前后一致&#xff0c;密碼請自行修改key…

Java—實現 IOC 功能的簡單 Spring 框架

編寫一個實現 IOC 功能的簡單 Spring 框架&#xff0c;包含對象注冊、對象管理、及暴 露給外部獲取對象的功能&#xff0c;并編寫測試程序。擴展注冊器的方式&#xff0c;要求采用 XML 和 txt 文件。 源代碼 package myspring;import java.lang.reflect.Method; import java.…

讀zepto核心源碼學習JS筆記(3)--zepto.init()

上篇已經講解了zepto.init()的幾種情況,這篇就繼續記錄這幾種情況下的具體分析. 1. 首先是第一種情況,selector為空 既然是反向分析,那我們先看看這句話的代碼; if (!selector) return zepto.Z() 這里的返回值為zepto.Z();那我們繼續往上找zepto.Z()函數 zepto.Z function(dom…