如何使用java画布和矩形打印标记云

wb1gzix0  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(394)

我的程序的目标是从整数值的字符串树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();
    }
}

我没有收到任何错误信息,但我的图形面板拒绝显示除白色背景以外的任何内容。而且每次我试图关闭图形窗口时,它都不会关闭。有没有其他方法来移动字符串?另外,如何在标记云中实现水平和垂直字符串,而不仅仅是我所拥有的水平字符串?

bis0qfac

bis0qfac1#

你应该延长一段时间 JPanel (或jcomponent)用于使用swing时的自定义绘制。
你重写了吗 paintComponent() 用于定制绘画。
绘制方法不应更改零部件的状态,只应绘制现有状态。这意味着所有的ArrayList都应该在绘制方法之外创建(和排序)。
不要使用 getGraphics() . 当swing确定需要绘制组件时,swing将图形对象传递给paintcomponent()方法。
绘画方法不应该使用随机逻辑。绘制方法将被多次调用,您不希望绘制随机更改。
类名应该以大写字符开头。
阅读swing教程中有关自定义绘制的部分,了解工作示例。下载工作代码并进行小的更改。然后测试。然后再做一个改变。在尝试编写自定义绘制的整个应用程序之前,请先学习绘制的基础知识。

相关问题