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

[6637 byte] By [Vercingetorixa] at [2007-11-27 6:23:12]
# 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.

camickra at 2007-7-12 17:40:50 > top of Java-index,Desktop,Core GUI APIs...
# 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?

Vercingetorixa at 2007-7-12 17:40:50 > top of Java-index,Desktop,Core GUI APIs...
# 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);

}

}

Vercingetorixa at 2007-7-12 17:40:50 > top of Java-index,Desktop,Core GUI APIs...