Wrong allignment when drawing a JTextPane into a BufferedImage - java

I am trying to draw some styled text into a buffered image. I use a JTextPane which is not part of any view hierarchy. I set the document properties with the desired alignment but the results are not correctly aligned. Even worse, I would get different results for different font size or sometimes even different results when running the same test again.
The following image shows the results. The paragraphs should be be, top to bottom, aligned left, center, right, full. The red frame is the JTextPane border. See for your self.
Because I am a new stackoverflow user, it did not allow me to post an image. You can see the image at http://www.sendtoprint.net/preview/textfile.jpg
This was done on Java 1.7 but did also happen in 1.6. The code:
public void createBufferedImage ()
{
try
{
BufferedImage bi = new BufferedImage (1000, 1200, BufferedImage.TYPE_INT_RGB);
Graphics2D gg = bi.createGraphics ();
gg.setRenderingHint (RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
gg.setRenderingHint (RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
gg.setBackground (Color.white);
gg.fillRect (0, 0, bi.getWidth (), bi.getHeight ());
gg.scale (3.0f, 3.0f);
gg.translate (16, 16);
String text = "The residents of Colorado and Washington state have voted to legalize "
+ "the recreational use of marijuana, and all hell is about to break "
+ "loose -- at least ideologically. The problem is that pot is still very much "
+ "illegal under federal law, and the Obama administration must decide whether "
+ "to enforce federal law in a state that has rejected the substance of that law."
+ "\n\n";
DefaultStyledDocument doc = new DefaultStyledDocument ();
MutableAttributeSet attr = new SimpleAttributeSet ();
StyleConstants.setFontFamily (attr, "Arial");
StyleConstants.setFontSize (attr, 9);
StyleConstants.setForeground (attr, Color.black);
MutableAttributeSet parAttr = new SimpleAttributeSet ();
doc.insertString (0, text, attr);
StyleConstants.setAlignment (parAttr, StyleConstants.ALIGN_LEFT);
doc.setParagraphAttributes (0, doc.getLength (), parAttr, false);
doc.insertString (doc.getLength (), text, attr);
StyleConstants.setAlignment (parAttr, StyleConstants.ALIGN_CENTER);
doc.setParagraphAttributes (doc.getLength () - text.length (), text.length (), parAttr, false);
doc.insertString (doc.getLength (), text, attr);
StyleConstants.setAlignment (parAttr, StyleConstants.ALIGN_RIGHT);
doc.setParagraphAttributes (doc.getLength () - text.length (), text.length (), parAttr, false);
doc.insertString (doc.getLength (), text, attr);
StyleConstants.setAlignment (parAttr, StyleConstants.ALIGN_JUSTIFIED);
doc.setParagraphAttributes (doc.getLength () - text.length (), text.length (), parAttr, false);
JTextPane tc = new JTextPane ();
tc.setBorder (BorderFactory.createLineBorder (Color.red, 1));
tc.setDocument (doc);
tc.setBackground (Color.white);
tc.setLocation (0, 0);
tc.setSize (new Dimension (300, 370));
tc.paint (gg);
System.out.println ("Writing file: " + new Date ().toString ());
File file = new File ("C:\\Users\\Yishai\\Desktop\\text\\file.jpg");
ImageIO.write (bi, "jpg", file);
}
catch (Exception e)
{
System.out.println (e.getMessage ());
}
}
Any ideas what can I do differently? is there a JTextPane setting? A text cache? anything?
Thanks.

Related

panel setBackground is messing up colors of JLabels within

Here's my code in problem.
The problem is that if I use "white" to set the Background of panel, the colors of icon in the "pic" JLabel become very light.
If I use "black" instead, the colors of pic JLabel are visible.
It doesn't matter what colors I use in the pic JLabel. They all get lightened as soon as the panel is set to white.
Is there any other way I can set background color of the panel without affecting the colors of the JLabel within?
Color black = new Color( 20, 20, 20, 255 );
Color white = new Color( 255, 255, 255, 255 );
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize( 1200, 500 );
frame.setVisible(true);
frame.getRootPane().setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.BLACK));
frame.setLocationRelativeTo( null );
frame.setResizable( false );
JPanel panel= new JPanel();
frame.getContentPane().add( panel );
panel.setLayout( null );
panel.getAccessibleContext().setAccessibleName("panel");
panel.getAccessibleContext().setAccessibleDescription(" ");
// this is the line that causes problem
panel.setBackground( black );
JLabel pic = new JLabel( new ImageIcon( showBaseImage() ) );
panel.add( pic );
pic.setSize( 1200, 500 );
pic.setLocation( 1, 1);
pic.setBackground( black );
public BufferedImage showBaseImage(){
BufferedImage c = new BufferedImage( 1200, 500, BufferedImage.TYPE_INT_ARGB );
Graphics2D gg= c.createGraphics();
gg.setPaint( new Color( 125, 0, 125, 255 ));
gg.fillRect( 0,0, c.getWidth(), c.getHeight() );
gg.setPaint( new Color( 255, 255, 225, 255 ));
imgFont = new Font( "Arial", Font.BOLD, 45 );
gg.setFont( imgFont );
gg.drawString( "Write something", 20, 20 );
gg.dispose();
return c;
}
You may use label.setOpaque(true) to allow your label to be opaque.
Its implementation comes from JComponent which is false by default.
Note that labels are not opaque by default. If you need to paint the label's background, it is recommended that you turn its opacity property to "true". The following code snippet shows how to do this.
label.setOpaque(true);
https://docs.oracle.com/javase/tutorial/uiswing/components/label.html

How to either not provide a font that won't render bold or force it to be bold

I have a zoom function that adjusts the font size of row/column labels to match a displayed grid/image. The row/column label corresponding to the hovered cell is bold and all other labels are plain. However, sometimes the hovered horizontal row label will appear plain even though the vertical column label of the same size appears bold.
I've done some testing and have determined that this is happening at certain standard font sizes (12, 18, 24, etc.) for certain fonts (e.g. Courier) and not for other fonts (e.g. Helvetica Neue). Odd font sizes are bolded as expected for all fonts, including the problematic fonts. Even when the font does not appear as bold, when I call myfont.isBold(), it returns true.
My assessment here is that in the case of some fonts, such as my version of courier, a bold version of the font is not available when the size is one that is provided directly from the font library and thus the font defaults to plain. In the case of the odd font sizes, or when the font is rendered vertically, a programmatic bold style is applied.
Am I correct that this is what is happening? If so, how can I catch when this is happening or going to happen, and either not provide that font as an available font, or force the font to render as bold at the problem sizes (e.g. 12)?
Here is a working example:
import java.awt.*;
public class Test {
public static void main ( String[] args ) {
class helloFrame extends Frame {
public void paint( Graphics g ) {
final Graphics2D g2d = (Graphics2D) g;
g2d.setFont(new Font("Courier",Font.BOLD,12));
System.out.println("Style is [" + (g2d.getFont().isBold() ? "bold" : "not bold") + "].");
g2d.drawString("Hello", 10, 40 );
g2d.setFont(new Font("Courier",Font.BOLD,13));
System.out.println("Style is [" + (g2d.getFont().isBold() ? "bold" : "not bold") + "].");
g2d.drawString("Hello", 10, 55 );
g2d.setFont(new Font("Courier",Font.BOLD,17));
System.out.println("Style is [" + (g2d.getFont().isBold() ? "bold" : "not bold") + "].");
g2d.drawString("Hello", 10, 70 );
g2d.setFont(new Font("Courier",Font.BOLD,18));
System.out.println("Style is [" + (g2d.getFont().isBold() ? "bold" : "not bold") + "].");
g2d.drawString("Hello", 10, 85 );
g2d.setFont(new Font("Courier",Font.BOLD,19));
System.out.println("Style is [" + (g2d.getFont().isBold() ? "bold" : "not bold") + "].");
g2d.drawString("Hello", 10, 100 );
}
}
helloFrame frm = new helloFrame();
frm.setSize(150,120);
frm.setVisible(true);
}
}
which prints:
Style is [bold].
Style is [bold].
Style is [bold].
Style is [bold].
Style is [bold].
for every print even though the font does not appear as bold for font sizes 12 & 18:
UPDATE: It appears that this problem is OS-specific. The non-bold text is apparent on Mac but everything appears as it should on Windows.
Try adding:
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
This turns on antialiasing which (at least on my system) greatly improve the font rendering and all sizes appear bold.

How to change font with showconfirmdialog?

I have tried many different tutorials and none have worked this is what I have. Any help?
UIManager.put("OptionPane.font", new FontUIResource(new Font("Press Start 2P", Font.PLAIN, 11)));
if (questionNumber == questions.size()) {
triviagui.questionFrame.setVisible(false);
JOptionPane.showMessageDialog(null, "Your score for this level was : " + levelScore + " out of 10. \n Your total score is " + triviagui.totalScore, "Scores", JOptionPane.INFORMATION_MESSAGE, pokeballIcon);
}
this is how I change my font in a JLabel, so maybe it is any help?
message = new JLabel(textMessage);
// create bigger text (to-times-bigger)
Font f = message.getFont();
message.setFont(new Font(f.getName(), Font.PLAIN, f.getSize()*2));
// put text in middle of vertical space
message.setVerticalTextPosition(JLabel.CENTER);
You just take the font from your label, and reset the font as you like.
Maybe you can do the same with your JDialog?
I found a working answer here: formatting text in jdialog box
this could be a method called by the actionListener of a button:
public void openPopUp(){
String t = "<html>The quick <font color=#A62A2A>brown</font> fox.";
JOptionPane.showMessageDialog(null, t);
}
Gives you this result:

How to center text and a JComponent in a JTextPane vertically?

Currently it looks so
What to do so that it looks so?
Below is my code:
JFrame f = new JFrame();
JTextPane textPane = new JTextPane();
JTextField component = new JTextField(" ");
component.setMaximumSize(component.getPreferredSize());
textPane.setSelectionStart(textPane.getDocument().getLength());
textPane.setSelectionEnd(textPane.getDocument().getLength());
textPane.insertComponent(component);
try {
textPane.getDocument().insertString(textPane.getDocument().getLength(), "text",
new SimpleAttributeSet());
} catch (BadLocationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
f.add(new JScrollPane(textPane));
f.setSize(200, 100);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
The single question which is near to this topic I found: JTextPane insert component, faulty vertical alignment
But there is no answer how to change the alignment. But it must be possible according to the discussion there.
You can use this http://java-sl.com/tip_center_vertically.html
It should work with JComponents as well.
You can also override LabelView's getPreferredSpan() adding some space to the bottom.
Alternatively you can try to override RowView inner class in ParagraphView
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/javax/swing/text/ParagraphView.java#ParagraphView.Row
That points to inner class Row extends BoxView
You should replace it with own one. Try to override
public float getAlignment(int axis)
to return CENTER (0.5). If this does not help override layoutMinorAxis(0 to return proper offsets (shifted).
Define a style for your document with a JLabel and set the vertical aligment on it:
Style s = doc.addStyle("icUf", regular);
ImageIcon icUf = createImageIcon("uf.png", "Unidad Funcional");
if (icUf != null) {
JLabel jl = new JLabel(icUf);
jl.setVerticalAlignment(JLabel.CENTER);
StyleConstants.setComponent(s, jl);
}
Insert the label:
doc.insertString(doc.getLength(), " ", doc.getStyle("icUf"));
and the text:
doc.insertString(doc.getLength(), " text ", doc.getStyle("bold"));
Based on the answer above (which didn't work for me, but helped me find this), I used:
Style s = doc.addStyle("icUf", regular);
ImageIcon icUf = createImageIcon("uf.png", "Unidad Funcional");
if (icUf != null) {
// create label with icon AND text
JLabel jl = new JLabel("some text",icUf, SwingConstants.LEFT);
StyleConstants.setComponent(s, jl);
}
doc.insertString(doc.getLength(), " ", doc.getStyle("icUf"))
This properly aligned the text 'some text' and the icon.

java print api - printing JComponent at 300dpi

please tell me if I am doing something wrong. I want to print barcodes onto labels, so I need high quality printout for these barcodes so I am pushing printer to print in 300dpi. What I've done:
made a big JFrame; width: 2490px, height: 3515px so it represents A4 paper in 1:1 measure (this is A4 paper resolution if print is to be 300dpi)
draw 40 barcode images onto contentPane of that JFrame
setup print attributes so it will print in 300dpi:
PrintRequestAttributeSet aset =
new HashPrintRequestAttributeSet();
PrinterResolution pr =
new PrinterResolution(300,300,PrinterResolution.DPI);
MediaPrintableArea mpa=new MediaPrintableArea(8,21,
210-16, 296-42, MediaPrintableArea.MM);
attribute set is filled with this data:
aset.add( mpa );
aset.add( pr );
aset.add( MediaSizeName.ISO_A4 );
aset.add( new Copies(1) );
aset.add(OrientationRequested.PORTRAIT );
aset.add(PrintQuality.HIGH);
aset.add( Fidelity.FIDELITY_TRUE );
printJob.setPrintable(this);
printJob.print(aset);
this class has print method:
public int print(Graphics g, PageFormat pageFormat, int pageIndex) {
if (pageIndex > 0) {
return(NO_SUCH_PAGE);
} else {
Graphics2D g2d = (Graphics2D)g;
g2d.translate(pageFormat.getImageableX(),pageFormat.getImageableY());
disableDoubleBuffering(componentToBePrinted);
componentToBePrinted.paint(g2d);
enableDoubleBuffering(componentToBePrinted);
return(PAGE_EXISTS);
}
I need to have 40 barcodes on that A4 sheet, each in size 48.5mm x 25.4mm.
What is printed out on paper is 6 barcodes each doubled in size of 104mm x 46mm (that is in width almost half of page's width) which fulfilled whole paper.
Any idea, what can I do wrong?
Your resolution is probably being set to 72 dpi which has the effect of increasing the size of the image.

Categories