(Java Swing)如何创建一个在同一行上有多个图标的JTextPane?
如问题所述,如何在(Java Swing)如何创建一个在同一行上有多个图标的JTextPane?,java,swing,icons,jtextpane,Java,Swing,Icons,Jtextpane,如问题所述,如何在JTextPane中的同一行文本上成功放置多个图标?每次我尝试更改actionText的值时,结果都是非常不可预测的。举个例子,这就是我想要实现的目标: 如果我只传递图标标记来创建图标(“”,例如),它们只是堆叠在一起(或者可能不是,很难说)。如果我把“,”或“和”,那么第一个战斗机图标出现在第一行,而逗号和其他战斗机图标出现在第二行 我目前正在尝试使用一个基于oracle教程的解决方案,用于JTextPane:。下面是创建自定义文本窗格的代码块 public final c
JTextPane
中的同一行文本上成功放置多个图标?每次我尝试更改actionText
的值时,结果都是非常不可预测的。举个例子,这就是我想要实现的目标:
如果我只传递图标标记来创建图标(“”,例如),它们只是堆叠在一起(或者可能不是,很难说)。如果我把“,”或“和”,那么第一个战斗机图标出现在第一行,而逗号和其他战斗机图标出现在第二行
我目前正在尝试使用一个基于oracle教程的解决方案,用于JTextPane
:。下面是创建自定义文本窗格的代码块
public final class GameTextPaneFactory {
private static final String[] ADVENTURER_TOKENS = {"<FIGHTER>", "<CLERIC>", "<WIZARD>", "<ROGUE>"};
private static final int TEXT_PANE_WIDTH = 30;
public static JTextPane createActionTextPane(String actionText) {
ArrayList<String>[] 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<String>[] parseActionText(String text) {
String[] words = text.split(" ");
ArrayList<String> outputStrings = new ArrayList<String>();
ArrayList<String> outputStyles = new ArrayList<String>();
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 "<FIGHTER>":
outputStyles.add("fighterIcon");
break;
case "<CLERIC>":
outputStyles.add("clericIcon");
break;
case "<WIZARD>":
outputStyles.add("wizardIcon");
break;
case "<ROGUE>":
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<String>[] output = new ArrayList[2];
output[0] = outputStrings;
output[1] = outputStyles;
return output;
}
公共最终类GameTextPaneFactory{
私有静态最终字符串[]冒险家_令牌={“”、“”、“”、“”};
私有静态最终整型文本窗格宽度=30;
公共静态JTextPane createActionTextPane(字符串actionText){
ArrayList[]wordsAndStyles=parseActionText(actionText);
JTextPane actionTextPane=新的JTextPane();
StyledDocument doc=actionTextPane.getStyledDocument();
addStylesToDocument(doc);
试一试{
对于(int i=0;i文本窗格宽度){
nextStringBuilder.append(“\n”);
currentLineLength=0;
}
nextStringBuilder.append(“+”字);
currentLineLength+=字长度()+1;
}
}
如果(nextStringBuilder.length()!=0){
add(nextStringBuilder.toString());
添加(“常规”);
}
@抑制警告(“未选中”)
ArrayList[]输出=新的ArrayList[2];
输出[0]=输出字符串;
输出[1]=输出样式;
返回输出;
}
}
如果有人有更好的解决办法,我会洗耳恭听。谢谢 尝试添加
outputStrings.add(" "); // this is ignored, but cannot be empty
outputStyles.add("regular");
在每一个新的“冒险家”风格之后
outputStrings.add(“”;//这将被忽略,但不能为空
开关(字){
案例“”:
outputStyles.add(“fighterIcon”);
打破
案例“”:
outputStyles.add(“clericIcon”);
打破
案例“”:
添加(“向导图标”);
打破
案例“”:
outputStyles.add(“rogueIcon”);
打破
}
OutputString.add(“”;//这将被忽略,但不能为空
添加(“常规”);
已更新
我有一个小游戏,看看我是否可以得到格式看起来更好一点,这基本上是我想出的
我基本上没有使用样式,而是直接将文本和图像插入到文本窗格中。似乎有类似样式的问题被设置在彼此的旁边,因此,相反,它们基本上被合并到文档中的单个条目中,这可以解释为什么您的样式存在问题。出于某种原因,我对图标也有类似的问题,因此,我必须在每个tim中创建一个新实例
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");
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;
}