C # Прозрачные панели Проблемы с обновлением - PullRequest
0 голосов
/ 05 июня 2011

В настоящее время я работаю над проектом, который требует анимации на прозрачной панели. Мне удалось создать прозрачную панель и рисовать на ней, но когда я обновляю панель, где я рисовал с помощью инструмента «Перо», она не перерисовывается как прозрачная. Это оставляет последнюю позицию того, что я нарисовал ранее, на панели.

Я предполагаю, что есть простой способ переопределить OnPaint или Refresh, чтобы перерисовать все пиксели на панели как прозрачные, но я не могу найти решение онлайн или выяснить это сам.

Вот код, который я использовал, чтобы сделать фон прозрачным:

public class TransparentPanel : Panel
{
    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x20;
            return cp;
        }
    }

    protected override void OnPaintBackground(PaintEventArgs e)
    {
    }
 }

Это была моя лучшая неудачная попытка перерисовать фон как прозрачный:

protected override void OnPaint(PaintEventArgs pe)
{
        pe.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(100,255,255,255)), this.ClientRectangle);
}

Проблема с этим решением заключается в том, что после обновления пары фон становится непрозрачным белым.

Может кто-нибудь помочь мне понять, как это сделать? Я супер новичок в графике и анимации, и я предполагаю, что это довольно простой ответ. Заранее спасибо.


* ***** 1019 1020 * EDIT *** Согласно ответу Dyppl, я изменил способ рисования графики на панели. Вот мой текущий код:

    public TransparentPanel fighterPanel;
...
    fighterPanel.Paint +=new PaintEventHandler(fighterPanel_Paint);
...
    fighterPanel = new TransparentPanel();
    fighterPanel.Location = new System.Drawing.Point(600, 300);
    fighterPanel.Size = new System.Drawing.Size(400, 400);
    gameArenaForm.Controls.Add(fighterPanel);
    fighterPanel.BringToFront();        
...
    private void fighterPanel_Paint(object sender, PaintEventArgs e)
    {
        using (Pen blackPen = new Pen(Color.Black, 3), redPen = new Pen(Color.Red, 3), bluePen = new Pen(Color.Blue, 3))
        {
            //head     
            e.Graphics.DrawEllipse
                (blackPen,
                head.DrawPoint(torso.GetTorsoAngle(), torso.neck.getLocationX(), torso.neck.getLocationY()).X,
                head.DrawPoint(torso.GetTorsoAngle(), torso.neck.getLocationX(), torso.neck.getLocationY()).Y,
                head.radius * 2,
                head.radius * 2
                );
            //torso
            e.Graphics.DrawLine(blackPen, torso.neck.getLocationX(), torso.neck.getLocationY(), torso.shoulders.getLocationX(), torso.shoulders.getLocationY());
            e.Graphics.DrawLine(blackPen, torso.shoulders.getLocationX(), torso.shoulders.getLocationY(), torso.hips.getLocationX(), torso.hips.getLocationY());
            //right arm
            e.Graphics.DrawLine(blackPen, torso.shoulders.getLocationX(), torso.shoulders.getLocationY(), rightArm.elbow.getLocationX(), rightArm.elbow.getLocationY());
            e.Graphics.DrawLine(redPen, rightArm.elbow.getLocationX(), rightArm.elbow.getLocationY(), rightArm.attachHand.getLocationX(), rightArm.attachHand.getLocationY());
            //left arm
            e.Graphics.DrawLine(blackPen, torso.shoulders.getLocationX(), torso.shoulders.getLocationY(), leftArm.elbow.getLocationX(), leftArm.elbow.getLocationY());
            e.Graphics.DrawLine(bluePen, leftArm.elbow.getLocationX(), leftArm.elbow.getLocationY(), leftArm.attachHand.getLocationX(), leftArm.attachHand.getLocationY());
            //right leg
            e.Graphics.DrawLine(blackPen, torso.hips.getLocationX(), torso.hips.getLocationY(), rightLeg.knee.getLocationX(), rightLeg.knee.getLocationY());
            e.Graphics.DrawLine(redPen, rightLeg.knee.getLocationX(), rightLeg.knee.getLocationY(), rightLeg.attachFoot.getLocationX(), rightLeg.attachFoot.getLocationY());
            //left leg
            e.Graphics.DrawLine(blackPen, torso.hips.getLocationX(), torso.hips.getLocationY(), leftLeg.knee.getLocationX(), leftLeg.knee.getLocationY());
            e.Graphics.DrawLine(bluePen, leftLeg.knee.getLocationX(), leftLeg.knee.getLocationY(), leftLeg.attachFoot.getLocationX(), leftLeg.attachFoot.getLocationY());
        }
    }

Вот несколько снимков до и после того, как объект несколько раз перемещается и обновляется:

До

* После 1036 *

Извините, но я не смогу вставлять изображения, если у меня нет 10 респ.

1 Ответ

0 голосов
/ 05 июня 2011

Вы не должны использовать CreateGraphics для своей задачи. Подпишитесь на событие Paint вашей панели и делайте все свои рисунки в обработчике событий, используя PaintEventArgs.Graphics в качестве объекта Graphics.

private void transparentPanel1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawRectangle(new Pen(Color.Red,2), 4,4,64,64);
}

Вот что я получил, используя ваш TransparentPanel и мой обработчик событий:

Result image

ОБНОВЛЕНИЕ: Проблема в том, что вам нужно вызывать метод Graphics.Clear в начале каждого цикла отрисовки, чтобы избавиться от всех предыдущих чертежей. Это испортит ваш прозрачный фон. Эта ссылка дает вам несколько советов, касающихся проблемы. Ключевым моментом является то, что вы должны сделать недействительным родительский элемент управления вашей панели, чтобы получить «прозрачный» фон.

Итак, я оставил код TransparentPanel нетронутым, но изменил код основной формы:

readonly Random _rand =new Random();

private void transparentPanel1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawRectangle(new Pen(Color.Red,2), _rand.Next(60),_rand.Next(30),64,64);
}

private void button1_Click(object sender, EventArgs e)
{
   Invalidate(new Rectangle(transparentPanel1.Location, transparentPanel1.Size),true);
}

Теперь, когда я нажимаю кнопку в моей форме, панель перерисовывается и показывает один прямоугольник в случайном месте. Если вы аннулируете сам transparantPanel1, он не очистится и вы увидите беспорядок красных прямоугольников.


ОБНОВЛЕНО (Алекс): Это код, предоставленный в ссылке от Dyppl, который решил проблему. Его просто нужно поместить в класс прозрачной панели:

public void InvalidateEx()
    {
        if (Parent == null)
            return;
        Rectangle rc = new Rectangle(this.Location, this.Size);
        Parent.Invalidate(rc, true);
    } 

Я вызываю этот код при каждом обновлении панели, и фон остается прозрачным.

...