【问题标题】:Creating different brush patterns in c#在 C# 中创建不同的画笔图案
【发布时间】:2018-03-15 03:09:17
【问题描述】:

我正在尝试制作类似于绘画的东西。我试图弄清楚如何制作不同的画笔样式。就像在 Paint 3D 中一样,使用钢笔工具与使用画笔工具相比,您会得到一定的线条填充。

我什至不知道从哪里开始。我花了一天的大部分时间浏览文档和观看 YouTube 视频。我比开始时更失落。我遇到的最接近的东西是线帽,但这绝对不是我想要的。

【问题讨论】:

标签: c# winforms picturebox


【解决方案1】:

!!查看下面的更新!!

Hans' link 应该为您指明正确的方向,即指向TextureBrushes

为了帮助您进一步了解以下几点:

  • TextureBrush 是画笔,而不是钢笔。所以你不能沿着一条路径走,就像鼠标移动沿着那条曲线画一样。相反,您需要找到一个区域来填充画笔。

  • 这也意味着你需要决定如何以及何时触发绘图;基本选项是按时间和/或按距离。通常,用户可以为这些通常称为“流量”和“距离”的参数设置参数。..

  • 您可以继续将形状添加到 GraphicsPath 并填充该路径,而不是填充简单的形状并绘制其中的许多形状。

  • 要创建 TextureBrush 您需要一个具有透明度的图案文件。您可以制作一些或从网络上下载它们,其中很多都是免费的。

  • 大多数都是 Photoshop 画笔格式“abr”;如果它们不是太新 (abrMate 将它们转换为 png 文件。

  • 您可以将一组画笔加载到 ImageList,设置为足够大的尺寸(最大 256x256)和 32bpp 以允许 alpha。

  • 大多数图案都是带有 alpha 的黑色,因此如果您想要颜色,您需要创建当前画笔图像的彩色版本(可能使用 ColorMatrix)。

  • 您可能还想更改其透明度(最好也使用 ColorMatrix)。

  • 并且您需要将大小更改为当前画笔大小。


更新

在做了一些测试之后,我不得不收回原来的假设,即 TextureBrush 是一种适合使用纹理笔尖进行绘图的工具。

填充区域可以,但是徒手画就不行了。有几个原因..:

  • 其中一个原因是 TextureBrush 将始终以某种方式平铺图案,无论是否翻转,这将始终看起来像您正在揭示一个大的底层图案,而不是用几个笔划堆积油漆.

  • 另一个问题是找到要填充的区域相当困难。

  • 此外,提示可能是方形的,也可能不是方形的,但除非你用矩形填充,否则会有间隙。

请参阅here,了解您在工作中想要什么的示例。

解决方案非常简单,上面的大部分内容仍然适用:

  • 您所做的几乎是常规绘图,但最后,您使用准备好的“画笔”图案绘制DrawImage

常规绘图涉及:

  • 一个List<List<Point>> curves 包含所有完成的鼠标路径
  • 当前路径的List<Point> curentCurve

Paint 事件中,您绘制所有曲线,如果有任何点,还绘制当前路径。

对于带图案的绘图,还需要知道何时绘制哪个图案版本。

如果我们确保不泄露它们,我们可以缓存画笔图案..:

Bitmap brushPattern = null;
List<Tuple<Bitmap,List<Point>>> curves = new List<Tuple<Bitmap,List<Point>>>();
Tuple<Bitmap, List<Point>> curCurve = null;

这是一种简单/简单的缓存方法。为了提高效率,您可以使用带有命名方案的Dictionary&lt;string, Bitmap&gt;,该方案从模式索引、大小、颜色、alpha 和可能的旋转角度生成字符串;这样每个模式将只存储一次。

这是一个工作示例:

几点说明:

在 MouseDown 我们创建一个新的电流曲线:

curCurve = new Tuple<Bitmap, List<Point>>(brushPattern, new List<Point>());
curCurve.Item2.Add(e.Location);

在 MouseUp 中,我将当前曲线添加到曲线列表中:

 curves.Add(new Tuple<Bitmap, List<Point>>(curCurve.Item1, curCurve.Item2.ToList()));

由于我们要清除当前曲线,我们需要复制它的点列表;这是通过ToList() 调用实现的!

在 MouseMove 中,我们只需为其添加一个新点:

if (e.Button == MouseButtons.Left)
{
    curCurve.Item2.Add(e.Location);
    panel1.Invalidate();
}

Paint 遍历所有曲线,包括当前曲线:

for (int c = 0; c < curves.Count; c++)
{
    e.Graphics.TranslateTransform(-curves[c].Item1.Width / 2, -curves[c].Item1.Height / 2);
    foreach (var p in curves[c].Item2)
        e.Graphics.DrawImage(curves[c].Item1, p);
    e.Graphics.ResetTransform();
}
if (curCurve != null && curCurve.Item2.Count > 0)
{
    e.Graphics.TranslateTransform(-curCurve.Item1.Width / 2, -curCurve.Item1.Height / 2);

    foreach (var p in curCurve.Item2)
        e.Graphics.DrawImage(curCurve.Item1, p);
    e.Graphics.ResetTransform();
}

确保图案居中绘制。

ListView 设置为 SmallIcons,其 SmallImageList 指向原始 ImageList 的较小副本。

重要的是让面板Doublebuffered!避免闪烁!


更新: 可以使用 PictureboxLabel(与 Autosize=false );两者都具有开箱即用的DoubleBuffered 属性,并且比Panels 更支持绘图。

顺便说一句:上述快速而肮脏的示例只有 200 行(未注释)。添加画笔旋转、预览、步进距离、保存按钮并实现画笔缓存使其达到 300 行。

【讨论】:

  • 哦该死的,这比纹理画笔更漂亮!
  • @TaW 抱歉,我没有得到带有 ColorMatrix 的零件。我浏览了文档。 QBrush 但我找不到任何相关的东西。这出现在后续问题SO: QPainter how draw texture with special color 中。如果您能详细说明这一点(以启发我们),我会很高兴。
  • ColorMatrix 是一种快速简单的图像更改方法。请参阅here 以获得出色的指南。 - 请参阅here 了解更多为图像着色的信息。 - 有关更改 alpha(即透明度)的更多信息,请参阅 here
  • @TaW,你好!你能提供这个项目的源代码吗?我试图重现,但它非常难看。据我了解,您为 WinForms 制作了这个示例?我需要一个 WPF 版本,但如果您没有 wpf,请给您的 winForms 完整示例?请用 URL(源代码)更新您的答案?
猜你喜欢
  • 2014-07-20
  • 1970-01-01
  • 2011-10-26
  • 1970-01-01
  • 1970-01-01
  • 2016-08-10
  • 1970-01-01
  • 2010-10-31
  • 1970-01-01
相关资源
最近更新 更多