gpt4 book ai didi

c# - PictureBox 仅在调整大小时更新

转载 作者:太空宇宙 更新时间:2023-11-03 13:02:44 24 4
gpt4 key购买 nike

尝试在表单应用程序上显示图形。创建一个 PictureBox 控件并使用它的值初始化此类。在调整大小时,图表总是更新;在鼠标滚动上,它几乎没有。它是 GraphBox 和 PictureBox 控件,位于 GraphBoxPanel 面板控件内。

这个类:

public struct DLT_measure_item
{
public DateTime ts;
public float value;
public int id;
public int X;
public int Y;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct dlt_ser_meas
{
public byte msg_id; // 'D'
public byte meas_count; // Number of measures
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] port; // Module ID (4b) + Port ID (4b)
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public float[] meas; // measure
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] msg_end;
}

public class manageGraph
{
private PictureBox box;
public bool displayGrid = true;
private int horAxisMin_p = 0;
private int horAxisMax_p = 300;
private float verAxisMin_p = 0;
private float verAxisMax_p = 40;
public int horAxisMin
{
get { return this.horAxisMin_p; }
set
{
if (value < horAxisMax_p)
{
this.horAxisMin_p = value;
reDraw();
}
}
}
public int horAxisMax
{
get { return this.horAxisMax_p; }
set
{
if (value > horAxisMin_p)
{
this.horAxisMax_p = value;
reDraw();
}
}
}
public float verAxisMin
{
get { return this.verAxisMin_p; }
set
{
if (value < verAxisMax_p)
{
this.verAxisMin_p = value;
verPointPerUnit = graphArea.Height / (verAxisMax_p - this.verAxisMin_p);
}
}
}
public float verAxisMax
{
get { return this.verAxisMax_p; }
set
{
if (value > verAxisMin_p)
{
this.verAxisMax_p = value;
verPointPerUnit = graphArea.Height / (this.verAxisMax_p - verAxisMin_p);
}
}
}
Pen axes = new Pen(Color.Black, (float)1.5);
public int horAxisSpacing = 30;
public int verAxisSpacing = 20;
public int horAxis = 20;
public int verAxis = 20;
private float horPointPerUnit = 1;
private float verPointPerUnit = 1;
public int horAxisTickLen = 5;
public int verAxisTickLen = 5;
public bool horAxisShowTime = false;
private Rectangle graphArea = new Rectangle();


public void reDraw()
{
box.Image.Dispose();
Bitmap GraphBlankImage = new Bitmap(box.Width, box.Height);
box.Image = GraphBlankImage;
updatePointPerUnit();
drawGrid();
box.Refresh();

}
public manageGraph(PictureBox targetImageBoxbox)
{
box = targetImageBoxbox;
horAxisMin_p = 0;
horAxisMax_p = 300;
verAxisMin_p = 0F;
verAxisMax_p = 50F;
updatePointPerUnit();
}
private Point measToPoint(DLT_measure_item measure) {
Point coords = new Point();
coords.X = graphArea.Width - (int)(
((DateTime.Now - measure.ts).TotalSeconds + horAxisMin_p) * horPointPerUnit ) ;
coords.Y = graphArea.Height - (int)(
((measure.value - verAxisMin_p) * verPointPerUnit));
return coords;
}
public manageGraph(PictureBox targetImageBoxbox,
int xmin, int xmax, float ymin, float ymax)
{
box = targetImageBoxbox;
horAxisMin_p = xmin;
horAxisMax_p = xmax;
verAxisMin_p = ymin;
verAxisMax_p = ymax;
updatePointPerUnit();
}

private void updateGraphArea()
{
graphArea = new Rectangle(0, 0, box.Width - horAxis, box.Height - verAxis);
}

private void updatePointPerUnit()
{
updateGraphArea();
horPointPerUnit = graphArea.Width / (horAxisMax_p - horAxisMin_p);
verPointPerUnit = graphArea.Height / (verAxisMax_p - verAxisMin_p);
}

public void drawGrid()
{

//updatePointPerUnit();
using (Graphics g = Graphics.FromImage(box.Image))
{
// X axis
g.DrawLine(axes, graphArea.Left, graphArea.Bottom, box.Width, graphArea.Bottom);
// Y axis
g.DrawLine(axes, graphArea.Right + 1, graphArea.Top, graphArea.Right +1, graphArea.Bottom);
using (Font ArialFont = new Font("Arial", 10))
{
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
// Put x labels
for (int i = 1; i <= (graphArea.Width / horPointPerUnit); i = i + (int)(horAxisSpacing / horPointPerUnit ) + 1)
{
g.DrawString((i).ToString(), ArialFont, Brushes.Black, graphArea.Width - ( i * horPointPerUnit) - 5, graphArea.Bottom +5);
g.DrawLine(axes, graphArea.Width - (i * horPointPerUnit), graphArea.Bottom + (horAxisTickLen / 2), graphArea.Width - (i * horPointPerUnit), graphArea.Bottom - (horAxisTickLen / 2));
}
// Put y labels
for (int i = 1; i <= (graphArea.Height / verPointPerUnit); i = i + (int)(verAxisSpacing / verPointPerUnit) +1)
{
g.DrawString((i).ToString(), ArialFont, Brushes.Black, graphArea.Right + 1 , graphArea.Height - (i * verPointPerUnit) - 8);
g.DrawLine(axes, graphArea.Width - (verAxisTickLen / 2), (i * verPointPerUnit), graphArea.Width + (verAxisTickLen / 2), (i * verPointPerUnit));
}
}
/*Put some random data*/
DLT_measure_item testmeas = new DLT_measure_item();
Point testGraphPoint = new Point();
testmeas.ts = DateTime.Now;
testmeas.value = 0;
testGraphPoint = measToPoint(testmeas);
g.FillEllipse(Brushes.Blue, testGraphPoint.X, testGraphPoint.Y, 4, 4);
for (double i = 0; i < 300; i++)
{
double x = i;
double freq = 10;
double y = 30 - (i/10);
testmeas.value = (float)y;
testmeas.ts = DateTime.Now.AddSeconds(-1 * i);
testGraphPoint = measToPoint(testmeas);
g.FillEllipse(Brushes.Red, testGraphPoint.X, testGraphPoint.Y, 2,2);
}
}
}
}

初始化:

    public DLThermalogMainForm()
{
InitializeComponent();
Bitmap GraphBlankImage = new Bitmap(GraphBox.Width, GraphBox.Height);
GraphBox.Image = GraphBlankImage;
myGraph = new manageGraph(GraphBox);
myGraph.drawGrid();

}

那些处理程序:

    private void Form1_ResizeEnd(object sender, EventArgs e)
{
myGraph.reDraw();
OutputTextBox.AppendText("Resize." + Environment.NewLine);
}

private void GraphBox_MouseMove(object sender, MouseEventArgs e)
{
//Get the focus to have the wheel working
GraphBoxPanel.Focus();
}

private void GraphBoxPanel_MouseWheel(object sender, MouseEventArgs e)
{
// Change x axis max value to zoom in/out the graph
myGraph.horAxisMax += e.Delta/ 120;
myGraph.reDraw();
}

在调整大小事件中,它总是重绘;在鼠标滚轮上,只有较小的 horAxisMax 值才会快速执行(这有意义吗???),但对于较大的值,更新需要很多秒,或者根本不需要。非常感谢

最佳答案

像这样更改reDraw:

public void reDraw()
{
box.Image.Dispose();
Bitmap GraphBlankImage = new Bitmap(box.ClientSize.Width, box.ClientSize.Height);
updatePointPerUnit();
drawGrid(GraphBlankImage);
box.Image = GraphBlankImage;
}

drawGrid像这样:

public void drawGrid(Bitmap bmp)
{
//updatePointPerUnit(); //??
using (Graphics g = Graphics.FromImage(bmp))
{
...
...
...
}
}

现在带有网格的 Bitmap 应该立即显示在 PictureBox 中。

如前所述,Graphics 对象是一种用于更改关联的Bitmap 的工具。要选择它,Bitmap 应该分配给 PictureBoxeImage

另请注意,除非您的 PictureBox 没有 Border,否则 outer 大小(也称为 Bounds ) 和内部 大小,ClientRectangle/ClientSize。图片应具有 ClientSize

您可能想知道为什么您的原始代码不起作用?毕竟 Image 是一种引用类型,因此像您所做的那样更改它就足够了..

但深入研究 source code我们找到原因:

PictureBox 的 Image 是一个属性,在它的 setter 中调用了 InstallNewImage:

    public Image Image {
get {
return image;
}
set {
InstallNewImage(value, ImageInstallationType.DirectlySpecified);
}
}

同样的调用也出现在其他几个地方,如 LoadImageLocation 的 setter 中。但是仅在幕后更改 Image 不会强制 PictureBox 进行调用。 Refresh() 也应该这样做。而且,正如您所发现的,调整它的大小也会导致 PictureBox 在 Image Bitmap 中获取更改的数据。

关于c# - PictureBox 仅在调整大小时更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31874341/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com