为什么在VisualC#中我无法将像素写入picturebox?

为什么在VisualC#中我无法将像素写入picturebox?,c#,C#,我正在编写一个仿真程序,虚拟显示器应该能够接收3字节的颜色数据并显示正确的颜色像素,类似于真实屏幕的工作方式。但是当我设置一些滚动条来测试像素的生成时,什么都没有发生。这是我的代码和表单的屏幕截图: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.

我正在编写一个仿真程序,虚拟显示器应该能够接收3字节的颜色数据并显示正确的颜色像素,类似于真实屏幕的工作方式。但是当我设置一些滚动条来测试像素的生成时,什么都没有发生。这是我的代码和表单的屏幕截图:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;




namespace TSC_Multi_System_Emulator
{

    public partial class Form1 : Form
    {
        private PictureBox Display = new PictureBox();
        string @emulationfolderpath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        Bitmap screen = new Bitmap(@Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Resource_Folder\" + @"FirstFrame.bmp");
        int x = 0;
        int y = 0;

        public Form1()
        {
            InitializeComponent();

        }
        private void Form1_Load(object sender, System.EventArgs e) {
            // Dock the PictureBox to the form and set its background to black.
            Display.BackColor = Color.Black;
            // Connect the Paint event of the PictureBox to the event handler method.

            // Add the PictureBox control to the Form. 
            this.Controls.Add(Display);


        }
        public void DigitalGraphicsDisplay(int red, int green, int blue) {
            Graphics g = Display.CreateGraphics(); 
            screen.SetPixel(x, y, Color.FromArgb(red, green, blue));
            g.DrawImage(screen, 0, 0, screen.Width, screen.Height);
            g.Save();
            if (x < screen.Width)
            {
                x = x + 1;
            }
            else if (x == screen.Width)
            {
                x = 0;
                if (y < screen.Height)
                {
                    y = y + 1;
                }
                else if (y == screen.Height)
                {
                    y = 0;
                }
            }
        }



        private void button1_Click(object sender, EventArgs e){
            int rchannel = redControl.Value;
            int gchannel = greenControl.Value;
            int bchannel = blueControl.Value;             
            DigitalGraphicsDisplay(rchannel, gchannel, bchannel);
        }




    }
}
}

我得到的只是一个没有其他东西的白色图片盒。。。
(渐变代码确实有效)

看起来您正试图直接在PictureBox控件本身上绘制

相反,您应该将图像指定给PictureBox,然后在图像上绘制

尝试更改代码,如下所示。(包括测试的点击事件。)
注意,PictureBox保留了对图像的直接引用,因此您不需要在类中使用单独的屏幕图像,除非您有不同的用途

此外,它使用
Bitmap.SetPixel()
,这是一种非常慢的像素设置方法。在这些其他链接中,有一种更快但稍微更复杂的方式:

记住,单击按钮一次只能绘制一个像素。
因此,请务必仔细查看:

在click事件中运行我的测试代码将产生以下结果:

所有可能的错误一蹴而就

  • 切勿使用
    CreateGraphics
    绘制持久图形!始终进行
    绘制
    事件或将绘制到图像中

  • Graphics.Save
    不保存任何绘制的像素。它保存图形对象的状态,该对象不包含图形,但是写入相关位图的工具。状态包括缩放、旋转、平滑模式,然后是一些

您已经在位图中写入内容,因此只需将其设置为新的
PictureBox.Image

PictureBox.BackgroundImage

正如我所说的,你可以在PBox的表面上写上这两个字。为此,请使用
Paint
事件、
Invalidate
触发它,并使用类级变量保存必要的数据

后者用于变化很大的图形,前两个用于累积变化


控件。CreateGraphics
仅用于瞬态图形,如橡皮筋线或光标十字。

缩短代码示例。例如,退出事件不是理解所必需的,也无助于解决您的问题。我用您的代码替换了我的函数,但它仍然没有做任何事情。。。还有,你为什么要画一个矩形?我只想一次画一个像素,你唯一能想到的方法就是画一个非常小的矩形吗?我有点困惑:(请参阅我答案中的更新代码。我对其进行了测试,它与显示您应该看到的内容的屏幕截图一起工作。为了简单起见,我将代码切换回SetPixel,尽管这样速度慢得多,但请参阅链接以获得更好的方式。此外,我简化了您的x,y增量代码。此外,您的单击事件一次只绘制一个像素,因此,您可以需要仔细查看。查看更改。请参阅屏幕截图以供参考。我提供了一个测试示例,可以更改整个图像,但由于设置像素的原因,速度会有点慢。如果这对您有效,请不要忘记标记为已回答,谢谢。您的代码可以工作,但我的按钮测试仍然无法工作,以下是我的按钮测试无法工作的代码:
private void button1\u Click(对象发送方,事件参数e){Boolean a=false;int b=0;do{DigitalGraphicsDisplay(51153102);if(b==10000){a=true;}b=b+1;}while(a);}
它显示的是一个白色的图片框…它工作正常,但you's loop设计为只运行一次,在左上角只更改了一个像素(很难看到)。更改代码,使
a
变量设置为
true
,直到
b==10000
,然后将其设置为
false
。而循环仅在条件==true时运行。我将在上面答案的底部放置一个代码的工作副本。PS:一旦成功,别忘了将其标记为已回答。我们仍然可以如果你愿意,我会在之后讨论你的设计。这很有效!!!非常感谢你的帮助,你真的为我省了很多麻烦,我不敢相信我把while循环搞砸了。当一双新眼睛检查错误时,这真的很有帮助:)你在图像中画图是什么意思,我想我对你的意思有点了解,但我的代码仍然不起作用…你能给我一个代码示例吗?它意味着使用相关的图形对象来更改位图的像素。关系由
Graphics G=Graphics.FromImage(someBitmap)创建
。你在问题的原始、较长版本中有这样的代码,想想看。在控件表面绘制和位图绘制的区别已经解释了-要更改像素,你可以在位图上使用
SetPixel
,或者
e.Graphics.FillRectangle(画笔,x,y,1,1)
在控件的
绘制事件中..靠近代码一点我想知道应该显示什么:每个按钮点击一个像素,对吗?上一个像素应该仍然存在还是应该清除?上一个像素应该仍然存在,它应该自动前进到下一个像素值,(它应该异步工作)
public partial class Form1 : Form
{

    string @emulationfolderpath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
    Bitmap screen = new Bitmap(@Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Resource_Folder\" + @"FirstFrame.bmp");
    int x = 0;
    int y = 0;

    public Form1()
    {
        InitializeComponent();

    }
    private void Form1_Load(object sender, System.EventArgs e) {
        // Dock the PictureBox to the form and set its background to black.
        Display.BackColor = Color.Black;
        // Connect the Paint event of the PictureBox to the event handler method.

        // Add the PictureBox control to the Form. 
        this.Controls.Add(Display);


    }

    public void DigitalGraphicsDisplay(int red, int green, int blue)
    {
        if (Display.Image == null)
        {
            Bitmap NewBMP = new Bitmap(Display.ClientRectangle.Width, Display.ClientRectangle.Height);
            using (Graphics g = Graphics.FromImage(NewBMP))
            {
                g.Clear(Color.White);
            }
            Display.Image = NewBMP;
        }

        (Display.Image as Bitmap).SetPixel(x, y, Color.FromArgb(red, green, blue));

        Display.Invalidate();

        x++;

        if (x >= Display.Image.Width)
        {
            x = 0;
            y++;

            if (y >= Display.Image.Height)
            {
                y = 0;
            }
        }
    }


    private void button1_Click(object sender, EventArgs e){
        Boolean a = false;
        int b = 0;
        do
        {
            DigitalGraphicsDisplay(51, 153, 102);
            if (b == 10000)
            {
                a = true;
            }
            b = b + 1;
        } while (a);

    }





}
int x = 0;
int y = 0;
public void DigitalGraphicsDisplay(int red, int green, int blue)
{
    if (Display.Image == null)
    {
        Bitmap NewBMP = new Bitmap(Display.ClientRectangle.Width, Display.ClientRectangle.Height);
        using (Graphics g = Graphics.FromImage(NewBMP))
        {
            g.Clear(Color.White);
        }
        Display.Image = NewBMP;
    }

    (Display.Image as Bitmap).SetPixel(x, y, Color.FromArgb(red, green, blue));

    Display.Invalidate();

    x++;

    if (x >= Display.Image.Width)
    {
        x = 0;
        y++;

        if (y >= Display.Image.Height)
        {
            y = 0;
        }
    }
}

private void button1_Click(object sender, EventArgs e)
{
    // Temporary code to show that it works (Due to Bitmap.SetPixel() it will be slow)
    for (int I = 1; I < Display.ClientRectangle.Width * Display.ClientRectangle.Height; I++)
        DigitalGraphicsDisplay((I/255)%255, (I % Display.ClientRectangle.Width) % 255, 127);
}
private void button1_Click(object sender, EventArgs e)
{ 
    Boolean a = true; 
    int b = 0; 
    do
    { 
        DigitalGraphicsDisplay(51, 153, 102); 

        if (b == 10000) 
        {
            a = false;
        } 

        b = b + 1; 
    } while (a); 
}
    public void DigitalGraphicsDisplay(int red, int green, int blue) {
        Graphics g = Display.CreateGraphics(); 
        screen.SetPixel(x, y, Color.FromArgb(red, green, blue));
        g.DrawImage(screen, 0, 0, screen.Width, screen.Height);
        g.Save();