Reputation: 1642
I am sorry for the lack of a better title, but I have no idea how to specify the error further, since I don't understand its nature. Maybe someone can edit it, when the problem is understood.
I am writing an application in which the user can add icons into a text field. I obviously picked a JTextPane
to display the text and the icons. After playing around with the insertComponent()
function of the class I ran into some weird layout problems, so I decided to lookup the tutorial at oracle.com. After looking at the source code of the example, I decided to do the same and also use styles to add components to the underlying StyledDocument
. It was when I started the first test run, when I discovered, that the layout problems stayed the same.
So, what is actually happening?
What I intended the text pane to show is "abcOdefO", but as you can tell by the screenshot, the two icons (circles) have some space to the right of them. I want the icon to be treated as a slightly larger character, so it should only occupy as much space as it needs, not (availableSpace / numberOfIcons), which seems to be what it actually occupies.
When typing another character at the caret position:
This is even weirder. If the icons have MouseListeners
, all 4 visible circles trigger the event. If I drag the frame to another window or minimize and restore it, the weird parts vanish and the frame looks like the first image (except for the additional character). So I guess, this part of my problem is fixed with a call to repaint()
at the correct location - but where?
This is the code that produces the images seen above:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;
public class TextPaneTestPanel extends JPanel {
private class myIcon extends JPanel {
private final int side;
private final int padding = 1;
public myIcon(int size) {
this.side = size - 2 * padding;
this.setSize(size, size);
this.setPreferredSize(getSize());
this.setMinimumSize(getSize());
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.BLACK);
g2d.setStroke(new BasicStroke(2));
g2d.drawOval(padding, padding, side, side);
}
}
private final JTextPane textPane;
public TextPaneTestPanel() {
textPane = new JTextPane();
StyledDocument doc = textPane.getStyledDocument();
Style def = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
StyleConstants.setFontFamily(def, "Monospaced");
Style regular = doc.addStyle("regular", def);
try {
doc.insertString(0, "abc", regular);
Style s1 = doc.addStyle("icon1", regular);
StyleConstants.setComponent(s1, new myIcon(20));
doc.insertString(3, " ", s1);
doc.insertString(4, "def", regular);
Style s2 = doc.addStyle("icon2", regular);
StyleConstants.setComponent(s2, new myIcon(20));
doc.insertString(7, " ", s2);
} catch (BadLocationException e1) {
e1.printStackTrace();
}
this.setLayout(new GridBagLayout());
this.add(textPane, new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(4, 4, 4, 4), 0, 0));
}
public static void main(String[] args) {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
TextPaneTestPanel panel = new TextPaneTestPanel();
frame.getContentPane().add(panel);
frame.setSize(300, 100);
frame.setVisible(true);
}
}
To sum up my questions:
What causes the space to appear after an icon?
Where do I add the repaint()
or revalidate()
to fix the problem seen in image #2?
P.S.: I know, that my "icon" does not implement Icon
, but it shouldn't be necessary, since JTextPanes
can handle all sorts of Components
.
Upvotes: 3
Views: 636
Reputation: 324118
1.What causes the space to appear after an icon?
Well, you have the following code:
this.setMinimumSize(getSize());
What about the maximum size?
How to fix the problem seen in image #2?
Custom painting is done by overriding the paintComponent() method, not the paint() method and don't forget to invoke super.paintComponent.
An Icon would be more appropriate here since all you are doing is custom painting. Or even a JComponent, but not a JPanel which is a Container used for holding other components. Plus is you use an Icon you don't have the size problems that you have with a panel, or JComponent since that method is specifically implemented as part of the interface.
Upvotes: 2