3

私は4つPictureBoxes(各PictureBoxは1つのサイコロを表します)と、100ミリ秒ごとにソース画像を変更するタイマーList<Bitmap> imagesLoadedFromIncludedResources(としてメモリにロードされます)を持っています。

ここに画像の説明を入力

コード:

private List<PictureBox> dices = new List<PictureBox>();

private void timer_diceImageChanger_Tick(object sender, EventArgs e)
{
    foreach (PictureBox onePictureBox in dices)
    {
        oneDice.WaitOnLoad = false;
        onePictureBox.Image = //... ;
        oneDice.Refresh();
    }
}  

一度にすべての画像を変更する必要があります。この時点で、画像が左から右に少し遅れて変更されていることがわかります。

Threadそれぞれに1つずつバリアントを試しました(この回答の方法をPictureBox使用)-視覚的には少し良くなりますが、完全ではありません。Control.Invoke

4

3 に答える 3

4

フォームのレイアウトロジックを一時停止してみてください。

SuspendLayout();
// set images to pictureboxes
ResumeLayout(false);
于 2013-01-20T22:57:01.427 に答える
0

私はこれに別の方法でアプローチします。WinFormsのもので遊んでからしばらく経ちますが、おそらく画像のレンダリングをより細かく制御できるでしょう。

この例では、すべての画像を1つのソースビットマップに垂直にスタックし、アセンブリのリソースとして保存しています。

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private Timer timer;

        private Bitmap dice;

        private int[] currentValues = new int[6];

        private Random random = new Random();

        public Form1()
        {
            InitializeComponent();
            this.timer = new Timer();
            this.timer.Interval = 500;
            this.timer.Tick += TimerOnTick;

            this.dice = Properties.Resources.Dice;
        }

        private void TimerOnTick(object sender, EventArgs eventArgs)
        {
            for (var i = 0; i < currentValues.Length; i++)
            {
                this.currentValues[i] = this.random.Next(1, 7);
            }

            this.panel1.Invalidate();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (this.timer.Enabled)
            {
                this.timer.Stop();
            }
            else
            {
                this.timer.Start();
            }
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.Clear(Color.White);

            if (this.timer.Enabled)
            {
                for (var i = 0; i < currentValues.Length; i++)
                {
                    e.Graphics.DrawImage(this.dice, new Rectangle(i * 70, 0, 60, 60), 0, (currentValues[i] - 1) * 60, 60, 60, GraphicsUnit.Pixel);
                }
            }
        }
    }
}

それが役立つ場合、ソースはここにあります:http ://sdrv.ms/Wx2Ets

于 2013-01-20T23:03:37.850 に答える
0
Parallel.ForEach
(
    dices,
    new ParallelOptions { MaxDegreeOfParallelism = 4 },
    (dice) =>
    {
        dice.Image = ...;
        dice.WaitOnLoad = false;
        dice.Refresh();
    }
);

問題は、UI コントロールが UI スレッドからしかアクセスできないことです。このアプローチを使用する場合は、PictureBox のコピーを作成し、操作が完了したら UI のものを置き換える必要があります。

もう 1 つのアプローチは、2 つの PictureBoxes を作成し、最初の 1 つをもう 1 つの上に配置することです (後者を非表示にします)。すべての画像を変更し、処理が完了したら、後ろのすべての画像を繰り返します。それらを上に置くと、遅延が少なくなります。

于 2013-01-20T22:49:57.017 に答える