Всем привет, Сразу к делу : Моя задача вращать картинку в pictureBox (есть ракета, она должна плавно отклоняться на угол от -30° до 30° в зависимости от значения переменной причем вращение должно происходить вокруг заданной мною точки на данный момент у меня есть этот код, который работает не совсем правильно
public partial class Form1 : Form
{
private static System.Timers.Timer aTimer;
public Image img = Image.FromFile(Application.StartupPath.ToString() + @"\image\Rocket1.png");
public float rotationAngle;
public Bitmap bmp;
public Form1()
{
InitializeComponent();
pictureBox1.Image = img;
aTimer = new System.Timers.Timer(100);
aTimer.Elapsed += OnTimedEvent;
aTimer.AutoReset = true;
aTimer.Enabled = true;
int sizeWith = img.Size.Width;
int sizeHeight = img.Size.Height;
bmp = new Bitmap(pictureBox1.Image, new Size(sizeWith, sizeHeight));
}
public void OnTimedEvent(Object source, ElapsedEventArgs e)
{
rotationAngle = rotationAngle + 1;
RotateImage(img, rotationAngle);
}
public void RotateImage(Image img, float rotationAngle)
{
using (Graphics gfx = Graphics.FromImage(bmp))
{
gfx.TranslateTransform((float)bmp.Width, (float)bmp.Height);
gfx.RotateTransform(rotationAngle);
gfx.TranslateTransform(-(float)bmp.Width, -(float)bmp.Height);
gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
gfx.DrawImage(bmp, new Point(0, 0));
gfx.Dispose();
pictureBox1.Image = bmp;
}
}
после всех этих махинаций у меня получается следующее
Вопрос, как исправить все это
Подозреваю, что проблема в том, что вы рисуете на одном и том же Image => каждые поворот накладывается на предыдущий и вы получаете вот такой эффект.
Как вариант, создавайте новый Image
и на нем отрисовывайте повернутое изображение.
Т.е у вас должно быть 2 Bitmap
'а:
Bitmap
, который хранит текущую повернутую картинку, которая в данный момент отображаетсяBitmap
на котором вы довернули до нового угла старый Bitmap
.После доворота, выставляете в Control
новый Bitmap
, а про старый забываете, вызвав Dispose()
.
P.S В gfx.Dispose();
нету смысла, так как using
это сам сделает.
Вообщем скидываю решение, всем кто помогал спасибо
protected override void OnPaint(PaintEventArgs e)
{
using (Bitmap clone = (Bitmap)pictureBox1.Image.Clone())
{
using (Graphics gfx = Graphics.FromImage(clone))
{
gfx.Clear(Color.Transparent);
gfx.TranslateTransform(pictureBox1.Image.Width / 2, pictureBox1.Image.Height / 2);
gfx.RotateTransform(rotationAngle);
gfx.DrawImage(pictureBox1.Image, -pictureBox1.Image.Width / 2, -pictureBox1.Image.Height / 2);
}
pictureBox1.Image = (Bitmap)clone.Clone();
}
}
вызов метода происходит с помощью
Invalidate();
Еще есть вот такая вот переменная(путь к картинке которую мы собираемся вращать)
public Image img = Image.FromFile(Application.StartupPath.ToString() + @"\image\Rocket1.png");
которую мы в начале скрипта записываем в
pictureBox1.Image = img;
данный метод вращает изображение на заданный вами угол т.е. если переменная rotationAngle = 30, то результат будет следующим:
Сразу скажу что при повороте изображение теряет качество
чем больше вы его раз повернете тем хуже качество, пока решение этой проблемы не нашел( скорее всего качество теряется из-за того что мы поворачиваем уже повернутый объект,поэтому со временем картинка начинает терять качество, если при каждом повороте брать нашу начальную картинку, то я думаю потери качества можно избежать) надеюсь понятно и дословно объяснил.
Напишем простой контрол для вашего случая:
public sealed class RotatableImage : Control
{
private Bitmap _bitmap;
private float _angle;
public Bitmap Bitmap
{
get { return _bitmap; }
set
{
_bitmap = value;
if (_bitmap is null)
{
return;
}
Invalidate(); // для вызова метода отрисовки OnPaint(...).
}
}
public float Angle
{
get { return _angle; }
set
{
_angle = value;
if (_bitmap is null)
{
return;
}
Invalidate(); // для вызова метода отрисовки OnPaint(...).
}
}
protected override void Dispose(bool disposing)
{
Bitmap?.Dispose();
if (disposing)
{
Bitmap = null;
Angle = .0f;
}
base.Dispose(disposing);
}
public RotatableImage()
{
DoubleBuffered = true; // что бы не было мерцаний.
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.Clear(BackColor); // можно изменить на любой другой, я использую фоновый цвет.
if (Bitmap is null)
{
base.OnPaint(e);
return;
}
e.Graphics.TranslateTransform(Bitmap.Width + .0f, Bitmap.Height + .0f);
e.Graphics.RotateTransform(Angle);
e.Graphics.TranslateTransform(-Bitmap.Width + .0f, -Bitmap.Height + .0f);
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
e.Graphics.DrawImage(Bitmap, new Point(0, 0));
base.OnPaint(e);
}
}
Нажмите Ctrl+Shift+B, добавьте новый контрол на форму.
Далее, определимся как будем загружать изображение, в моем примере, я его загружаю при помощи кнопки:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// привязываемся к изменению позиции трекбара, и передаем его в `RotatbleImage`
RotatableImage.DataBindings.Add
(
new Binding("Angle", AngleTrackBar, "Value")
);
OpenBtn.Click += OpenBtnOnClick;
}
private void OpenBtnOnClick(object sender, EventArgs e)
{
using (OpenFileDialog ofd = new OpenFileDialog())
{
if (ofd.ShowDialog() != DialogResult.OK)
{
return;
}
try
{
RotatableImage.Bitmap = new Bitmap(ofd.FileName);
}
catch (FileNotFoundException fileNotFoundException)
{
RotatableImage.Bitmap = null;
MessageBox.Show
(
fileNotFoundException.Message,
Resources.FileNotFoundCaption,
MessageBoxButtons.OK,
MessageBoxIcon.Error
);
}
}
}
}
Запускаем приложение, открываем изображение, двигаем трекбар.
Результат:
P.S. Зеленый фон... Баг программы записи.
Вот рабочий метод только image мерцает
PaintEventArgs p = new PaintEventArgs(pictureBox1.CreateGraphics(), pictureBox1.Bounds); //Компонент на котором нужно рисовать и область на которой нужно рисовать
Rotate(sender, p);
с помощью данного кода мы запускаем наш метод
public void Rotate(object sender, PaintEventArgs e)
{
Bitmap bitmap = new Bitmap(img, img.Width, img.Height); // создаем новый битмап
e.Graphics.Clear(Color.Transparent); // трем старый рисунок
e.Graphics.TranslateTransform(bitmap.Width /2 , bitmap.Height + 200); // перемещение в picturebox
e.Graphics.RotateTransform(Convert.ToInt32(RotationAngle / 1.5)); // угол вращения (Переменная RotationAngle)
e.Graphics.TranslateTransform(-bitmap.Width/ 2, -bitmap.Height - 200); // задаем точку вокруг которой осуществляется вращение
e.Graphics.DrawImage(bitmap, bitmap.Width / 6, bitmap.Height / 6); // проецируем изображение
}
а это сам метод
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Моя цель - обработать событие загрузки приложения, при этом применяя паттерн MVVM
Есть приложение написанное на C# Xamarin (Android, IOS)Необходимо показывать изображение которое распологается на сайте
Доброго времени суток Сделал языковой переключатель и вот такую логику от которой подключая языковые пакеты и отображаю на выбранном языке...