BufferedImage on JTextPane
Hi,
Please help me solving two problems I have encountered in my application.
My class Frame creates a GUI with menubar, toolbar, status bar and a vertical radio buttons bar. Views menu contains Draw and Count submenus. When Count view is selected, then the drawing from draw view is transformed in a BufferedImage, that is drawn in reduced scale on a scrollable JTextPane. In reality my code is more complicated then the following one, made just to demonstrate the problems:
1. The image has black borders on the right and bottom side, how can I eliminate them?
2. How can the cursor be placed bellow the image? (Actually the cursor appears only pressing Enter repeatedly.)
[import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import com.borland.jbcl.layout.*;
import java.awt.image.BufferedImage;
class DrawPanel
extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(40, 40, 600, 400);
}
}
class CountPanel
extends JTextPane {
final Image im;
public CountPanel(BufferedImage im) {
setBackground(SystemColor.LIGHT_GRAY);
this.im = im;
MediaTracker tr = new MediaTracker(this);
tr.addImage(im, 0);
try {
tr.waitForID(0);
}
catch (InterruptedException e) {
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
if (im != null) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g2.drawImage(im, 0, 0, Toolkit.getDefaultToolkit().
getScreenSize().width * 2 / 3,
Toolkit.getDefaultToolkit().
getScreenSize().height * 2 / 3, this);
g2.dispose();
}
}
}
public class Frame
extends JFrame {
JMenuBar jMenuBar = new JMenuBar();
JToolBar jToolBar = new JToolBar();
JMenu viewMenu = new JMenu();
JMenuItem drawView = new JMenuItem();
JMenuItem countView = new JMenuItem();
JButton jButton1 = new JButton();
JButton jButton2 = new JButton();
JRadioButton line = new JRadioButton("Line");
JRadioButton rect = new JRadioButton("Rectangle");
ButtonGroup bg = new ButtonGroup();
JPanel buttonPanel = new JPanel();
JPanel drawPanel = new JPanel();
static JLabel statusBar = new JLabel();
BorderLayout borderLayout = new BorderLayout();
VerticalFlowLayout verticalFlowLayout = new VerticalFlowLayout();
JPanel views = new JPanel(new CardLayout());
final String VIEW1 = "Draw view";
final String VIEW2 = "Count view";
DrawPanel draw;
CountPanel count;
BufferedImage im;
public Frame() {
try {
init();
setVisible(true);
}
catch (Exception exception) {
exception.printStackTrace();
}
}
private void init() throws Exception {
setBounds(0, 0, Toolkit.getDefaultToolkit().getScreenSize().width,
Toolkit.getDefaultToolkit().getScreenSize().height * 48 /
50);
setTitle("Black borders");
draw = new DrawPanel();
draw.setBackground(SystemColor.text);
draw.add(drawPanel);
views.add(draw, VIEW1);
JTextPane countPanel = new JTextPane();
countPanel.setBounds(0, 0, Toolkit.getDefaultToolkit().
getScreenSize().width,
Toolkit.getDefaultToolkit().
getScreenSize().height);
viewMenu.setText("Views");
drawView.setText("Draw");
drawView.addActionListener(new Frame_drawView_actionAdapter(this));
countView.setText("Count");
countView.addActionListener(new Frame_countView_actionAdapter(this));
bg.add(line);
bg.add(rect);
jButton1.setToolTipText("Draw view");
jButton2.setToolTipText("Count view");
jMenuBar.add(viewMenu);
viewMenu.add(drawView);
viewMenu.add(countView);
setJMenuBar(jMenuBar);
jToolBar.add(jButton1);
jToolBar.add(jButton2);
buttonPanel.add(line);
buttonPanel.add(rect);
buttonPanel.setLayout(verticalFlowLayout);
statusBar.setAlignmentY( (float) 0.0);
statusBar.setActionMap(null);
statusBar.setLabelFor(null);
statusBar.setText("Draw view");
JPanel cp = (JPanel) getContentPane();
cp.setLayout(borderLayout);
cp.add(new JScrollPane(countPanel));
cp.add(views, java.awt.BorderLayout.CENTER);
cp.add(buttonPanel, java.awt.BorderLayout.EAST);
cp.add(jToolBar, java.awt.BorderLayout.NORTH);
cp.add(statusBar, java.awt.BorderLayout.SOUTH);
}
public void drawView_actionPerformed(java.awt.event.ActionEvent e) {
try {
buttonPanel.setVisible(true);
( (CardLayout) (views.getLayout())).show(views, VIEW1);
statusBar.setText(
"Draw view");
}
catch (Exception exception) {
exception.printStackTrace();
}
}
public void countView_actionPerformed(java.awt.event.ActionEvent e) {
buttonPanel.setVisible(false);
im = new BufferedImage(Toolkit.getDefaultToolkit().getScreenSize().width,
Toolkit.getDefaultToolkit().getScreenSize().height
, BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D)this.getGraphics();
g = im.createGraphics();
draw.paint(g);
g.dispose();
count = new CountPanel(im);
JScrollPane sp = new JScrollPane(count);
views.add(sp, VIEW2);
( (CardLayout) (views.getLayout())).show(views, VIEW2);
statusBar.setText(
"Count view.");
}
public static void main(String[] args) {
new Frame();
}
}
class Frame_drawView_actionAdapter
implements java.awt.event.ActionListener {
private Frame adaptee;
Frame_drawView_actionAdapter(Frame adaptee) {
this.adaptee = adaptee;
}
public void actionPerformed(java.awt.event.ActionEvent e) {
adaptee.drawView_actionPerformed(e);
}
}
class Frame_countView_actionAdapter
implements java.awt.event.ActionListener {
private Frame adaptee;
Frame_countView_actionAdapter(Frame adaptee) {
this.adaptee = adaptee;
}
public void actionPerformed(java.awt.event.ActionEvent e) {
adaptee.countView_actionPerformed(e);
}
}
]
Waiting for answer, with best regards,
Vercingetorix
# 1
The posted code is not compileable.
If you need further help then you need to create a [url http://homepage1.nifty.com/algafield/sscce.html]Short, Self Contained, Compilable and Executable, Example Program[/url] (SSCCE) that demonstrates the incorrect behaviour.
Don't forget to use the [url http://forum.java.sun.com/help.jspa?sec=formatting]Code Formatting Tags[/url] so the posted code retains its original formatting.
# 2
> The posted code is not compileable.
The posted code compiles well with JBuilder2005 I'm using.
> If you need further help then you need to create a
> [url
> http://homepage1.nifty.com/algafield/sscce.html]Short,
> Self Contained, Compilable and Executable, Example
> Program[/url] (SSCCE) that demonstrates the incorrect
> behaviour.
As I stated, the given program is a demo one, the original has more then 3000 rows
> Don't forget to use the [url
> http://forum.java.sun.com/help.jspa?sec=formatting]Cod
> e Formatting Tags[/url] so the posted code retains
> its original formatting.
Excuse me, I've not used correct the Formatting Tags, but this time I hope the code will be readable.
Meantime I found the answer to the first question:
I changed the BufferedImage size and I put the radio buttons on toolbar,
in the following code the previous code lines, that caused the black borders, appear in comments:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import com.borland.jbcl.layout.*;
import java.awt.image.BufferedImage;
class DrawPanel
extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(40, 40, 600, 400);
}
}
class CountPanel
extends JTextPane {
final Image im;
public CountPanel(BufferedImage im) {
setBackground(SystemColor.LIGHT_GRAY);
this.im = im;
MediaTracker tr = new MediaTracker(this);
tr.addImage(im, 0);
try {
tr.waitForID(0);
}
catch (InterruptedException e) {
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
if (im != null) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g2.drawImage(im, 0, 0, Toolkit.getDefaultToolkit().
getScreenSize().width * 2 / 3,
Toolkit.getDefaultToolkit().
getScreenSize().height * 2 / 3, this);
g2.dispose();
}
}
}
public class Frame
extends JFrame {
JMenuBar jMenuBar = new JMenuBar();
JToolBar jToolBar = new JToolBar();
JMenu viewMenu = new JMenu();
JMenuItem drawView = new JMenuItem();
JMenuItem countView = new JMenuItem();
JButton jButton1 = new JButton();
JButton jButton2 = new JButton();
JRadioButton line = new JRadioButton("Line");
JRadioButton rect = new JRadioButton("Rectangle");
ButtonGroup bg = new ButtonGroup();
JPanel buttonPanel = new JPanel();
JPanel drawPanel = new JPanel();
static JLabel statusBar = new JLabel();
BorderLayout borderLayout = new BorderLayout();
/*Code that caused the black borders:
VerticalFlowLayout verticalFlowLayout = new VerticalFlowLayout();*/
JPanel views = new JPanel(new CardLayout());
final String VIEW1 = "Draw view";
final String VIEW2 = "Count view";
DrawPanel draw;
CountPanel count;
BufferedImage im;
JPanel cp;
public Frame() {
try {
init();
setVisible(true);
}
catch (Exception exception) {
exception.printStackTrace();
}
}
private void init() throws Exception {
setBounds(0, 0, Toolkit.getDefaultToolkit().getScreenSize().width,
Toolkit.getDefaultToolkit().getScreenSize().height * 48 /
50);
setTitle("Black borders");
draw = new DrawPanel();
draw.setBackground(SystemColor.text);
draw.add(drawPanel);
views.add(draw, VIEW1);
JTextPane countPanel = new JTextPane();
countPanel.setBounds(0, 0, Toolkit.getDefaultToolkit().
getScreenSize().width,
Toolkit.getDefaultToolkit().
getScreenSize().height);
viewMenu.setText("Views");
drawView.setText("Draw");
drawView.addActionListener(new Frame_drawView_actionAdapter(this));
countView.setText("Count");
countView.addActionListener(new Frame_countView_actionAdapter(this));
bg.add(line);
bg.add(rect);
jButton1.setToolTipText("Draw view");
jButton2.setToolTipText("Count view");
jMenuBar.add(viewMenu);
viewMenu.add(drawView);
viewMenu.add(countView);
setJMenuBar(jMenuBar);
jToolBar.add(jButton1);
jToolBar.add(jButton2);
buttonPanel.add(line);
buttonPanel.add(rect);
jToolBar.add(buttonPanel);
/* Code that caused the black borders:
buttonPanel.setLayout(verticalFlowLayout);*/
statusBar.setAlignmentY( (float) 0.0);
statusBar.setActionMap(null);
statusBar.setLabelFor(null);
statusBar.setText("Draw view");
cp = (JPanel) getContentPane();
cp.setLayout(borderLayout);
cp.add(new JScrollPane(countPanel));
cp.add(views, java.awt.BorderLayout.CENTER);
/* Code that caused the black borders:
cp.add(buttonPanel, java.awt.BorderLayout.EAST);*/
cp.add(jToolBar, java.awt.BorderLayout.NORTH);
cp.add(statusBar, java.awt.BorderLayout.SOUTH);
}
public void drawView_actionPerformed(java.awt.event.ActionEvent e) {
try {
buttonPanel.setVisible(true);
( (CardLayout) (views.getLayout())).show(views, VIEW1);
statusBar.setText(
"Draw view");
}
catch (Exception exception) {
exception.printStackTrace();
}
}
public void countView_actionPerformed(java.awt.event.ActionEvent e) {
buttonPanel.setVisible(false);
im = new BufferedImage(cp.getSize().width,
cp.getSize().height -
jMenuBar.getBounds().height -
jToolBar.getBounds().height
, BufferedImage.TYPE_INT_RGB);
/* Code that caused the black borders:
Toolkit.getDefaultToolkit().getScreenSize().width,
Toolkit.getDefaultToolkit().getScreenSize().height */
Graphics2D g = (Graphics2D)this.getGraphics();
g = im.createGraphics();
draw.paint(g);
g.dispose();
count = new CountPanel(im);
JScrollPane sp = new JScrollPane(count);
views.add(sp, VIEW2);
( (CardLayout) (views.getLayout())).show(views, VIEW2);
statusBar.setText(
"Count view.");
}
public static void main(String[] args) {
new Frame();
}
}
class Frame_drawView_actionAdapter
implements java.awt.event.ActionListener {
private Frame adaptee;
Frame_drawView_actionAdapter(Frame adaptee) {
this.adaptee = adaptee;
}
public void actionPerformed(java.awt.event.ActionEvent e) {
adaptee.drawView_actionPerformed(e);
}
}
class Frame_countView_actionAdapter
implements java.awt.event.ActionListener {
private Frame adaptee;
Frame_countView_actionAdapter(Frame adaptee) {
this.adaptee = adaptee;
}
public void actionPerformed(java.awt.event.ActionEvent e) {
adaptee.countView_actionPerformed(e);
}
}
So remains only one question : how to place the cursor of the JTextPane (=caret ) at the bottom of the inserted BufferedImage?
# 3
Although I've reviewed some thousands answers, I didn't find the second solution.
My advice for those in same situation is to not give up, and to continue the search in Archived Forums.
Here I found an answer given by Camickr in Nov 11, 2002:
http://forum.java.sun.com/thread.jspa?forumID=257&threadID=322346
Based upon this idea, finally I found a solution:
I have introduced as many line feeds \n as the quotient height of the inserted BufferedImage/ the height of a row is.
The code is the following:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;//New import to the second solution.
import com.borland.jbcl.layout.*;
import java.awt.image.BufferedImage;
class DrawPanel
extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(40, 40, 600, 400);
}
}
class CountPanel
extends JTextPane {
final Image im;
public CountPanel(BufferedImage im) {
setBackground(SystemColor.LIGHT_GRAY);
this.im = im;
MediaTracker tr = new MediaTracker(this);
tr.addImage(im, 0);
try {
tr.waitForID(0);
}
catch (InterruptedException e) {
}
//Beginning of sol. 2
FontMetrics fm = this.getFontMetrics(this.getFont());
introwHeight = fm.getHeight();
intimHeight = Toolkit.getDefaultToolkit().
getScreenSize().height * 2 / 3;
StyledDocument doc = this.getStyledDocument();
try { for (int i = 0; i <= imHeight/rowHeight ; i = i + 1) {
doc.insertString(doc.getLength(), "To be continued.\n", null);
}
} catch (Exception e) {
e.printStackTrace();
}
//End of sol. 2
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
if (im != null) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g2.drawImage(im, 0, 0, Toolkit.getDefaultToolkit().
getScreenSize().width * 2 / 3,
Toolkit.getDefaultToolkit().
getScreenSize().height * 2 / 3, this);
g2.dispose();
}
}
}
public class Frame
extends JFrame {
JMenuBar jMenuBar = new JMenuBar();
JToolBar jToolBar = new JToolBar();
JMenu viewMenu = new JMenu();
JMenuItem drawView = new JMenuItem();
JMenuItem countView = new JMenuItem();
JButton jButton1 = new JButton();
JButton jButton2 = new JButton();
JRadioButton line = new JRadioButton("Line");
JRadioButton rect = new JRadioButton("Rectangle");
ButtonGroup bg = new ButtonGroup();
JPanel buttonPanel = new JPanel();
JPanel drawPanel = new JPanel();
static JLabel statusBar = new JLabel();
BorderLayout borderLayout = new BorderLayout();
//VerticalFlowLayout verticalFlowLayout = new VerticalFlowLayout();
JPanel views = new JPanel(new CardLayout());
final String VIEW1 = "Draw view";
final String VIEW2 = "Count view";
DrawPanel draw;
CountPanel count;
BufferedImage im;
JPanel cp;
public Frame() {
try {
init();
setVisible(true);
}
catch (Exception exception) {
exception.printStackTrace();
}
}
private void init() throws Exception {
setBounds(0, 0, Toolkit.getDefaultToolkit().getScreenSize().width,
Toolkit.getDefaultToolkit().getScreenSize().height * 48 /
50);
setTitle("Black borders");
draw = new DrawPanel();
draw.setBackground(SystemColor.text);
draw.add(drawPanel);
views.add(draw, VIEW1);
JTextPane countPanel = new JTextPane();
countPanel.setBounds(0, 0, Toolkit.getDefaultToolkit().
getScreenSize().width,
Toolkit.getDefaultToolkit().
getScreenSize().height);
viewMenu.setText("Views");
drawView.setText("Draw");
drawView.addActionListener(new Frame_drawView_actionAdapter(this));
countView.setText("Count");
countView.addActionListener(new Frame_countView_actionAdapter(this));
bg.add(line);
bg.add(rect);
jButton1.setToolTipText("Draw view");
jButton2.setToolTipText("Count view");
jMenuBar.add(viewMenu);
viewMenu.add(drawView);
viewMenu.add(countView);
setJMenuBar(jMenuBar);
jToolBar.add(jButton1);
jToolBar.add(jButton2);
buttonPanel.add(line);
buttonPanel.add(rect);
jToolBar.add( buttonPanel);
// buttonPanel.setLayout(verticalFlowLayout);
statusBar.setAlignmentY( (float) 0.0);
statusBar.setActionMap(null);
statusBar.setLabelFor(null);
statusBar.setText("Draw view");
cp = (JPanel) getContentPane();
cp.setLayout(borderLayout);
cp.add(new JScrollPane(countPanel));
cp.add(views, java.awt.BorderLayout.CENTER);
// cp.add(buttonPanel, java.awt.BorderLayout.EAST);
cp.add(jToolBar, java.awt.BorderLayout.NORTH);
cp.add(statusBar, java.awt.BorderLayout.SOUTH);
}
public void drawView_actionPerformed(java.awt.event.ActionEvent e) {
try {
buttonPanel.setVisible(true);
( (CardLayout) (views.getLayout())).show(views, VIEW1);
statusBar.setText(
"Draw view");
}
catch (Exception exception) {
exception.printStackTrace();
}
}
public void countView_actionPerformed(java.awt.event.ActionEvent e) {
buttonPanel.setVisible(false);
im = new BufferedImage(cp.getSize().width,
cp.getSize().height -
jMenuBar.getBounds().height -
jToolBar.getBounds().height
, BufferedImage.TYPE_INT_RGB);
/* The code that caused the black borders:
Toolkit.getDefaultToolkit().getScreenSize().width,
Toolkit.getDefaultToolkit().getScreenSize().height */
Graphics2D g = (Graphics2D)this.getGraphics();
g = im.createGraphics();
draw.paint(g);
g.dispose();
count = new CountPanel(im);
JScrollPane sp = new JScrollPane(count);
views.add(sp, VIEW2);
( (CardLayout) (views.getLayout())).show(views, VIEW2);
statusBar.setText(
"Count view.");
}
public static void main(String[] args) {
new Frame();
}
}
class Frame_drawView_actionAdapter
implements java.awt.event.ActionListener {
private Frame adaptee;
Frame_drawView_actionAdapter(Frame adaptee) {
this.adaptee = adaptee;
}
public void actionPerformed(java.awt.event.ActionEvent e) {
adaptee.drawView_actionPerformed(e);
}
}
class Frame_countView_actionAdapter
implements java.awt.event.ActionListener {
private Frame adaptee;
Frame_countView_actionAdapter(Frame adaptee) {
this.adaptee = adaptee;
}
public void actionPerformed(java.awt.event.ActionEvent e) {
adaptee.countView_actionPerformed(e);
}
}
