java - 将图像添加到与线条重叠的 JTextPane 以节省空间
问题描述
我有一个带有 StyledDocument 的 JTextPane,需要在高于字体的文本之间添加一个图像。这意味着通常这条线会变高:
我的目标是让图像略微重叠,因此它使用更少的空间。在 MCVE 中,我通过返回较小的垂直跨度来实现这一点,IconView
如下所示:
所以基本上它认为图像不那么高,但无论如何都会完全绘制它。
这主要是有效的,但是有两个问题:
- 额外的高度仍然只添加在顶部,如果均匀分布可能会更好。
- 但更重要的是,有时底部不会被绘制,例如在上下滚动时:
很容易理解,因为下半部分并不是图像预期的位置。
我现在的问题是,有没有更好(不那么老套)的方法来防止图像占用这么多空间?或者至少是一种修复绘图的方法?我已经对代码进行了一些研究,但我不确定哪个部分负责决定绘制什么或如何最好地更改它而不弄乱其他任何东西。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BadLocationException;
import javax.swing.text.BoxView;
import javax.swing.text.ComponentView;
import javax.swing.text.Element;
import javax.swing.text.IconView;
import javax.swing.text.LabelView;
import javax.swing.text.ParagraphView;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
public class OverlappingImage {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createGui();
});
}
private static void createGui() {
JTextPane textPane = new JTextPane();
textPane.setEditorKit(new MyEditorKit());
textPane.setEditable(false);
textPane.setPreferredSize(new Dimension(320, 200));
StyledDocument doc = textPane.getStyledDocument();
SimpleAttributeSet iconStyle = new SimpleAttributeSet();
StyleConstants.setIcon(iconStyle, createImage());
try {
doc.insertString(doc.getLength(), TEST_TEXT+"\n"+TEST_TEXT, null);
doc.insertString(doc.getLength(), "Image", iconStyle);
doc.insertString(doc.getLength(), TEST_TEXT, null);
} catch (BadLocationException ex) {
Logger.getLogger(OverlappingImage.class.getName()).log(Level.SEVERE, null, ex);
}
JFrame window = new JFrame();
window.add(new JScrollPane(textPane), BorderLayout.CENTER);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.pack();
window.setLocationByPlatform(true);
window.setTitle("Test");
window.setVisible(true);
}
static class MyEditorKit extends StyledEditorKit {
private final ViewFactory factory;
public MyEditorKit() {
this.factory = new StyledViewFactory();
}
@Override
public ViewFactory getViewFactory() {
return factory;
}
static class StyledViewFactory implements ViewFactory {
@Override
public View create(Element elem) {
String kind = elem.getName();
if (kind != null) {
if (kind.equals(AbstractDocument.ContentElementName)) {
return new LabelView(elem);
} else if (kind.equals(AbstractDocument.ParagraphElementName)) {
return new ParagraphView(elem);
} else if (kind.equals(AbstractDocument.SectionElementName)) {
return new BoxView(elem, View.Y_AXIS);
} else if (kind.equals(StyleConstants.ComponentElementName)) {
return new ComponentView(elem);
} else if (kind.equals(StyleConstants.IconElementName)) {
return new MyIconView(elem);
}
}
return new LabelView(elem);
}
}
}
static class MyIconView extends IconView {
public MyIconView(Element elem) {
super(elem);
}
@Override
public float getPreferredSpan(int axis) {
if (axis == View.Y_AXIS) {
float height = super.getPreferredSpan(axis);
return height * 0.7f;
}
return super.getPreferredSpan(axis);
}
}
/**
* Creates the example image.
*/
public static ImageIcon createImage() {
BufferedImage image = new BufferedImage(28,28, BufferedImage.TYPE_INT_ARGB);
Graphics g = image.getGraphics();
g.setColor(Color.GREEN);
g.fillRect(0, 0, 28, 28);
g.setColor(Color.BLACK);
g.drawRect(0, 0, 27, 27);
g.dispose();
return new ImageIcon(image);
}
private static final String TEST_TEXT = "Lorem ipsum dolor sit amet, "
+ "consectetur adipisici elit, sed eiusmod tempor incidunt ut "
+ "labore et dolore magna aliqua. Ut enim ad minim veniam, quis "
+ "nostrud exercitation ullamco laboris nisi ut aliquid ex ea "
+ "commodi consequat. Quis aute iure reprehenderit in voluptate "
+ "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur "
+ "sint obcaecat cupiditat non proident, sunt in culpa qui officia "
+ "deserunt mollit anim id est laborum.";
}
解决方案
有没有更好(不那么老套)的方法来防止图像占用这么多空间?或者至少是一种修复绘图的方法?
不知道这是否更好或更少hacky(或者它是否会起作用),所以我会让你决定。
也许您可以对图像进行自己的自定义绘画:
与其将图标添加到文档中,不如添加一个
Box.createHorizontalStrut(...)
为Icon
.然后您可以使用
createPosition()
文档的方法来获取Icon
应该添加的位置。您创建一个
HashMap
来存储Position
和Icon
对象。然后重写
paintComponent()
文本窗格的方法以遍历HashMap
并绘制所有图标。该Position
对象将包含添加组件的偏移量。您可以使用 的modelToView(...)
方法Document
来获取组件在文本窗格中的 x/y 位置。做数学以垂直居中图标,然后绘制它。
推荐阅读
- r - R将新列添加到数据框中,按周平均
- python-3.x - 我应该使用什么方法让 TCP 服务器在 Python3 中处理许多客户端设备?
- docker - Docker 映像未更新
- arrays - 如何检查Google表格中的任何时间范围是否相互重叠
- reactjs - react-leaflet-universal 的 ts 模块声明不起作用
- java - 如何获取运行时依赖项以及 Gradle 项目的坐标和 JAR 文件?
- python - Python在dict中创建值时将数组更改为包含数组的字符串
- python - aiohttp - 如何绕过 Duplicate Content-Length Header 错误并读取响应标头?
- android - 为什么我不能使用 AudioTrack 的静态模式播放原始音频字节?
- python - 将尺寸为 (3,50) 的嵌入层连接到 lstm