如何使用C#并行绘制两个不同的图形 [英] How the two different graphics plots in parallel using C#

查看:133
本文介绍了如何使用C#并行绘制两个不同的图形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问候每个人,



我需要帮助以使用图像上的相同数据并行绘制两个图形(不同样式(点和矩形点)图)。此GUI程序按以下方式执行:



1.读取文本文件包含必须在图片文件中绘制的数据点,该文件加载到图片框中。



2.程序使用单击按钮和复选框。



3.点击按钮后程序执行从绘制第一个图形开始,但是当选中复选框时,第二个图形绘图与第一个图形并行启动,当取消选中复选框时,第二个图形绘图停止。(两个图形样式使用相同的文本文件)。



4.第二个图形实际上绘制了第一个图形的轨迹(连续图/跟踪图)。当用户想要观察时轨迹(跟踪图)所以检查t他复选框。



5.我使用线程技术读取文本文件并在点击按钮下激活此线程。



我需要帮助在这种情况下做什么,我应该为复选框创建单独的线程,用于与第一个图形并行绘制第二个图形吗?



这里我正在共享我的代码块,我试图实现但是它首先绘制图形,当选中复选框时,程序会连续绘制第一个和第二个图形,这不符合我的程序要求。当复选框被选中时,我想连续绘制矩形点(轨迹图)作为第二个图形。



请帮助!



我的尝试:



  public   partial   class  Form1:Form 
{
double x;
double y;
线程T;
int F;
委托 void refresh();
private System.Drawing.Graphics g;


public Form1()
{
InitializeComponent();
}

void refresh_PicBox()
{
if (pictureBox1.InvokeRequired)
{
refresh r = new refresh(refresh_PicBox);
pictureBox.Invoke(r);
}
else
{
pictureBox.Refresh();
}
}

public void 块( )
{
StreamReader file = new StreamReader( @ C:\Text.txt);
string 行;
int sc = 100 ;

while ((line = file.ReadLine())!= null
{
char [] del = new char [] {' \t'};
string [] part = line.Split(del,StringSplitOptions.RemoveEmptyEntries);

w = Convert.ToDouble(部分[ 0 ])* sc;
z = Convert.ToDouble(部分[ 1 ])* sc;

g = pictureBox.CreateGraphics();
if (flag == 0
{
g。 DrawImage( new 位图( @ C:\ interface .png),Convert.ToInt32(w),Convert.ToInt32(z), 20 20 );
Thread.Sleep( 50 );
refresh_PicBox(); // 调用刷新图片框

}
if (flag == 1
{
g.DrawImage( new 位图( @ C:\\ \\ interface.png),Convert.ToInt32(w),Convert.ToInt32(z), 20 20 );
refresh_PicBox();
g.FillRectangle(Brushes.Blue,Convert.ToInt32(w),Convert.ToInt32(z), 9 9 );
Thread.Sleep( 50 );
}
}
}

private void Form1_Load( object sender,EventArgs e)
{
pictureBox.Image = new 位图( @ C:\ Image.jpg);
}

private void button_Click( object sender,EventArgs e)
{
T = new 线程(块);
T.Start();
flag = 0 ;
}

private void checkBox_CheckedChanged( object sender,EventArgs e)
{
if (checkBox.Checked)
{
flag = 1 ;
}
其他
{
flag = 0 ;
}
}
}

解决方案

我会:

1.有一个用于在目标图片框上渲染的类对象

2.为图像中的每个绘图创建一个对象,绘制点,&目标画布(PictureBox)

3.启动计时器并在每个刻度上,询问每个(取决于CheckBox)绘制下一个点



这样会:

1.删除需要使用线程

2.计时器控制更新频率,不再有Thread.Sleep(...)

3.删除重复的代码

4.将相关代码组合在一起,使其更易于阅读和调试



所以你会结束这样的事情:

  public   partial   class  Form1:表格
{
public Form1()
{
InitializeComponent();
LoadSeries();
HookTimer();
}

private void butPlot_Click( object sender,EventArgs e)
{
completedCount = 0 ;
plotTimer.Start();
}

私人列表<系列>系列;

private void LoadSeries()
{
Series = new 列表<系列>
{
new 系列(picPlotCanvas,MarkerType.Rectangle,Color.Blue)
{
Points = new 列表< PointF>
{
new PointF(0f,0f),
new PointF(1f,1f),
new PointF(2f,2f),
new PointF(3f,3f),
}
},
new 系列(picPlotCanvas,MarkerType.Triangle,Color.Red )
{
Points = new List< PointF>
{
new PointF(0f,0f),
new PointF(1f,1f),
new PointF(2f,2f),
new PointF(3f,3f),
}
}
};

foreach var series 系列)
{
series.Done + = Series_Done;
}
}

private int completedCount;
private void Series_Done( object sender,EventArgs e)
{
completedCount ++;
}

// 每100ms更新一次
private readonly 计时器plotTimer = 计时器{ Interval = 100 };

private void HookTimer()
{
plotTimer.Tick + = Timer_Tick;
}

private void Timer_Tick( object sender,EventArgs e)
{
if (chkDualPlot.Checked?completedCount < Series.Count:completedCount == 0
{
Series [ 0 ] NextPoint公司();

// 我们是否绘制了第二个系列?
< span class =code-keyword> if
(chkDualPlot.Checked)
Series [ 1 ]。NextPoint();
}
其他
{
// < span class =code-comment>我们已经完成了!
plotTimer.Stop();
}
}
}

内部 枚举 MarkerType
{
矩形,
三角形
}

内部 class 系列
{
public 系列(PictureBox画布,MarkerType标记)
(canvas,marker,Color.Red){}

public 系列(PictureBox画布,MarkerType标记,颜色)
{
.canvas = canvas;
Marker = marker;
颜色=颜色;
}

public event EventHandler完成;

public MarkerType Marker { get ; set ; }
public 颜色颜色{ get ; set ; }
public 列表< PointF>点数{获取; set ; }

私人 PictureBox画布;
private int currentIndex;

public void NextPoint()
{
if (Points == null
throw new NoNullAllowedException();

if (currentIndex < Points.Count)
{
// 在画布上绘制点
Debug.WriteLine(


绘图点:{currentIndex}标记:{Marker.ToString()});

currentIndex ++;
}
else
{
currentIndex = 0 ;
完成?.Invoke( this ,EventArgs.Empty);
}
}
}



我将把绘图部分留给你实施。 :)


Greetings Everyone,

I need help to plot two graphics (of a different style (point and rectangular dot) plot in parallel using same data on an image. This GUI program executes in the following way:

1. Reads text file contains the data points which have to be plotted on an image file which loads in picture Box.

2. The program uses click button and the check box.

3. After clicking up the button the program execution started with the plotting of the First graphic, however when the check box is checked the second graphic plotting started in parallel with the first graphic, and when the check box unchecked the second graphic plotting stopped. (Both of the graphics style using the same text file).

4. The second graphic actually plots the trajectory (continuous plot /tracking plot) of the first graphic. As when the user wants to observe the trajectory(tracking plot) so check the check box.

5. I used the threading technique to read a text file and activates this thread under click button.

I need help what to do in this case, should I create the separate thread for check box for plotting the second graphic in parallel with the first graphic?

here I am sharing a block of my code, which I tried to implement but it plots first graphic and when the check box is checked the program plots the first and second graphic continuously which does not meet my program requirement. I want to plot the rectangular dot continuously (track plot) as the second graphic when the check box is checked.

Please help!

What I have tried:

public partial class Form1 : Form
{ 
    double x;
    double y;
    Thread T;
    int F;
    delegate void refresh();
    private System.Drawing.Graphics g;
    

    public Form1()
    {
        InitializeComponent();
    }

    void refresh_PicBox()
    {
        if (pictureBox1.InvokeRequired)
        {
            refresh r = new refresh(refresh_PicBox);
            pictureBox.Invoke(r);
        }
        else
        {
            pictureBox.Refresh();
        }
    }

    public void block()
    {
        StreamReader file = new StreamReader(@"C:\Text.txt");
        string line;
        int sc = 100;
       
        while ((line = file.ReadLine()) != null)
        {
            char[] del = new char[] { '\t' };
            string[] part = line.Split(del, StringSplitOptions.RemoveEmptyEntries);

            w = Convert.ToDouble(part[0]) * sc;
            z = Convert.ToDouble(part[1]) * sc;

            g = pictureBox.CreateGraphics();
            if (flag == 0)
            {
                g.DrawImage(new Bitmap(@"C:\interface.png"), Convert.ToInt32(w), Convert.ToInt32(z), 20, 20);
                Thread.Sleep(50);
                refresh_PicBox();// invoke for refreshing picture box

            }
            if (flag == 1)
            {
             g.DrawImage(new Bitmap(@"C:\interface.png"), Convert.ToInt32(w), Convert.ToInt32(z), 20, 20);
             refresh_PicBox();
             g.FillRectangle(Brushes.Blue, Convert.ToInt32(w), Convert.ToInt32(z), 9, 9); 
             Thread.Sleep(50);
            }
        }
    }
    
    private void Form1_Load(object sender, EventArgs e)
    {
        pictureBox.Image = new Bitmap(@"C:\Image.jpg");
    }
    
    private void button_Click(object sender, EventArgs e)
    {
        T = new Thread(block);
        T.Start();
        flag = 0;
    }

    private void checkBox_CheckedChanged(object sender, EventArgs e)
    {
        if (checkBox.Checked)
        {
            flag = 1;
        }
        else
        {
            flag = 0;
        }
    }
}

解决方案

I would:
1. have a class object that is used to render on the destination picturebox
2. create an object for each plot passing in the image, plot points, & destination canvas(PictureBox)
3. Start a timer and on each tick, ask each (dependent on the CheckBox) to plot the next point

This would:
1. remove the need to use threads
2. timer controls the update frequency, no more Thread.Sleep(...)
3. remove duplicate code
4. group related code together making it easier to read and debug

So you would end up with something like this:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        LoadSeries();
        HookTimer();
    }

    private void butPlot_Click(object sender, EventArgs e)
    {
        completedCount = 0;
        plotTimer.Start();
    }

    private List<Series> Series;

    private void LoadSeries()
    {
        Series = new List<Series>
        {
            new Series(picPlotCanvas, MarkerType.Rectangle, Color.Blue)
            {
                Points = new List<PointF>
                {
                    new PointF(0f, 0f),
                    new PointF(1f, 1f),
                    new PointF(2f, 2f),
                    new PointF(3f, 3f),
                }
            },
            new Series(picPlotCanvas, MarkerType.Triangle, Color.Red)
            {
                Points = new List<PointF>
                {
                    new PointF(0f, 0f),
                    new PointF(1f, 1f),
                    new PointF(2f, 2f),
                    new PointF(3f, 3f),
                }
            }
        };

        foreach (var series in Series)
        {
            series.Done += Series_Done;
        }
    }

    private int completedCount;
    private void Series_Done(object sender, EventArgs e)
    {
        completedCount++;
    }

    // update every 100ms
    private readonly Timer plotTimer = new Timer { Interval = 100 };

    private void HookTimer()
    {
        plotTimer.Tick += Timer_Tick;
    }

    private void Timer_Tick(object sender, EventArgs e)
    {
        if (chkDualPlot.Checked ? completedCount < Series.Count : completedCount == 0)
        {
            Series[0].NextPoint();

            // do we plot the second series?
            if (chkDualPlot.Checked)
                Series[1].NextPoint();
        }
        else
        {
            // We're done!
            plotTimer.Stop();
        }
    }
}

internal enum MarkerType
{
    Rectangle,
    Triangle
}

internal class Series
{
    public Series(PictureBox canvas, MarkerType marker)
        : this(canvas,marker,Color.Red) { }

    public Series(PictureBox canvas, MarkerType marker, Color color)
    {
        this.canvas = canvas;
        Marker = marker;
        Color = color;
    }

    public event EventHandler Done;

    public MarkerType Marker { get; set; }
    public Color Color { get; set; }
    public List<PointF> Points { get; set; }

    private PictureBox canvas;
    private int currentIndex;

    public void NextPoint()
    {
        if (Points == null)
            throw new NoNullAllowedException();

        if (currentIndex < Points.Count)
        {
            // Draw point on canvas
            Debug.WriteLine(


"plotting point: {currentIndex} Marker: {Marker.ToString()}"); currentIndex++; } else { currentIndex = 0; Done?.Invoke(this, EventArgs.Empty); } } }


I'll leave the drawing part up to you to implement. :)


这篇关于如何使用C#并行绘制两个不同的图形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆