Ich habe diese Komponente geschrieben, um das Streaming einer Kamera zu rendern. Über dem Streaming kann der Benutzer eine oder mehrere Formen zeichnen (verwaltet über eine Schnittstelle). Die verfügbaren Formen sind:
Punkt
Rechteck
Ellipse
Polylinie
Zusätzlich zum Zeichnen von Formen kann der Benutzer eine auswählen und die Größe und Position ändern. Der Benutzer kann auch den heißesten Punkt des Bildes sehen, der sich dann kontinuierlich innerhalb des Bildes bewegt.
Das Bild wird kontinuierlich aktualisiert und durch das Ereignis UpdateRadiometricImage behandelt
Dies ist mein vollständiger Code der Komponente:
using Imager.IRBinding;
using Imager.Services;
using Imager.Shapes;
using Imager.Types;
using Imager.Utils;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Web.UI.WebControls.Expressions;
using System.Windows.Forms;
namespace Imager.Components
{
public class RadiometricImage : PictureBox, IDisposable
{
// -------- PER IL DISEGNO
internal string Serial { get; set; }
internal List Shapes = new List(); // Forme permanenti
internal List SelectedShapes { get; set; } = new List(); // Forme selezionate
public ShapeType ShapeToDraw { get; set; } = ShapeType.None;
public ModeType CurrentMode { get; set; } = ModeType.None;
public PolylineShape CurrentPolyline { get; set; } = null; // Polilinea temporanea
public bool IsDrawingPolyline { get; set; } = false; // Flag per il disegno polilinea
private Point currentCursorPoint; // Posizione corrente del cursore
private Point? startPoint = null; // Punto iniziale del disegno
private IShape tempShape = null; // Forma temporanea
private Point? selectedHandler = null; // Handler selezionato per modifica
private bool isDragging = false; // Flag per indicare il trascinamento
private Point dragStartPoint; // Punto iniziale del trascinamento
private Point? activeResizeHandler = null; // Handler attivo per il resize
private int selectedResizeHandler; // Handler selezionato per il resize
// --------
// ------------ AREA DI MISURA PANNELLO
public event EventHandler ShapeChanged;
public event EventHandler ThermalImageUpdated;
// -----------
// --------- MOSTRA PUNTO CALDO GLOBALE
public bool ShowHotSpot { get; set; } = false;
private readonly PointShape _hotSpot = new PointShape();
// ---------
private bool _disposed = false;
private Rectangle _imageBounds;
private readonly ToolTip _toolTip = new ToolTip();
private Bitmap _paletteImage = null;
public Bitmap PaletteImage
{
get => _paletteImage;
set
{
Image = _paletteImage = value;
CalculateImageBounds();
}
}
public ushort[,] ThermalImage { get; set; } = null;
public EvoIRFrameMetadata Metadata { get; set; }
public RadiometricImage()
{
Console.WriteLine("RadiometricImage created.");
BackColor = Color.Black;
Dock = DockStyle.Fill;
DoubleBuffered = true;
SizeMode = PictureBoxSizeMode.Zoom;
Resize += (s, e) =>
{
Console.WriteLine("Resize event triggered.");
CalculateImageBounds();
};
MouseMove += RadiometricImage_MouseMove;
MouseLeave += RadiometricImage_MouseLeave;
MouseDown += RadiometricImage_MouseDown;
MouseUp += RadiometricImage_MouseUp;
Paint += RadiometricImage_Paint;
}
internal void UpdateRadiometricImage(ThermalPaletteImage img)
{
PaletteImage = img.PaletteImage;
Metadata = img.IRFrameMetadata;
ThermalImage = img.ThermalImage;
ThermalImageUpdated?.Invoke(this, EventArgs.Empty); // Notifica il cambiamento
}
private void RadiometricImage_MouseLeave(object sender, EventArgs e)
{
Console.WriteLine("Mouse fouri dall'immagine, nascondo tooltip");
_toolTip.Hide(this);
}
private void RadiometricImage_Paint(object sender, PaintEventArgs e)
{
if (ShowHotSpot)
{
int maxI = 0, maxJ = 0;
ushort max = ThermalImage[0, 0];
for (int i = 0; i < ThermalImage.GetLength(0); ++i)
{
for (int j = 0; j < ThermalImage.GetLength(1); ++j)
{
if (ThermalImage[i, j] > max)
{
max = ThermalImage[i, j];
maxI = i;
maxJ = j;
}
}
}
_hotSpot.Position = new Point(maxJ, maxI);
_hotSpot.Name = $"{Conversion.RealTemperatureValue(max)} °C";
_hotSpot.Draw(e.Graphics, FromImageToContainer, Color.Black);
DrawShapeName(e.Graphics, _hotSpot, Color.Black);
}
foreach (var shape in Shapes)
{
Console.WriteLine("shape");
shape.Draw(e.Graphics, FromImageToContainer);
DrawShapeName(e.Graphics, shape);
if (SelectedShapes.Contains(shape))
{
DrawShapeHandlers(e.Graphics, shape);
}
}
if (ShapeToDraw == ShapeType.Polyline && CurrentPolyline != null)
{
Console.WriteLine("polyline shape");
CurrentPolyline.Draw(e.Graphics, FromImageToContainer);
DrawPolylinePreview(e.Graphics);
DrawShapeHandlers(e.Graphics, CurrentPolyline);
}
tempShape?.Draw(e.Graphics, FromImageToContainer);
}
internal void RadiometricImage_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Delete)
{
if (SelectedShapes.Any())
{
foreach (var shape in SelectedShapes.ToList())
{
RemoveShape(shape);
}
SelectedShapes.Clear();
Invalidate();
}
}
else if (e.KeyCode == Keys.Escape)
{
ResetDrawingState();
Invalidate();
}
if (SelectedShapes.Any())
{
const int moveStep = 1;
switch (e.KeyCode)
{
case Keys.Left:
MoveSelectedShapes(new Point(-moveStep, 0), true);
break;
case Keys.Right:
MoveSelectedShapes(new Point(moveStep, 0), true);
break;
case Keys.Up:
MoveSelectedShapes(new Point(0, -moveStep), true);
break;
case Keys.Down:
MoveSelectedShapes(new Point(0, moveStep), true);
break;
}
}
}
private void RadiometricImage_MouseUp(object sender, MouseEventArgs e)
{
Console.WriteLine($"MouseUp at {e.Location}");
if (isDragging)
{
isDragging = false;
Cursor = Cursors.Default;
}
else if (activeResizeHandler.HasValue)
{
activeResizeHandler = null;
Cursor = Cursors.Default;
}
else if ((ShapeToDraw == ShapeType.Rectangle || ShapeToDraw == ShapeType.Ellipse) && tempShape != null)
{
tempShape.Name = $"Area {Shapes.Count + 1}";
AddShape(tempShape);
tempShape = null;
startPoint = null;
}
selectedHandler = null;
Cursor = Cursors.Default;
// Invalidate();
}
private void RadiometricImage_MouseMove(object sender, MouseEventArgs e)
{
Console.WriteLine($"MouseMove at {e.Location}");
if (CurrentMode == ModeType.None && _imageBounds.Contains(e.Location))
{
var position = FromContainerToImage(e.Location);
double temperature = CameraService.GetPixelValue(ThermalImage, position);
_toolTip.Show($"{temperature} °C", this, e.X + 10, e.Y + 10);
}
else
{
_toolTip.Hide(this);
}
currentCursorPoint = e.Location;
if (activeResizeHandler.HasValue && SelectedShapes.Count == 1 && activeResizeHandler.Value != e.Location)
{
Console.WriteLine($"Active Handler: {activeResizeHandler.Value}");
var shape = SelectedShapes.First();
if (_imageBounds.Contains(e.Location))
{
shape.Resize(FromContainerToImage(activeResizeHandler.Value), FromContainerToImage(e.Location)); // Ridimensiona la forma
var aux = shape.GetHandlers();
activeResizeHandler = FromImageToContainer(aux.ElementAt(selectedResizeHandler)); // Aggiorna la posizione dell'handler
Invalidate();
}
}
else if (isDragging && SelectedShapes.Any())
{
MoveSelectedShapes(e.Location);
dragStartPoint = e.Location;
}
else
{
foreach (var shape in SelectedShapes)
{
var pos = FromContainerToImage(e.Location);
bool onHandler = false;
if (shape is PolylineShape polyline)
{
foreach (var handler in polyline.GetHandlers())
{
if (DrawHelper.IsCloseToPoint(e.Location, FromImageToContainer(handler)))
{
Cursor = Cursors.Hand;
onHandler = true;
break;
}
}
}
else if (!(shape is PointShape point))
{
foreach (var handler in shape.GetHandlers())
{
if (DrawHelper.IsCloseToPoint(e.Location, FromImageToContainer(handler)))
{
Cursor = DrawHelper.GetResizeCursor(handler, shape); // Ottieni il cursore corretto
onHandler = true;
break;
}
}
}
if (!onHandler)
{
Cursor = Cursors.Default;
}
}
}
if (CurrentMode == ModeType.Draw)
{
if (ShapeToDraw == ShapeType.Polyline && selectedHandler.HasValue) MovePolylineHandler(FromContainerToImage(e.Location));
if ((ShapeToDraw == ShapeType.Rectangle || ShapeToDraw == ShapeType.Ellipse) && startPoint.HasValue) UpdateTemporaryShape(e.Location);
Invalidate();
}
}
private void RadiometricImage_MouseDown(object sender, MouseEventArgs e)
{
Console.WriteLine($"MouseDown at {e.Location}");
if (CurrentMode == ModeType.Select)
{
HandleSelectionMouseDown(e.Location);
if (SelectedShapes.Any() && isDragging)
{
Cursor = Cursors.SizeAll;
}
}
if (CurrentMode == ModeType.Draw)
{
if (_imageBounds.Contains(e.Location))
{
switch (ShapeToDraw)
{
case ShapeType.Point:
AddPointShape(e.Location);
break;
case ShapeType.Rectangle:
case ShapeType.Ellipse:
startPoint = FromContainerToImage(e.Location);
break;
case ShapeType.Polyline:
HandlePolylineMouseDown(e);
break;
default:
break;
}
}
}
}
public void AddShape(IShape shape)
{
Shapes.Add(shape);
OnShapeAdded(shape);
Invalidate(); // Per ridisegnare shape.GetRegion(FromImageToContainer)
}
public void RemoveShape(IShape shape)
{
if (Shapes.Remove(shape))
{
OnShapeRemoved(shape);
Invalidate(); // Per ridisegnare shape.GetRegion(FromImageToContainer)
}
}
#region HELPERS
private Point FromContainerToImage(Point src)
{
if (Image == null) return Point.Empty;
float xRatio = (float)(src.X - _imageBounds.Left) / _imageBounds.Width;
float yRatio = (float)(src.Y - _imageBounds.Top) / _imageBounds.Height;
return new Point((int)(xRatio * Image.Width), (int)(yRatio * Image.Height));
}
private Point FromImageToContainer(Point src)
{
if (Image == null) return Point.Empty;
float xRatio = (float)src.X / Image.Width;
float yRatio = (float)src.Y / Image.Height;
return new Point((int)(xRatio * _imageBounds.Width + _imageBounds.Left), (int)(yRatio * _imageBounds.Height + _imageBounds.Top));
}
private void CalculateImageBounds()
{
if (Image == null)
{
_imageBounds = new Rectangle(0, 0, 0, 0);
return;
}
float xRatio = (float)Width / Image.Width;
float yRatio = (float)Height / Image.Height;
float ratio = Math.Min(xRatio, yRatio);
int width = (int)(Image.Width * ratio);
int height = (int)(Image.Height * ratio);
_imageBounds = new Rectangle((Width - width) / 2, (Height - height) / 2, width, height);
}
private void DrawHandler(Graphics g, Point point)
{
const int size = 10;
var rect = new Rectangle(point.X - size / 2, point.Y - size / 2, size, size);
using (var brush = new SolidBrush(SystemColors.Highlight))
{
g.FillRectangle(brush, rect);
}
}
private void DrawShapeHandlers(Graphics g, IShape shape)
{
foreach (var handler in shape.GetHandlers().Select(x => FromImageToContainer(x)))
{
DrawHandler(g, handler);
}
}
private void ResetDrawingState()
{
if (ShapeToDraw == ShapeType.Polyline && IsDrawingPolyline)
{
CurrentPolyline = null;
IsDrawingPolyline = false;
}
else if ((ShapeToDraw == ShapeType.Rectangle || ShapeToDraw == ShapeType.Ellipse) && tempShape != null)
{
tempShape = null;
startPoint = null;
}
else if (SelectedShapes.Any())
{
SelectedShapes.Clear();
}
// CurrentMode = ModeType.None;
}
private void HandlePolylineMouseDown(MouseEventArgs e)
{
if (CurrentPolyline != null)
{
var point = FromContainerToImage(e.Location);
if (CurrentPolyline.Points.Count > 0 && DrawHelper.IsCloseToPoint(point, CurrentPolyline.Points[0]))
{
CurrentPolyline.ClosePolyline();
CurrentPolyline.IsClosed = true;
CurrentPolyline.Name = $"Area {Shapes.Count + 1}";
AddShape(CurrentPolyline);
CurrentPolyline = null;
IsDrawingPolyline = true;
}
else
{
CurrentPolyline.Points.Add(point);
}
}
}
private void AddPointShape(Point location)
{
var pointShape = new PointShape() { Name = $"Area {Shapes.Count + 1}", Position = FromContainerToImage(location) };
AddShape(pointShape);
}
private void UpdateTemporaryShape(Point location)
{
if (startPoint.HasValue && _imageBounds.Contains(location))
{
var rect = DrawHelper.GetRectangleFromPoints(startPoint.Value, FromContainerToImage(location));
switch (ShapeToDraw)
{
case ShapeType.Rectangle:
tempShape = new RectangleShape { Rect = rect };
break;
case ShapeType.Ellipse:
tempShape = new EllipseShape { Bounds = rect };
break;
}
}
}
private void MoveSelectedShapes(Point location, bool keyboard = false)
{
var bounds = new Rectangle(0, 0, Image.Width, Image.Height);
if (keyboard)
{
foreach (var shape in SelectedShapes)
{
shape.Move(bounds, location);
}
}
else
{
var convertedLocation = FromContainerToImage(location);
var convartedStartPoint = FromContainerToImage(dragStartPoint);
var deltaX = convertedLocation.X - convartedStartPoint.X;
var deltaY = convertedLocation.Y - convartedStartPoint.Y;
foreach (var shape in SelectedShapes)
{
shape.Move(bounds, new Point(deltaX, deltaY));
}
dragStartPoint = location;
}
}
private void MovePolylineHandler(Point location)
{
if (CurrentPolyline != null && selectedHandler.HasValue)
{
var index = CurrentPolyline.Points.IndexOf(selectedHandler.Value);
if (index >= 0)
{
CurrentPolyline.Points[index] = location;
}
}
}
private void DrawShapeName(Graphics g, IShape shape, Color color = default)
{
var center = shape.NamePosition(FromImageToContainer, Image.Height);
if (color == default) color = Color.White;
using (var font = new Font("Arial", 14))
{
using (var brush = new SolidBrush(color))
{
g.DrawString(shape.Name, font, brush, center);
}
}
}
private void HandleSelectionMouseDown(Point location)
{
SelectedShapes.Clear();
activeResizeHandler = null; // Resetta l'handler attivo
foreach (var shape in Shapes)
{
if (!(shape is PointShape point))
{
int i = 0;
foreach (var handler in shape.GetHandlers())
{
var h = FromImageToContainer(handler);
if (DrawHelper.IsCloseToPoint(location, h))
{
SelectedShapes.Add(shape);
activeResizeHandler = h; // Memorizza l'handler attivo per il resize
selectedResizeHandler = i;
Console.WriteLine($"Handler: {h}");
return;
}
i++;
}
}
if (shape.PointOnBound(FromContainerToImage(location)))
{
SelectedShapes.Add(shape);
dragStartPoint = location;
isDragging = true;
Invalidate();
return;
}
}
}
private void DrawPolylinePreview(Graphics g)
{
if (CurrentPolyline != null && CurrentPolyline.Points.Count > 0)
{
var lastPoint = CurrentPolyline.Points.Last();
if (DrawHelper.IsCloseToPoint(FromContainerToImage(currentCursorPoint), CurrentPolyline.Points[0]))
{
g.DrawLine(Pens.White, FromImageToContainer(lastPoint), FromImageToContainer(CurrentPolyline.Points[0]));
}
else
{
g.DrawLine(Pens.Gray, FromImageToContainer(lastPoint), currentCursorPoint);
}
}
}
#endregion
#region AREA_DI_MISURA
private void OnShapeAdded(IShape shape)
{
ShapeChanged?.Invoke(this, new ShapeChangedEventArgs(shape, AreaOperation.Added));
}
private void OnShapeRemoved(IShape shape)
{
ShapeChanged?.Invoke(this, new ShapeChangedEventArgs(shape, AreaOperation.Removed));
}
#endregion
protected override void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
if (PaletteImage != null)
{
PaletteImage.Dispose();
PaletteImage = null;
}
if (Shapes != null)
{
Shapes.Clear();
Shapes = null;
}
if (SelectedShapes != null)
{
SelectedShapes.Clear();
SelectedShapes = null;
}
if (ThermalImage != null) ThermalImage = null;
if (CurrentPolyline != null) CurrentPolyline = null;
Resize -= (s, e) => CalculateImageBounds();
MouseMove -= RadiometricImage_MouseMove;
MouseDown -= RadiometricImage_MouseDown;
MouseUp -= RadiometricImage_MouseUp;
Paint -= RadiometricImage_Paint;
}
}
base.Dispose(disposing);
_disposed = true;
}
}
}
Der Code funktioniert, aber wenn das Streaming von der Kamera in hoher Auflösung erfolgt oder viele Formen gezeichnet werden, wird die gesamte Anwendung langsamer, was für den Benutzer zu Unannehmlichkeiten führt. Haben Sie Ratschläge und Anregungen, um diese Komponente optimal zu optimieren?
Ich habe diese Komponente geschrieben, um das Streaming einer Kamera zu rendern. Über dem Streaming kann der Benutzer eine oder mehrere Formen zeichnen (verwaltet über eine Schnittstelle). Die verfügbaren Formen sind: [list] [*]Punkt [*]Rechteck [*]Ellipse Polylinie [/list] Zusätzlich zum Zeichnen von Formen kann der Benutzer eine auswählen und die Größe und Position ändern. Der Benutzer kann auch den heißesten Punkt des Bildes sehen, der sich dann kontinuierlich innerhalb des Bildes bewegt. Das Bild wird kontinuierlich aktualisiert und durch das Ereignis UpdateRadiometricImage behandelt Dies ist mein vollständiger Code der Komponente: [code]using Imager.IRBinding; using Imager.Services; using Imager.Shapes; using Imager.Types; using Imager.Utils; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Web.UI.WebControls.Expressions; using System.Windows.Forms;
namespace Imager.Components { public class RadiometricImage : PictureBox, IDisposable { // -------- PER IL DISEGNO internal string Serial { get; set; } internal List Shapes = new List(); // Forme permanenti
internal List SelectedShapes { get; set; } = new List(); // Forme selezionate
public ShapeType ShapeToDraw { get; set; } = ShapeType.None; public ModeType CurrentMode { get; set; } = ModeType.None; public PolylineShape CurrentPolyline { get; set; } = null; // Polilinea temporanea public bool IsDrawingPolyline { get; set; } = false; // Flag per il disegno polilinea
private Point currentCursorPoint; // Posizione corrente del cursore private Point? startPoint = null; // Punto iniziale del disegno private IShape tempShape = null; // Forma temporanea private Point? selectedHandler = null; // Handler selezionato per modifica private bool isDragging = false; // Flag per indicare il trascinamento private Point dragStartPoint; // Punto iniziale del trascinamento private Point? activeResizeHandler = null; // Handler attivo per il resize private int selectedResizeHandler; // Handler selezionato per il resize // --------
// ------------ AREA DI MISURA PANNELLO public event EventHandler ShapeChanged; public event EventHandler ThermalImageUpdated; // -----------
// --------- MOSTRA PUNTO CALDO GLOBALE public bool ShowHotSpot { get; set; } = false; private readonly PointShape _hotSpot = new PointShape(); // ---------
private void RadiometricImage_MouseMove(object sender, MouseEventArgs e) { Console.WriteLine($"MouseMove at {e.Location}");
if (CurrentMode == ModeType.None && _imageBounds.Contains(e.Location)) { var position = FromContainerToImage(e.Location); double temperature = CameraService.GetPixelValue(ThermalImage, position); _toolTip.Show($"{temperature} °C", this, e.X + 10, e.Y + 10); } else { _toolTip.Hide(this); }
currentCursorPoint = e.Location;
if (activeResizeHandler.HasValue && SelectedShapes.Count == 1 && activeResizeHandler.Value != e.Location) { Console.WriteLine($"Active Handler: {activeResizeHandler.Value}"); var shape = SelectedShapes.First(); if (_imageBounds.Contains(e.Location)) {
shape.Resize(FromContainerToImage(activeResizeHandler.Value), FromContainerToImage(e.Location)); // Ridimensiona la forma var aux = shape.GetHandlers(); activeResizeHandler = FromImageToContainer(aux.ElementAt(selectedResizeHandler)); // Aggiorna la posizione dell'handler Invalidate(); }
} else if (isDragging && SelectedShapes.Any()) { MoveSelectedShapes(e.Location); dragStartPoint = e.Location; } else { foreach (var shape in SelectedShapes) { var pos = FromContainerToImage(e.Location); bool onHandler = false; if (shape is PolylineShape polyline) { foreach (var handler in polyline.GetHandlers()) { if (DrawHelper.IsCloseToPoint(e.Location, FromImageToContainer(handler))) { Cursor = Cursors.Hand; onHandler = true; break; } } } else if (!(shape is PointShape point)) { foreach (var handler in shape.GetHandlers()) { if (DrawHelper.IsCloseToPoint(e.Location, FromImageToContainer(handler))) { Cursor = DrawHelper.GetResizeCursor(handler, shape); // Ottieni il cursore corretto onHandler = true; break; } } } if (!onHandler) { Cursor = Cursors.Default; } } } if (CurrentMode == ModeType.Draw) { if (ShapeToDraw == ShapeType.Polyline && selectedHandler.HasValue) MovePolylineHandler(FromContainerToImage(e.Location)); if ((ShapeToDraw == ShapeType.Rectangle || ShapeToDraw == ShapeType.Ellipse) && startPoint.HasValue) UpdateTemporaryShape(e.Location);
Invalidate(); } }
private void RadiometricImage_MouseDown(object sender, MouseEventArgs e) { Console.WriteLine($"MouseDown at {e.Location}");
if (CurrentMode == ModeType.Select) { HandleSelectionMouseDown(e.Location); if (SelectedShapes.Any() && isDragging) { Cursor = Cursors.SizeAll; } }
if (CurrentMode == ModeType.Draw) { if (_imageBounds.Contains(e.Location)) { switch (ShapeToDraw) { case ShapeType.Point: AddPointShape(e.Location); break; case ShapeType.Rectangle: case ShapeType.Ellipse: startPoint = FromContainerToImage(e.Location); break; case ShapeType.Polyline: HandlePolylineMouseDown(e); break; default: break; } } } }
public void AddShape(IShape shape) { Shapes.Add(shape); OnShapeAdded(shape); Invalidate(); // Per ridisegnare shape.GetRegion(FromImageToContainer) }
public void RemoveShape(IShape shape) { if (Shapes.Remove(shape)) { OnShapeRemoved(shape); Invalidate(); // Per ridisegnare shape.GetRegion(FromImageToContainer) } }
#region HELPERS
private Point FromContainerToImage(Point src) { if (Image == null) return Point.Empty;
private void AddPointShape(Point location) { var pointShape = new PointShape() { Name = $"Area {Shapes.Count + 1}", Position = FromContainerToImage(location) }; AddShape(pointShape); }
private void UpdateTemporaryShape(Point location) { if (startPoint.HasValue && _imageBounds.Contains(location)) { var rect = DrawHelper.GetRectangleFromPoints(startPoint.Value, FromContainerToImage(location)); switch (ShapeToDraw) { case ShapeType.Rectangle: tempShape = new RectangleShape { Rect = rect }; break; case ShapeType.Ellipse: tempShape = new EllipseShape { Bounds = rect }; break; } } }
private void MoveSelectedShapes(Point location, bool keyboard = false) { var bounds = new Rectangle(0, 0, Image.Width, Image.Height); if (keyboard) { foreach (var shape in SelectedShapes) { shape.Move(bounds, location); } } else { var convertedLocation = FromContainerToImage(location); var convartedStartPoint = FromContainerToImage(dragStartPoint);
var deltaX = convertedLocation.X - convartedStartPoint.X; var deltaY = convertedLocation.Y - convartedStartPoint.Y;
foreach (var shape in SelectedShapes) { shape.Move(bounds, new Point(deltaX, deltaY)); } dragStartPoint = location; } }
private void MovePolylineHandler(Point location) { if (CurrentPolyline != null && selectedHandler.HasValue) { var index = CurrentPolyline.Points.IndexOf(selectedHandler.Value); if (index >= 0) { CurrentPolyline.Points[index] = location; } } }
private void DrawShapeName(Graphics g, IShape shape, Color color = default) { var center = shape.NamePosition(FromImageToContainer, Image.Height);
if (color == default) color = Color.White;
using (var font = new Font("Arial", 14)) { using (var brush = new SolidBrush(color)) { g.DrawString(shape.Name, font, brush, center); } } }
_disposed = true; } } } [/code] Der Code funktioniert, aber wenn das Streaming von der Kamera in hoher Auflösung erfolgt oder viele Formen gezeichnet werden, wird die gesamte Anwendung langsamer, was für den Benutzer zu Unannehmlichkeiten führt. Haben Sie Ratschläge und Anregungen, um diese Komponente optimal zu optimieren?
Ich habe die akzeptierte Antwort gefunden und sie funktioniert perfekt. Die Antwort von @RezaAghaei. Allerdings funktioniert nur das Resize-Ereignis. Kein anderes Ereignis funktioniert.
Ich verwende...
Ich entworfene eine Multi-Thread-Datenpipeline, die auf dem Service A beruht. Ich verfolge ein Produzenten-Verbraucher-Design, um eine Liste von Objekten zu verarbeiten. Wo mein Produzent die API von...
Ich arbeite an einer Laravel-Anwendung, die einfachen E-Commerce ermöglicht und über alle Funktionen verfügt. Ich stehe vor einem Problem: Wenn ich eine Bestellung aufgegeben habe, dauert es sehr...