正如问题所述,我如何成功地将多个图标放在同一行文本中JTextPane
?每当我尝试改变其值时actionText
,结果都是非常不可预测的.举个例子,这就是我想要实现的目标:
如果我只传递图标标记来创建图标(例如""),它们只是叠加在一起(或者可能不是,很难说).如果我输入","或"和",则第一个战斗机图标出现在第一行,而逗号和其他战斗机图标出现在第二行.
我目前正在尝试使用基于oracle教程构建的解决方案JTextPane
:JTextPane教程.以下是我创建自定义文本窗格的代码块.
public final class GameTextPaneFactory { private static final String[] ADVENTURER_TOKENS = {"", " ", " ", " "}; private static final int TEXT_PANE_WIDTH = 30; public static JTextPane createActionTextPane(String actionText) { ArrayList [] wordsAndStyles = parseActionText(actionText); JTextPane actionTextPane = new JTextPane(); StyledDocument doc = actionTextPane.getStyledDocument(); addStylesToDocument(doc); try { for (int i=0; i < wordsAndStyles[0].size(); i++) { doc.insertString(doc.getLength(), wordsAndStyles[0].get(i), doc.getStyle(wordsAndStyles[1].get(i))); } } catch (BadLocationException ble) { System.err.println("Couldn't insert initial text into text pane."); } actionTextPane.setEditable(false); return actionTextPane; } private static void addStylesToDocument(StyledDocument doc) { // TODO add images (styles) here Style def = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE); Style regular = doc.addStyle("regular", def); Style icons = doc.addStyle("fighterIcon", regular); StyleConstants.setAlignment(icons, StyleConstants.ALIGN_CENTER); ImageIcon fighterIcon = new ImageIcon("images/fighter_image.png", "fighter"); StyleConstants.setIcon(icons, fighterIcon); icons = doc.addStyle("clericIcon", regular); StyleConstants.setAlignment(icons, StyleConstants.ALIGN_CENTER); ImageIcon clericIcon = new ImageIcon("images/cleric_image.png", "cleric"); StyleConstants.setIcon(icons, clericIcon); icons = doc.addStyle("wizardIcon", regular); StyleConstants.setAlignment(icons, StyleConstants.ALIGN_CENTER); ImageIcon wizardIcon = new ImageIcon("images/wizard_image.png", "wizard"); StyleConstants.setIcon(icons, wizardIcon); icons = doc.addStyle("rogueIcon", regular); StyleConstants.setAlignment(icons, StyleConstants.ALIGN_CENTER); ImageIcon rogueIcon = new ImageIcon("images/rogue_image.png", "rogue"); StyleConstants.setIcon(icons, rogueIcon); } private static ArrayList [] parseActionText(String text) { String[] words = text.split(" "); ArrayList outputStrings = new ArrayList (); ArrayList outputStyles = new ArrayList (); StringBuilder nextStringBuilder = new StringBuilder(); int currentLineLength = TEXT_PANE_WIDTH; for(String word : words) { if(Arrays.asList(ADVENTURER_TOKENS).contains(word)) { if(nextStringBuilder.length() != 0) { outputStrings.add(nextStringBuilder.toString()); outputStyles.add("regular"); nextStringBuilder = new StringBuilder(); } outputStrings.add(" "); // this is ignored, but cannot be empty switch(word) { case " ": outputStyles.add("fighterIcon"); break; case " ": outputStyles.add("clericIcon"); break; case " ": outputStyles.add("wizardIcon"); break; case " ": outputStyles.add("rogueIcon"); break; } currentLineLength += 3; // an icon is about 3 characters in length } else { if(currentLineLength + word.length() + 1 > TEXT_PANE_WIDTH) { nextStringBuilder.append("\n"); currentLineLength = 0; } nextStringBuilder.append(" " + word); currentLineLength += word.length() + 1; } } if(nextStringBuilder.length() != 0) { outputStrings.add(nextStringBuilder.toString()); outputStyles.add("regular"); } @SuppressWarnings("unchecked") ArrayList [] output = new ArrayList[2]; output[0] = outputStrings; output[1] = outputStyles; return output; }
}
如果有人有更好的解决方案,我全都耳朵.谢谢!
尝试添加
outputStrings.add(" "); // this is ignored, but cannot be empty outputStyles.add("regular");
每个新的"冒险家"风格后
outputStrings.add(" "); // this is ignored, but cannot be empty switch (word) { case "<FIGHTER>": outputStyles.add("fighterIcon"); break; case "<CLERIC>": outputStyles.add("clericIcon"); break; case "<WIZARD>": outputStyles.add("wizardIcon"); break; case "<ROGUE>": outputStyles.add("rogueIcon"); break; } outputStrings.add(" "); // this is ignored, but cannot be empty outputStyles.add("regular");
更新
我有点玩,看看我是否可以让格式看起来好一点,这基本上就是我想出来的......
我基本上将文本和图像直接插入文本窗格,而不是使用样式.似乎有类似样式的问题彼此相邻设置,所以相反,它们基本上合并到文档中的单个条目,这可以解释为什么你的样式有问题.出于某种原因,我在图标上遇到了类似的问题,因此我每次都必须创建一个新实例...
这有点粗糙和准备,但基本的想法是存在的.它基本上使用正则表达式API来查找"关键字"的所有匹配项,在它之前插入文本,然后根据关键字插入一个特殊图标...
public static JTextPane createActionTextPane(String actionText) { JTextPane actionTextPane = new JTextPane(); actionTextPane.setOpaque(false); StyledDocument doc = actionTextPane.getStyledDocument(); Pattern pattern = Pattern.compile("<FIGHTER>|<CLERIC>|<GOLD>"); Matcher matcher = pattern.matcher(actionText); int previousMatch = 0; while (matcher.find()) { int startIndex = matcher.start(); int endIndex = matcher.end(); String group = matcher.group(); String subText = actionText.substring(previousMatch, startIndex); if (!subText.isEmpty()) { actionTextPane.replaceSelection(subText); } switch (group) { case "<FIGHTER>": actionTextPane.insertIcon(new ImageIcon("fifight.gif")); break; case "<CLERIC>": actionTextPane.insertIcon(new ImageIcon("mage.gif")); break; case "<GOLD>": actionTextPane.insertIcon(new ImageIcon("Gold.png")); break; } previousMatch = endIndex; } String subText = actionText.substring(previousMatch); if (!subText.isEmpty()) { actionTextPane.replaceSelection(subText); } actionTextPane.setEditable(false); return actionTextPane; }
现在,坦率地说,我并没有对线宽等感到困扰,相反,使用了a JScrollPane
和它JTextComponent
的包装功能......但这取决于你......