1

矢印キーを1つずつクリックしてからクリックしてからもう一度クリックすると、画像が変化します。しかし、右矢印キーをノンストップで押し続けると、右矢印キーを停止したままにして、このtrackBar値の画像がロードされた場合にのみ、画像が変化します。

これは私のスクロールイベントです:

private void trackBar1_Scroll(object sender, EventArgs e)
{   
    currentFrameIndex = trackBar1.Value;
    textBox1.Text = "Frame Number : " + trackBar1.Value;
    wireObject1.woc.Set(wireObjectAnimation1.GetFrame(currentFrameIndex)); 
    LoadPictureAt(trackBar1.Value, sender);

    button1.Enabled = false;
    button2.Enabled = false;
    button3.Enabled = false;
    button4.Enabled = false;
    button8.Enabled = false;
    SaveFormPicutreBoxToBitMapIncludingDrawings();
    return;
}

これまでのところ、trackBarの他のイベントはありません。

これはLoadPictureAt関数です。

private bool LoadPictureAt(int nIndex, object c)
{
    bool bRet = false;
    if (nIndex >= 0 && nIndex < fi.Length)
    {
        if (c.Equals(trackBar1))
            pictureBox1.Load(fi[nIndex].FullName);
        bRet = true;
    }   
    return bRet;
}

私はそれを解決しました:

スクロールイベントの前に新しい関数を追加しました。

private void setpicture(int indx)
        {
            if (fi == null)
            {

            }
            else
            {
                if (indx >= 0 && indx <= trackBar1.Maximum && fi.Length > indx)
                {
                    try
                    {
                        label19.ForeColor = Color.Red;
                        fileToolStripMenuItem.Enabled = true;
                        label19.Visible = false;
                        label20.Visible = false;
                        label14.Visible = true;
                        label15.Visible = true;
                        label8.Visible = true;
                        label9.Visible = true;

                        trackBar1.Enabled = true;
                        using (FileStream fs = new FileStream(fi[indx].FullName, FileMode.Open))
                        {
                            this.label8.Visible = true;
                            this.label9.Visible = true;
                            this.label9.Text = fi[indx].Name;
                            Image img = null;
                            Bitmap bmp = null;
                            Image imgOLd = null;

                            try
                            {


                                img = Image.FromStream(fs);
                                bmp = new Bitmap(img);

                                imgOLd = this.pictureBox1.Image;
                                this.pictureBox1.Image = bmp;
                                if (imgOLd != null)
                                    imgOLd.Dispose();

                                img.Dispose();
                                img = null;
                            }
                            catch
                            {
                                if (img != null)
                                    img.Dispose();
                                if (bmp != null)
                                    bmp.Dispose();
                                if (imgOLd != null)
                                    imgOLd.Dispose();
                            }
                        }
                    }
                    catch
                    {

                    }
                }
                else
                {
                    Image imgOLd = this.pictureBox1.Image;


                    if (imgOLd != null)
                    {
                        imgOLd.Dispose();
                        imgOLd = null;
                    }

                    Application.DoEvents();
                }
            }
        }

そして、スクロールイベントを次のように変更しました。

private void trackBar1_Scroll(object sender, EventArgs e)
        {

            currentFrameIndex = trackBar1.Value;
            textBox1.Text = "Frame Number : " + trackBar1.Value;
            wireObject1.woc.Set(wireObjectAnimation1.GetFrame(currentFrameIndex)); 

            trackBar1.Minimum = 0;
            trackBar1.Maximum = fi.Length - 1;
            setpicture(trackBar1.Value);
            pictureBox1.Refresh();

            button1.Enabled = false;
            button2.Enabled = false;
            button3.Enabled = false;
            button4.Enabled = false;
            button8.Enabled = false;
            SaveFormPicutreBoxToBitMapIncludingDrawings();
            return;









        }
4

1 に答える 1

0

カーソルキーを押したままにしたり、できるだけ速く叩いたりすると、「ノンストップ」というようなことはありません。そのためのKeyDownイベントは、現代のCPUに対して氷河のペースで生成されます。1秒あたり約20ヒット、各ヒットの間隔が50ミリ秒よりもはるかに優れていることはありません。最新のコアは、キーストローク間で1億の命令を簡単に実行できます。

ただし、重要なのは、その膨大なリソースをどのように処理するかです。残念ながら、あまり多くのことをしていません。Scrollイベントでこのディスクをヒットしています。Image.Load()を呼び出し、そのように見えるのはImage.Save()です。これらは、ディスクが回転する速度でしか実行できないメソッドであり、CPUは、ディスクがそのジョブを実行するのを待機している間、何も有用なことをしていません。機械的なイベントが発生するのを待つために、1億CPUサイクルが無駄になりました。

そこから実際に悪化します。次に発生するのは、Winformsがディスクから取得した画像でウィンドウをペイントする必要があることです。ペイントは優先度の低い操作であり、これ以上重要なことを行う必要がない場合にのみ実行されます。

問題は、やらなければならないもっと重要なことがあるということです。ディスクが画像を取得/保存するのを待つのに非常に時間がかかったため、Winformsメッセージループが次に遭遇するのは、ペイントよりも重要なことです。入力イベント、次のキーストローク。

これが適切に実行されると、画像ボックスに実際に画像が割り当てられます。画面にペイントされていないため、表示されません。カーソルキーとbamを押すのをやめ、時間とペイントができました。

これはすべて設計によるものです。画像ボックスのUpdate()メソッドを呼び出すことで、強制的に再描画できます。これで、ユーザーは確実に画像を見ることができます。しかし、それも実際にはうまく機能しません。プログラムが遅れ始めます。キーストロークはメッセージキューにバッファリングされ、キーを離した後もプログラムは画像を更新し続けます。

あなたの毒を選んでください。

于 2012-07-22T21:44:40.307 に答える