我的程序的目标是从整数值的字符串树Map中打印一个单词标记云。数字最大的字符串将是字体最大的单词,以此类推。唯一的问题,我似乎是与交叉的话,当印刷。我一直在使用矩形与文本内,以检测交叉点使用交集方法。我的想法是从中间开始所有的单词,然后在一个随机的方向(上,下,左,右)移动每个单词,直到文本框不再与任何其他框相交。这是为了确保单词之间的空白尽可能少,没有交叉。这是我的密码:
import java.util.*;
import java.util.Map.Entry;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
public class draw extends Canvas{
Map<String, Integer> map = new TreeMap<String, Integer>();
public draw() {
map.put("kaylen", 16);
map.put("mia", 17);
map.put("isabel", 19);
map.put("sarah", 15);
map.put("natalie", 20);
map.put("emily", 5);
map.put("chang", 12);
map.put("dorothy", 2);
map.put("victoria", 17);
map.put("katie", 25);
map.put("hannah", 14);
map.put("megan", 9);
map.put("grace", 25);
map.put("rachel", 18);
}
public void paint(Graphics window){
setBackground(Color.white);
ArrayList<Integer> sortHighLow = new ArrayList<Integer>(); //used to sort the values from high to low
ArrayList<String> wordsDescend = new ArrayList<String>(); //list of strings in descending value based on points
for(Entry<String, Integer> entry: map.entrySet()) {
Integer a = entry.getValue();
sortHighLow.add(a);
}
Collections.sort(sortHighLow, Collections.reverseOrder());
for(Integer i: sortHighLow) {
for( Entry<String, Integer> entry : map.entrySet() ){
if(entry.getValue()==i && !wordsDescend.contains(entry.getKey())) {
wordsDescend.add(entry.getKey());
}
}
}
int largest = 200; //largest font size
int count = 0;
Rectangle[] rectangles;
ArrayList<Integer> width = new ArrayList<Integer>(); //list of each individual string/box's width
ArrayList<Integer> height = new ArrayList<Integer>(); //list of each individual string/box's height
ArrayList<Integer> fonts = new ArrayList<Integer>(); //list of each string's font sizes
for(String s: wordsDescend) {
//used to create box/rectangle dimensions + font sizes
int x = 400;//(int)(Math.random() * (700 - 100 + 1) + 100);
int y = 400;//(int)(Math.random() * (700 - 100 + 1) + 100);
AffineTransform affinetransform = new AffineTransform();
FontRenderContext frc = new FontRenderContext(affinetransform,true,true);
//window.setFont(new Font("Courier New", Font.PLAIN, largest-(count*13)));
Font font = new Font("Courier New", Font.PLAIN, largest-(count*14));
fonts.add(largest-(count*14));
int textwidth = (int)(font.getStringBounds(s, frc).getWidth());
width.add(textwidth);
int textheight = (int)(font.getStringBounds(s, frc).getHeight());
height.add(textheight);
count++;
}
rectangles = new Rectangle[fonts.size()];
for(int i=0; i < fonts.size(); i++) {
//used initialize each rectangle and assign it in rectangles list
Rectangle temp = new Rectangle(400, 400, width.get(i), height.get(i));
rectangles[i]=temp;
}
//checks to see if a rectangle intersects with any other rectangle and if it does, it moves it and checks again if the new position intersects any other rectangles
for(int i = 0; i < rectangles.length; i++) {
for(int j = 0; j<rectangles.length; j++) {
if((i!=j)&&(rectangles[i].intersects(rectangles[j]))) {
while(rectangles[i].intersects(rectangles[j])) {
int change= (int)(Math.random() * (1 - 1 + 1) - 1);
int change2= (int)(Math.random() * (1 - 1 + 1) - 1);
rectangles[i]= new Rectangle(rectangles[i].x+change, rectangles[i].y+change2, rectangles[i].width, rectangles[i].height);
}
}
j=0;
}
}
for(int x = 0; x<rectangles.length; x++) {
//prints out the strings in set font sizes and colors
window.setFont(new Font("Courier New", Font.PLAIN, fonts.get(x)));
window.setColor(new Color((int)(Math.random() * 0x1000000)));
window.drawString(wordsDescend.get(x), rectangles[x].x, rectangles[x].y+rectangles[x].height);
}
}
}
跑步者:
import javax.swing.JFrame;
public class drawRunner extends JFrame
{
public drawRunner()
{
super("tag cloud");
setSize(800,800);
draw r = new draw();
getContentPane().add(r);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
r.paint(getGraphics());
}
public static void main( String args[] )
{
drawRunner run = new drawRunner();
}
}
我没有收到任何错误信息,但我的图形面板拒绝显示除白色背景以外的任何内容。而且每次我试图关闭图形窗口时,它都不会关闭。有没有其他方法来移动字符串?另外,如何在标记云中实现水平和垂直字符串,而不仅仅是我所拥有的水平字符串?
1条答案
按热度按时间bis0qfac1#
你应该延长一段时间
JPanel
(或jcomponent)用于使用swing时的自定义绘制。你重写了吗
paintComponent()
用于定制绘画。绘制方法不应更改零部件的状态,只应绘制现有状态。这意味着所有的ArrayList都应该在绘制方法之外创建(和排序)。
不要使用
getGraphics()
. 当swing确定需要绘制组件时,swing将图形对象传递给paintcomponent()方法。绘画方法不应该使用随机逻辑。绘制方法将被多次调用,您不希望绘制随机更改。
类名应该以大写字符开头。
阅读swing教程中有关自定义绘制的部分,了解工作示例。下载工作代码并进行小的更改。然后测试。然后再做一个改变。在尝试编写自定义绘制的整个应用程序之前,请先学习绘制的基础知识。