一个近乎自组织的标签云






4.86/5 (14投票s)
在标签云中显示和使用项目进行数据输入。
引言
我经常在网站上看到标签云,但我需要在 Windows 窗体中使用它们。因此,我开发了一个可以轻松添加到窗体中的控件。它将帮助您根据重要性可视化文本或集合中的字符串。除此之外,您还可以单击项目以将其用于数据输入。每次点击都会增加项目的重要性,并可能改变云中项目的视图,因为它们都与云中所有其他项目相关联。
背景
字符串(我也称它们为“项目”)存储在 XML 文件中。XML 文件设计非常简单。每个项目都存储在一个 Tag
中,该 Tag
具有三个属性:Text
、Occurrence
和 Last
。示例
<Tag Text="ABC of programming" Occurrence="5" Last="633923147566312334" />
Text
包含项目的文本,Occurrence
存储项目被使用的频率(或项目在文本中出现的次数),Last
包含上次访问的时间(以 DateTime.Ticks
表示)。我实现了对名为“Tags.xml”的默认 XML 文件的访问,该文件位于程序目录中。当然,您可以加载和保存任何用户创建的标签文件。
为了演示控件的使用,我编写了一个包装器,它向您展示了控件的大部分功能。请注意,该包装器在 GUI 编程方面并非杰作。它的唯一目的是展示与标签云相关的一些效果。
在截图中(图 2),“读取默认标签 XML”按钮已被按下,其效果是默认文件“Tags.xml”的内容显示在标签云中。在右侧,您可以看到云中可以显示的项目数量:“云中显示的项目数量”,以及所有正在使用的项目数量:“所有项目数量”。在我们的示例中,可以显示 34 个项目。标签云中显示的项目数量取决于控件的大小(您可以在包装器中以“+10”的步长更改它)以及项目权重(即它们的出现频率)之间的复杂交互。
项目权重通过五种不同的字体样式和颜色可视化。您可以通过设置控件的属性来更改它们(稍后描述)。包装器演示了如何通过“设置输出设计 1”更改最不重要项目的输出设计,以及通过“设置输出设计 3”更改中等重要项目的输出设计。您可以使用“设置标准输出设计”重置为默认值。
除此之外,您还可以更改控件的背景颜色(默认值为 Color.Azure
)和标签的外观。设置属性“Underline on”会在鼠标悬停时显示项目下划线,设置“Frame on”会在项目周围显示框架(这也是单击项目时的捕获区域)。
点击项目会触发事件。您可以在包装器的“标签信息”区域中看到这一点:点击的文本显示在“文本”文本框中,出现次数显示在“出现次数”文本框中。每次点击项目都会使其权重增加 1,并且根据其他项目,它会改变其在云中的输出设计(或者不会!)。是否属于某个输出设计是通过统计方法计算的,取决于所有项目的总体平均值和标准差。您还可以找到“最”和“最少”点击的项目以及“最年轻”和“最老”点击的项目。
在“一些标签操作”区域中,您可以研究如何添加项目(请研究源代码,了解那里实际发生了什么),并且您可以“清除所有项目”。使用“添加此项目”,您可以向云中添加一个项目。它必须在按钮左侧的文本框中进行编辑。添加新项目时,其权重(出现次数)将设置为所有项目的平均值,以使其真正出现。如果它从权重 1 开始,则可能不会显示,因为其他项目会占据主导地位。
要操作云控件的内容,您可以右键单击项目打开上下文菜单。您可以添加新项目、删除项目或更改项目文本。
在云中显示标签的另一种方法是打开文本文件或 HTML 文件。这在“从文本和 HTML 文件读取标签”区域中进行了演示。那里的三个按钮演示了打开文本或 HTML 文件,评估其中的重要标签,并在云控件中显示标签。由于英语(或德语)中有许多填充词,我添加了两个文件:ExcludeList-en.txt 和 ExcludeList-de.txt,它们包含一些在构建云词列表时不会被考虑的词。这些词包括:I、you、are、if、them、here、about、never... 该列表会根据预期的语言读取。在我的示例中,它是英语和德语(没有法语、西班牙语、意大利语......抱歉)。我知道这些列表不完整,所以您可以随意添加或删除词,甚至为所需的语言设计一个排除列表。当尝试显示 HTML 文件时,会使用另一个排除列表:ExcludeList-html.txt。它包含一些 HTML 和网页设计的语法(但也不完整)。
此外,云控件具有拖放功能。您可以获取任何文本或 HTML 文件并将其拖放到控件上。请注意不要使用过大的文件。我实现了一些检查以避免加载错误的文件格式,因此您可能会收到类似这样的消息
下面,您可以看到一个英文文本文件(例如:majorca_en.txt),它已被拖放到云控件上。为了在控件中显示更多项目,高度和宽度已手动扩展。
Using the Code
要使用云控件,您必须将“TagCloud.dll”添加到您的引用中。您可以在 TagCloudWrapper 项目中最好地看到它,该项目是解决方案的一部分。
在以下部分中,我将尝试描述“TagCloud”项目的类。
TXT处理
这个类负责读取文本或 HTML 文件。文件中的单词由一些分隔符(如“,.:";”)分隔。下一步,检查所有单词是否“需要”。需要意味着它们不属于相应的排除列表。
但是,让我们从头开始。首先,检查一个文件是文本文件、HTML 文件,还是两者都不是。一个基本的算法检查它是英文还是德文文本,以及它是文本还是 HTML
void GetFileTypeAndLanguage(string filename,
out bool ishtml,
out TagCloudControl.TextLanguage language)
根据结果,调用 (ishtml == false
)
bool ReadTextFile(out SortedList<string, TagCloudControl.StringItem> sc,
string filename,
TagCloud.TagCloudControl.TextLanguage language)
或 (ishtml == true
)
bool ReadHTMLFile(out SortedList<string, TagCloudControl.StringItem> sc,
string filename,
TagCloud.TagCloudControl.TextLanguage language)
被调用。此外,根据英语或德语,将适当的排除列表应用于单词。对于 HTML 文件,HTML 排除列表也将应用于过滤一些 HTML 特定的单词。结果是“所需”单词的列表,这些单词存储在 SortedList sc
中。此列表的部分内容将显示在云控件中。
关于排除列表的简短评论:如上所述,它们被称为:ExcludeList-en.txt、ExcludeList-de.txt 和 ExcludeList-html.txt。
它们是普通的文本文件,您可以自行更改。
语法如下
Exclude:
word1, word2, word3, word4,..
wordxxx,wordyyy, wordzzz,...
...
Include:
word1, word2
“ExcludeList-en.txt”的示例部分
Exclude:
a,able,about,above,ah,ain't,alas,am,an,any,anybody,
anyone,anywhere,after,again,against,ago,all,also,
although,among,and,are,around,as,at,away,
...
Include:
May,US,
您可以看到还有一个“Include”部分。它的目的是包含通常应该排除的单词。在“Exclude”部分中的单词应该用小写字母书写并用逗号分隔。由于“may”和“May”具有不同的含义,您应该在“Include”部分定义所有不应以您在那里定义的方式(即:区分大小写)书写时被排除的单词。请随意添加或删除单词。我不是以英语为母语的人,所以我想您可以进行很多改进。
“TXTHandling
”类中处理单词的一些方法有
int FillExcludeIncludeList(
TagCloud.TagCloudControl.TextLanguage language,
bool clear)
bool WantedWord(string newword)
bool WantedHTMLWord(string newword)
bool IsRomanNumber(string number)
bool ContainsDigit(string word)
bool IsTimeSpan(string timespan)
XML处理
“XMLHandling
”类包含读取和写入标签文件的方法,该文件包含云的标签(项目)。“ReadTagFile
”和“WriteTagFile
”方法是重载的。它们提供对特定文件名或默认标签文件“Tags.xml”的访问。默认文件名由“GetDefaultFileName
”方法获取。
文件格式
“FileFormats
”类包含一些检查文件格式的方法。检查以下一些格式
- 图形文件格式
- 音频文件格式
- 视频文件格式
- 压缩文件格式
- 程序和开发文件格式
- 文档文件格式
- 系统文件格式
- 数据库文件格式
该列表并非详尽无遗——您可以随意添加其他文件格式。文件通过读取其魔术数字以简单的方式识别。这些是字节序列,大部分位于文件的开头,可以让您大致了解它可能是什么类型的文件。在此解决方案中,这些方法用于避免“错误”文件被拖放到云控件上。
统计
“Statistics
”类负责提供值集合的平均值
double Mean(IEnumerable<double> values)
和标准差
double StandardDeviation(IEnumerable<double> values, out double mean)
这两个值对于将项目与其在其他项目中的上下文联系起来至关重要,以决定它是否会显示在云控件中以及它在那里具有什么权重。根据其权重,将为其分配 5 种输出设计(字体、颜色)之一。
添加项目和重命名项目
这些类是简单的对话框,当在上下文菜单中单击时显示。“AddItem
”允许您向云中添加一个新项目,“RenameItem
”为您提供了更改现有项目名称的可能性。
TagCloudControl
这个类是云控件管理和显示的核心类。它包含许多属性和方法来控制云控件。在下面的部分中,我将描述其中一些。理解其功能的最佳方法是研究 TagCloudWrapper
中的方法和属性调用。
我们从 属性 开始
// Sets or gets the control's back color
public Color ControlBackColor
// Sets or gets the condition for drawing a rectangle
public bool ControlTextFrame
// Sets or gets the condition for drawing
// the text strings underlined on mouse hover
public bool ControlTextUnderline
// Sets or gets the control's height.
// Due to a height change, the cloud is set and painted new
public int ControlHeight
// Sets or gets the control's width.
// Due to a width change, the cloud is set and painted new
public int ControlWidth
// Gets the most clicked text item from
// the list with text items (StringCollection)
public string MostClickedItem
// Gets the least clicked text item from
// the list with text items (StringCollection)
public string LeastClickedItem
// Gets the oldest clicked text item from
// the list with text items (StringCollection)
public string OldestClickedItem
// Gets the youngest clicked text item from
// the list with text items (StringCollection)
public string YoungestClickedItem
// Gets the number of the items in StringCollection
public int ItemsCount
// Gets the number of the items shown in the cloud
public int ShownItemsCount
唯一触发的事件是鼠标单击项目时
[Description("Delegates a click onto the user control to the wrapper")]
// delegate declaration
public delegate void OnUserControlClick(string Text, double Occurrence);
// event declaration
public event OnUserControlClick clickHandler;
该事件返回云中项目的文本和出现次数。
输出设计管理的公共方法
// Sets the 5 predefined output designs
public void SetAllDesigns(bool update)
// Sets an output design
public bool SetDesign(int number, string font, float size, Color color)
// Overloaded, sets an output design
public bool SetDesign(int number, OutputDesign od)
字符串管理的公共方法
// Adds or replaces a text item to the list of items (StringCollection).
// If the item is new, its occurrence is set to 1,
// else its previous occurrence is incremented by 1.
// The attribute 'last' (last access) will be set to 'now'.
public void AddItem(string text)
// Overloaded, adds a text item to the list of items (StringCollection).
// The attribute 'last' (last access) will be set to 'now'.
public void AddItem(string text, double occ)
// Overloaded, adds a text item to the list of items (StringCollection).
// The attribute 'last' (last access) will be set by last.
public void AddItem(string text, double occ, long last)
// Overloaded, adds a complete list sc to the list of items (StringCollection).
public void AddItem(SortedList<string, StringItem> sc)
// Overloaded, adds or replaces a text item to the list of items (StringCollection).
// If the item exists already in StringCollection,
// the variable regardmean will be interpreted:
// - if regardmean is true and the item is not yet member of CloudCollections,
// the occurrence will be set to the mean occurrence
// of the items in the StringCollection
// - otherwise its occurrence is incremented by 1.
// If the item does not exist, the variable regardmean will be interpreted:
// - false: the occurrence will be set to 1
// - true: the occurrence will be set to the mean occurrence
// of the items in the StringCollection.
// The attribute 'last' (last access) will be set to 'now'.
public void AddItem(string text, bool regardmean)
// Removes the item text from the item list (StringCollection).
public void RemoveItem(string text)
// Clears the list with the items (StringCollection) completely.
public void ClearAllItems()
// Returns all the items from the StringCollection.
public SortedList<string, StringItem> GetAllItems()
构建云的私有方法
这些方法都是私有的,因为它们仅在以下情况被调用:
- 字符串被添加或从字符串集合中删除
- 项目的权重发生变化
- 项目的输出设计发生变化
- 云的设计发生变化
这些方法负责构建云的内容并显示项目
private void SetCloud()
private void CopyStringsToCloud()
private int BuildCloud(ref StringItem si)
该算法的工作原理如下:项目按字母顺序排列。根据它们的权重,它们会获得一种输出设计(5 种之一)。将计算项目的文本尺寸是否适合云。如果尺寸超出右边界,则会开始新的一行。一行的高度由该行中项目的最大高度决定。当您查看图 3 时,您可以最好地理解它,其中显示了文本边界(框架开启)。新行将以相同的方式填充,并且这样做直到达到云控件的下边界。如果项目列表尚未结束,则“最弱”的项目将从应显示的项目列表中删除。“最弱”的项目是出现次数最少且长时间未被调用的项目。
现在,云控件的填充开始一个新的周期。由于已删除一个项目,其他项目的权重可能已更改。因此,输出设计可能由于新的统计计算而发生更改,并且相应地,文本尺寸也可能发生更改。整个过程是一个递归过程,旨在显示大多数“重要”项目。在这种情况下,“重要”意味着出现次数最多且最近被调用的项目。有关详细信息,请研究代码。也许可以优化,但在我的机器上,我没有性能问题。
关注点
我计划在未来的两个应用程序中使用云控件。
一方面,我想编写一个程序,对数码相机拍摄的图像进行一些基本修改。其中一个要点是重命名文件,我想我将使用标签云来获取半自动文件重命名的关键字。我计划根据我们上次假期创建一组关键字,就像图 6 示例中建议的那样。
另一方面,我还计划编写一个程序,通过提问来帮助您学习,您必须正确回答这些问题。问题是随机提出的,但我可以想象,额外提供一个包含基于主题的关键字的标签云,您可以点击这些关键字,会是一件好事。
我希望您有更多的好主意——请告诉我!
历史
- 初始版本 1.0:2009 年 12 月。