为什么图形没有绘制到面板上
How come the graphics is not drawing onto the panel
我想在我的面板中绘制一个网格。我用位图创建的图形对象(屏幕)没有在我的面板中绘制。我尝试调试以查看屏幕是否未绘制,但事实并非如此。
我尝试从面板 createGraphic 方法创建图形对象,并从面板绘制方法创建参数 painteventargs
。两次我用它用OnPaint
画它都花了太长时间。
public Main()
{
InitializeComponent();
backBuffer = new Bitmap(drawPanel.Width, drawPanel.Height);
screen = Graphics.FromImage(backBuffer);
sizeGridPoints = 2;
lenghtBetweenGridPoints = 10;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
screen.Clear(Color.Black);
DrawGrid();
}
private void DrawGrid()
{
for(int x = lenghtBetweenGridPoints; x < drawPanel.Width; x += lenghtBetweenGridPoints)
{
for(int y = lenghtBetweenGridPoints; y < drawPanel.Height; y+= lenghtBetweenGridPoints)
{
screen.FillEllipse(new SolidBrush(Color.Green), x, y, sizeGridPoints, sizeGridPoints);
}
}
}
如果您从位图创建 Graphics
对象,它将在该位图上绘制,而不是在您的用户界面上绘制。相反,使用 OnPaint
方法的 PaintEventArgs e
中的 Graphics
对象直接在窗体或控件上绘制。
e.Graphics.FillEllipse(new SolidBrush(Color.Green), x, y, sizeGridPoints, sizeGridPoints);
您永远不应该创建自己的 Graphics
对象。
创建您自己的网格控件:
public class GridPanel : Panel
{
public GridPanel()
{
DoubleBuffered = true; // Speeds up drawing, e.g. when panel is resized.
// Set default colors
BackColor = Color.Black;
ForeColor = Color.Green;
}
private int _lenghtBetweenGridPoints = 20;
public int LenghtBetweenGridPoints
{
get { return _lenghtBetweenGridPoints; }
set {
if (value != _lenghtBetweenGridPoints) {
_lenghtBetweenGridPoints = value;
Invalidate(); // Redraw the grid.
}
}
}
private int _sizeGridPoints = 3;
public int SizeGridPoints
{
get {
return _sizeGridPoints;
}
set {
if (value != _sizeGridPoints) {
_sizeGridPoints = value;
Invalidate(); // Redraw the grid.
}
}
}
protected override void OnPaint(PaintEventArgs e)
{
// e.Graphics.Clear(Color.Black); Not necessary. We use the BackColor of the panel.
if (LenghtBetweenGridPoints > 0 && SizeGridPoints > 0) {
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; // Optional.
using (var brush = new SolidBrush(ForeColor)) { // We use the ForeColor of the panel.
for (int x = LenghtBetweenGridPoints; x < Width; x += LenghtBetweenGridPoints) {
for (int y = LenghtBetweenGridPoints; y < Height; y += LenghtBetweenGridPoints) {
e.Graphics.FillEllipse(brush, x, y, SizeGridPoints, SizeGridPoints);
}
}
}
}
}
}
编译完成后,它会自动出现在工具箱中window,您可以将其拖放到表单中。您甚至可以在属性 window.
中编辑属性 LenghtBetweenGridPoints
和 SizeGridPoints
您也可以简单地使用网格面板的已有 BackColor
和 ForeColor
属性。这也允许您在属性 window 中设置颜色。不要忘记处理您创建的画笔。
重要提示:不要直接调用 OnPaint
。相反,调用要重绘的对象的 Invalidate
或 Refresh
方法。重点是 Windows 决定何时调用 OnPaint
。例如。如果 Invalidate
被调用得太频繁(例如 1/60 秒内调用 5 次),Windows 可能会决定不每次都调用 OnPaint
,因为这会造成延迟。另一方面,当用户调整面板大小时,Windows 将自动调用 OnPaint
。如果恢复最小化的 window,这也会重新绘制控件。否则它会保持黑色。
我想在我的面板中绘制一个网格。我用位图创建的图形对象(屏幕)没有在我的面板中绘制。我尝试调试以查看屏幕是否未绘制,但事实并非如此。
我尝试从面板 createGraphic 方法创建图形对象,并从面板绘制方法创建参数 painteventargs
。两次我用它用OnPaint
画它都花了太长时间。
public Main()
{
InitializeComponent();
backBuffer = new Bitmap(drawPanel.Width, drawPanel.Height);
screen = Graphics.FromImage(backBuffer);
sizeGridPoints = 2;
lenghtBetweenGridPoints = 10;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
screen.Clear(Color.Black);
DrawGrid();
}
private void DrawGrid()
{
for(int x = lenghtBetweenGridPoints; x < drawPanel.Width; x += lenghtBetweenGridPoints)
{
for(int y = lenghtBetweenGridPoints; y < drawPanel.Height; y+= lenghtBetweenGridPoints)
{
screen.FillEllipse(new SolidBrush(Color.Green), x, y, sizeGridPoints, sizeGridPoints);
}
}
}
如果您从位图创建 Graphics
对象,它将在该位图上绘制,而不是在您的用户界面上绘制。相反,使用 OnPaint
方法的 PaintEventArgs e
中的 Graphics
对象直接在窗体或控件上绘制。
e.Graphics.FillEllipse(new SolidBrush(Color.Green), x, y, sizeGridPoints, sizeGridPoints);
您永远不应该创建自己的 Graphics
对象。
创建您自己的网格控件:
public class GridPanel : Panel
{
public GridPanel()
{
DoubleBuffered = true; // Speeds up drawing, e.g. when panel is resized.
// Set default colors
BackColor = Color.Black;
ForeColor = Color.Green;
}
private int _lenghtBetweenGridPoints = 20;
public int LenghtBetweenGridPoints
{
get { return _lenghtBetweenGridPoints; }
set {
if (value != _lenghtBetweenGridPoints) {
_lenghtBetweenGridPoints = value;
Invalidate(); // Redraw the grid.
}
}
}
private int _sizeGridPoints = 3;
public int SizeGridPoints
{
get {
return _sizeGridPoints;
}
set {
if (value != _sizeGridPoints) {
_sizeGridPoints = value;
Invalidate(); // Redraw the grid.
}
}
}
protected override void OnPaint(PaintEventArgs e)
{
// e.Graphics.Clear(Color.Black); Not necessary. We use the BackColor of the panel.
if (LenghtBetweenGridPoints > 0 && SizeGridPoints > 0) {
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; // Optional.
using (var brush = new SolidBrush(ForeColor)) { // We use the ForeColor of the panel.
for (int x = LenghtBetweenGridPoints; x < Width; x += LenghtBetweenGridPoints) {
for (int y = LenghtBetweenGridPoints; y < Height; y += LenghtBetweenGridPoints) {
e.Graphics.FillEllipse(brush, x, y, SizeGridPoints, SizeGridPoints);
}
}
}
}
}
}
编译完成后,它会自动出现在工具箱中window,您可以将其拖放到表单中。您甚至可以在属性 window.
中编辑属性LenghtBetweenGridPoints
和 SizeGridPoints
您也可以简单地使用网格面板的已有 BackColor
和 ForeColor
属性。这也允许您在属性 window 中设置颜色。不要忘记处理您创建的画笔。
重要提示:不要直接调用 OnPaint
。相反,调用要重绘的对象的 Invalidate
或 Refresh
方法。重点是 Windows 决定何时调用 OnPaint
。例如。如果 Invalidate
被调用得太频繁(例如 1/60 秒内调用 5 次),Windows 可能会决定不每次都调用 OnPaint
,因为这会造成延迟。另一方面,当用户调整面板大小时,Windows 将自动调用 OnPaint
。如果恢复最小化的 window,这也会重新绘制控件。否则它会保持黑色。