Removing borders on custom buttons - java

I've written this small program which attempts to create a custom JButton unfortunately I can't manage to remove the border. I thought button.setBorder(null); would remove it but this has been ineffective. Does anyone know how to remove the border from the button so it's just the icon? Any help greatly appreciated.
My code is as follows:
package custombuttons;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class CustomButtons {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
CustomButtons h = new CustomButtons();
h.setUp();
}
JFrame frame;
JPanel panel;
JButton button;
BufferedImage b;
String toolTip = "Configure";
public void setUp() {
frame = new JFrame("Custom Buttons");
try {
b = ImageIO.read(CustomButtons.class.getResource("/images/config.png"));
} catch (IOException ex) {
Logger.getLogger(CustomButtons.class.getName()).log(Level.SEVERE, null, ex);
ex.printStackTrace();
}
Image b1 = (Image) b;
ImageIcon iconRollover = new ImageIcon(b1);
int w = iconRollover.getIconWidth();
int h = iconRollover.getIconHeight();
GraphicsConfiguration gc = frame.getGraphicsConfiguration();
Image image = gc.createCompatibleImage(w, h, Transparency.TRANSLUCENT);
Graphics2D g = (Graphics2D) image.getGraphics();
g.drawImage(iconRollover.getImage(), 0, 0, null);
g.dispose();
ImageIcon iconDefault = new ImageIcon(b1);
image = gc.createCompatibleImage(w, h, Transparency.TRANSLUCENT);
g = (Graphics2D) image.getGraphics();
g.drawImage(iconRollover.getImage(), 2, 2, null);
g.dispose();
ImageIcon iconPressed = new ImageIcon(b1);
JButton button = new JButton();
button.setIgnoreRepaint(true);
button.setFocusable(false);
button.setToolTipText(toolTip);
button.setBorder(null);
button.setContentAreaFilled(false);
button.setIcon(iconDefault);
button.setRolloverIcon(iconRollover);
button.setPressedIcon(iconPressed);
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout(FlowLayout.LEFT));
panel = new JPanel();
panel.setOpaque(false);
panel.add(button);
frame.getContentPane().add(panel);
frame.setVisible(true);
}
}

have look at button.setBorderPainted(false) more about JButton here

actually i tested your code on my Netbeans IDE and got no borders as you desire
using only button.setBorder(null); or button.setBorderPainted(false); or both of them but
i think you should make sure that your original image is really do not have any borders it self

Related

Java Swing: How to set text on a self customized Jbutton?

This is my JButton code:
JButton Savebtn = new JButton();//("Save");
Savebtn.setFont(btnFont);
Savebtn.setOpaque(false);
Savebtn.setContentAreaFilled(false);
Savebtn.setBorder(null);
Savebtn.setMargin(new Insets(0, 0, 0, 0));
Savebtn.setIcon(new ImageIcon("src/Pic2/menubtn0.png"));
Savebtn.setPressedIcon(new ImageIcon("src/Pic2/menubtn1.png"));
//Savebtn.setText("Save");
The effect is like this :
I tried to do this:
JButton Savebtn = new JButton();//("Save");
Savebtn.setFont(btnFont);
Savebtn.setOpaque(false);
Savebtn.setContentAreaFilled(false);
Savebtn.setBorder(null);
Savebtn.setMargin(new Insets(0, 0, 0, 0));
Savebtn.setIcon(new ImageIcon("src/Pic2/menubtn0.png"));
Savebtn.setPressedIcon(new ImageIcon("src/Pic2/menubtn1.png"));
Savebtn.setText("Save");
The text did not appear and a white line occured at the right side.
Could any one help me with this?
PS:I can't just put the words onto my picture because the button text I want to show is related to my program.
The button picture:
The text did not appear and a white line occured at the right side
I suspect your issue is that you are not using layout managers (or you are manually setting the preferred size of your button) and the size of your button is incorrect and the text is being truncated.
By default the text will appear to the right of the Icon. So what you see is your Icon and then the gap between the Icon and the text.
You need to configure the button for the text to display centered on top the Icon (not right of the Icon):
JButton button = new JButton( "Save" );
button.setIcon(...);
button.setPressedIcon(...);
button.setHorizontalTextPosition(JLabel.CENTER);
button.setVerticalTextPosition(JLabel.CENTER);
I took your code snippet and put it in a GUI I created.
Here's what I came up with.
Now, it's not a very responsive button. You can't tell whether it's pressed or not.
What I did was comment out all of the unusual JButton methods and made sure I could display an ordinary JButton.
Then I uncommented out one line at a time and tested.
Test, test, test.
Here's the code I tested with.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class CustomButtonGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new CustomButtonGUI());
}
#Override
public void run() {
JFrame frame = new JFrame("Custom Button");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createButtonPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setPreferredSize(new Dimension(300, 100));
Font font = panel.getFont().deriveFont(48f);
JButton saveButton = new JButton("Save");
saveButton.setFont(font);
saveButton.setOpaque(false);
saveButton.setContentAreaFilled(false);
saveButton.setBorder(null);
saveButton.setMargin(new Insets(0, 0, 0, 0));
// saveButton.setIcon(new ImageIcon("src/Pic2/menubtn0.png"));
// saveButton.setPressedIcon(new ImageIcon("src/Pic2/menubtn1.png"));
//
panel.add(saveButton, BorderLayout.CENTER);
return panel;
}
}
I think you are using the JButton wrong, the setIcon and setPressedIcon is literally for an icon next to the JButton, however, for a game you probably want the background to change when pressed from one image to another, which by default the JButton class does not support.
Here is a custom JButton I made that allows exactly this:
CustomJButton.java:
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import javax.swing.JButton;
public class CustomJButton extends JButton {
private final BufferedImage normalIcon;
private final BufferedImage selectedIcon;
public CustomJButton(BufferedImage normalImage, BufferedImage selectedImage) {
super();
setOpaque(false);
setContentAreaFilled(false);
setBorder(null);
setFocusPainted(false);
setMargin(new Insets(0, 0, 0, 0));
this.normalIcon = normalImage;
this.selectedIcon = selectedImage;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(normalIcon.getWidth(), normalIcon.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
// lets anti-alias for better quality
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// lets anti-alias for text too
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
// lets draw the correct image depending on if the button is pressed or not
if (getModel().isPressed()) {
g2d.drawImage(selectedIcon, 0, 0, getWidth(), getHeight(), this);
} else {
g2d.drawImage(normalIcon, 0, 0, getWidth(), getHeight(), this);
}
// calc string x and y position
Font font = getFont();
String text = getText();
FontMetrics metrics = g2d.getFontMetrics(font);
int textWidth = metrics.stringWidth(text);
int textHeight = metrics.getHeight();
int textY = getWidth() / 2 - textWidth / 2;
int textX = getHeight() / 2 - textHeight / 2 + metrics.getAscent();
// draw the text
g2d.drawString(text, textY, textX);
}
}
Which you would then use like this:
CustomJButton button = new CustomJButton(ImageIO.read(new URL("https://i.stack.imgur.com/xCGQQ.png")), ImageIO.read(new URL("https://i.stack.imgur.com/R9i1s.png")));
button.setFont(new Font("Jokerman", Font.BOLD, 22));
button.setForeground(Color.WHITE);
button.setText("Press Me!");
button.addActionListener((ActionEvent e) -> {
JOptionPane.showMessageDialog(frame, "You pressed me");
});

How to draw something over all components of a JPanel

How to draw something over all components of a Panel?
In the code below I tried to do this overriding the paintComponent method, I call super.paintComponent(g) hoping this will draw all components added as part of the constructor, but still my X stays below the image.
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.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Stack extends JPanel {
private final JLabel some_text = new JLabel("Some very long text that will be covered", JLabel.LEFT);
private final JLabel some_icon = new JLabel((Icon)null, JLabel.CENTER);
public static final String COMPASS_URL = "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/Compass_Rose_English_North.svg/240px-Compass_Rose_English_North.svg.png";
public Stack() throws IOException {
super(new GridBagLayout());
URL compassUrl = new URL(COMPASS_URL);
BufferedImage compassImage = ImageIO.read(compassUrl);
ImageIcon compassIcon = new ImageIcon(compassImage);
some_icon.setIcon(compassIcon);
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;
add(some_icon, c);
c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 1;
add(some_text, c);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
g2.setColor(Color.RED);
g2.setStroke(new BasicStroke(15));
g2.drawLine(0, 0, this.getWidth(), this.getHeight());
g2.drawLine(this.getWidth(), 0, 0, this.getHeight());
g2.dispose();
}
private static void createAndShowUI() throws IOException {
JFrame frame = new JFrame("MyFrame");
frame.getContentPane().add(new Stack());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
try {
createAndShowUI();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
Is there a way to bring my X to the foreground or to wait for super.paintComponent(g) to paint everything, and then run the code that draws the X?
Thanks,
Roberto
Override the paint(…) method of your JPanel:
protected void paint(Graphics g)
{
super.paint(g);
// add custom painting code here
}
The paint(…) method invokes the paintChildren(…) method so your custom code will be executed after all the components on the panel are painted.
See A Closer Look at the Painting Mechanism for more information.
Try this. I made the following changes.
Drew the image in paintComponent as opposed to setIcon.
positioned the image to center it.
used setPreferredSize for real panel size (setting frame size includes borders which is probably not what you wanted).
used RenderingHints in paintComponent to smooth out edges of cross.
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Stack2 extends JPanel {
private final JLabel some_text = new JLabel(
"Some very long text that will be covered", JLabel.LEFT);
private final JLabel some_icon =
new JLabel((Icon) null, JLabel.CENTER);
public static final String COMPASS_URL =
"https://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/Compass_Rose_English_North.svg/240px-Compass_Rose_English_North.svg.png";
BufferedImage compassImage;
public Stack2() throws IOException {
super(new GridBagLayout());
URL compassUrl = new URL(COMPASS_URL);
compassImage = ImageIO.read(compassUrl);
// ImageIcon compassIcon = new ImageIcon(compassImage);
// some_icon.setIcon(compassIcon);
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;
add(some_icon, c);
c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 1;
add(some_text, c);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.drawImage(compassImage,
(400 - compassImage.getWidth()) / 2,
(400 - compassImage.getHeight()) / 2, null);
g2.setColor(Color.RED);
g2.setStroke(new BasicStroke(15));
g2.drawLine(0, 0, this.getWidth(), this.getHeight());
g2.drawLine(this.getWidth(), 0, 0, this.getHeight());
g2.dispose();
}
private static void createAndShowUI() throws IOException {
JFrame frame = new JFrame("MyFrame");
Stack2 panel = new Stack2();
frame.getContentPane().add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(new Dimension(400, 400));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
try {
createAndShowUI();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}

Backup for image that is drawn on in Java

In my application, there are things marked on an image by clicking on the image. That is done by setting the image as an Icon to a JLabel and adding a MousePressed method
I want to add a feature for the users to redo the last step now and need a backupimage for that.
The following is a code example:
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.Color;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class BuffImgTest {
private BufferedImage buffimg, scaledimg, backupscaledimg;
private Image img;
private JFrame frame;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
BuffImgTest window = new BuffImgTest();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public BuffImgTest() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
final JLabel label = new JLabel("");
label.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent arg0) {
Graphics graphics = scaledimg.getGraphics();
graphics.setColor(Color.RED);
graphics.drawString("Test", arg0.getX(), arg0.getY());
Image img = Toolkit.getDefaultToolkit().createImage(
scaledimg.getSource());
label.setIcon(new ImageIcon(img));
}
});
label.setBounds(10, 34, 414, 201);
try {
buffimg = ImageIO.read(new File("test.jpg"));
scaledimg = getScaledImage(buffimg, label.getWidth(),
label.getHeight());
backupscaledimg = scaledimg;
// backupscaledimg=getScaledImage(buffimg,label.getWidth(),label.getHeight());
Image img = Toolkit.getDefaultToolkit().createImage(
scaledimg.getSource());
label.setIcon(new ImageIcon(img));
} catch (Exception e) {
System.out.println(e);
}
frame.getContentPane().add(label);
JButton btnNewButton = new JButton("Restart Step");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
scaledimg = backupscaledimg;
Image img = Toolkit.getDefaultToolkit().createImage(
scaledimg.getSource());
label.setIcon(new ImageIcon(img));
}
});
btnNewButton.setBounds(111, 238, 89, 23);
frame.getContentPane().add(btnNewButton);
}
public static BufferedImage getScaledImage(BufferedImage image, int width,
int height) throws IOException {
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
double scaleX = (double) width / imageWidth;
double scaleY = (double) height / imageHeight;
AffineTransform scaleTransform = AffineTransform.getScaleInstance(
scaleX, scaleY);
AffineTransformOp bilinearScaleOp = new AffineTransformOp(
scaleTransform, AffineTransformOp.TYPE_BILINEAR);
return bilinearScaleOp.filter(image, new BufferedImage(width, height,
image.getType()));
}
}
It is not working as intended.
If I use the commented line backupscaledimg = getScaledImage(buffimg,label.getWidth(),label.getHeight()); instead of backupscaledimg = scaledimg;, it is working as expected.
The problem is that I want to do several steps of drawing things on the image, and it can only be redone the first time like that. From what I know the problem might be, that the command backupscaledimg = scaledimg is only creating a pointer for backupscaledimg pointing to scaledimg which results in both of them altering.
I don't want to save a new imagefile on each step though.
Is there any way around this? (found the scaling function on here by the way thanks for that anonymous)
Made some changes
Using GridBagLayout
Able to reset back to original image by pressing "Restart Step"
Able to undo last action with the use of an image stack (i.e. a Stack of BufferedImage)
Example code:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Stack;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import java.awt.Color;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class BuffImgTest {
private BufferedImage scaledImg, originalScaledImg;
private JFrame frame;
private Stack<BufferedImage> imageStack = new Stack<>();
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
BuffImgTest window = new BuffImgTest();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public BuffImgTest() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout());
JPanel panel = new JPanel(new GridBagLayout());
final JLabel imgLabel = new JLabel("");
imgLabel.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent arg0) {
// Add current image to the image stack
imageStack.add(copyImage(scaledImg));
// Change the image
Graphics graphics = scaledImg.getGraphics();
graphics.setColor(Color.BLACK);
graphics.setFont(new Font("Arial", Font.BOLD, 32));
graphics.drawString("TEST", arg0.getX(), arg0.getY());
// Update label
Image img = Toolkit.getDefaultToolkit().createImage(
scaledImg.getSource());
imgLabel.setIcon(new ImageIcon(img));
}
});
imgLabel.setSize(500, 500);
imgLabel.setPreferredSize(new Dimension(500, 500));
try {
BufferedImage buffImg = ImageIO.read(new File("test.jpg"));
scaledImg = getScaledImage(buffImg, imgLabel.getWidth(),
imgLabel.getHeight());
// Clone it first
originalScaledImg = copyImage(scaledImg);
Image img = Toolkit.getDefaultToolkit().createImage(
scaledImg.getSource());
imgLabel.setIcon(new ImageIcon(img));
} catch (Exception e) {
System.out.println(e);
}
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.insets = new Insets(20, 10, 10, 10);
panel.add(imgLabel, c);
JButton restartBtn = new JButton("Restart Step");
restartBtn.setFont(new Font("Arial", Font.ITALIC, 20));
restartBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
// Clear the image stack
imageStack.clear();
// Reset the image
scaledImg = copyImage(originalScaledImg);
Image img = Toolkit.getDefaultToolkit().createImage(
scaledImg.getSource());
imgLabel.setIcon(new ImageIcon(img));
}
});
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 1;
c.anchor = GridBagConstraints.CENTER;
c.insets = new Insets(10, 10, 5, 10);
panel.add(restartBtn, c);
JButton undoBtn = new JButton("Undo Last");
undoBtn.setFont(new Font("Arial", Font.ITALIC, 20));
undoBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if(imageStack.isEmpty()) {
JOptionPane.showMessageDialog(frame, "Cannot undo anymore!");
return;
}
// Get the previous image
scaledImg = copyImage(imageStack.pop());
Image img = Toolkit.getDefaultToolkit().createImage(
scaledImg.getSource());
imgLabel.setIcon(new ImageIcon(img));
}
});
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 2;
c.anchor = GridBagConstraints.CENTER;
c.insets = new Insets(5, 10, 20, 10);
panel.add(undoBtn, c);
frame.getContentPane().add(panel, BorderLayout.CENTER);
frame.setSize(800, 800);
}
/** For copying image */
public static BufferedImage copyImage(BufferedImage source){
BufferedImage b = new BufferedImage(
source.getWidth(), source.getHeight(), source.getType());
Graphics g = b.getGraphics();
g.drawImage(source, 0, 0, null);
g.dispose();
return b;
}
public static BufferedImage getScaledImage(BufferedImage image, int width,
int height) throws IOException {
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
double scaleX = (double) width / imageWidth;
double scaleY = (double) height / imageHeight;
AffineTransform scaleTransform = AffineTransform.getScaleInstance(
scaleX, scaleY);
AffineTransformOp bilinearScaleOp = new AffineTransformOp(
scaleTransform, AffineTransformOp.TYPE_BILINEAR);
return bilinearScaleOp.filter(image, new BufferedImage(width, height,
image.getType()));
}
}
Edited Image:
Image after pressing "Restart step":
Pressing "Undo Last" when image stack is empty:
Note:
Code for copying image is from this answer by APerson

why can't I draw any stuffs on Frame in java?

Coding is here.
I can't create any rectangle or circle inside frame.
the object of this project is to create converting celcius 2 Farenheit & Farenheit 2 Celcius.
so what I want is, please teach me to how to draw rectangle or oval in side the frame.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class C2F extends JComponent{
private double input1, output1;
private double input2, output2;
JPanel center = new JPanel();
JPanel top = new JPanel();
JPanel east = new JPanel();
JPanel south = new JPanel();
//for giving input & output
C2F(){
JFrame frame = new JFrame();
frame.setTitle("C2F");
frame.setSize(700,500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.getContentPane().add(top,BorderLayout.NORTH);
frame.getContentPane().add(center,BorderLayout.CENTER);
frame.getContentPane().add(south,BorderLayout.SOUTH);
frame.getContentPane().add(east,BorderLayout.EAST);
frame.setVisible(true);
CC2F();
}
public void CC2F(){
//making frame
//give specific location
JLabel L1 = new JLabel("Please input Celcius or Fahrenheit to Convert");
top.add(L1);
JLabel l1 = new JLabel("Cel -> Fah");
south.add(l1);
JTextField T1 = new JTextField(12);
south.add(T1);
JButton B1 = new JButton("Convert");
south.add(B1);
JLabel l2 = new JLabel("Fah -> Cel");
south.add(l2);
JTextField T2 = new JTextField(12);
south.add(T2);
JButton B2 = new JButton("Convert");
south.add(B2);
//to create buttons and labels to give an answer
B1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
input1 = Double.parseDouble(T1.getText());
output1 = input1 *(9/5) + 32;
T2.setText(""+output1);
repaint();
}
});
B2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
input2 = Double.parseDouble(T2.getText());
output2 = (input2 - 32)/9*5;
T1.setText(""+output2);
}
});
//making events
//placing the buttons and labels
output1 = 0;
output2 = 0;
//initialize the value
}
public void paintComponent(Graphics g) {
//error spots. it compiles well. But this is not what I want.
super.paintComponent(g);
Graphics2D gg = (Graphics2D) g;
gg.setColor(Color.BLACK);
gg.drawOval(350, 500,12,12);
gg.setColor(Color.RED);
gg.fillRect(350, 500, 10,(int) output1);
gg.fillOval(350, 500, 10, 10);
gg.setColor(Color.RED);
gg.fillRect(350, 500, 10,(int) output2);
gg.fillOval(350, 500, 10, 10);
//to draw stuffs
}
public static void main(String[] args)
{//to run the program
new C2F();
}
}
You never actually add C2F to anything that would be able to paint it, therefore your paint method will never be called.
You should override paintComponent instead of paint, as you've broken the paint chain for the component which could cause no end of issues with wonderful and interesting paint glitches. Convention would also suggest that you should call super.paintComponent (when overriding paintComponent) as well before you perform any custom painting
See Painting in AWT and Swing and Performing Custom Painting for more details
As a general piece of advice, I'd discourage you from creating a frame within the constructor of another component, this will make the component pretty much unusable again (if you wanted to re-use it on another container for example)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class C2F extends JComponent {
public C2F() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
TestPane center = new TestPane();
JPanel top = new JPanel();
JPanel east = new JPanel();
JPanel south = new JPanel();
//give specific location
JLabel L1 = new JLabel("Please input Celcius or Fahrenheit to Convert");
top.add(L1);
JLabel l1 = new JLabel("Cel -> Fah");
south.add(l1);
JTextField T1 = new JTextField(12);
south.add(T1);
JButton B1 = new JButton("Convert");
south.add(B1);
JLabel l2 = new JLabel("Fah -> Cel");
south.add(l2);
JTextField T2 = new JTextField(12);
south.add(T2);
JButton B2 = new JButton("Convert");
south.add(B2);
//to create buttons and labels to give an answer
B1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
double input1 = Double.parseDouble(T1.getText());
double output1 = input1 * (9 / 5) + 32;
T2.setText("" + output1);
center.setOutput1(output1);
}
});
B2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
double input2 = Double.parseDouble(T2.getText());
double output2 = (input2 - 32) / 9 * 5;
T1.setText("" + output2);
center.setOutput2(output2);
}
});
//making events
frame.getContentPane().add(top, BorderLayout.NORTH);
frame.getContentPane().add(center, BorderLayout.CENTER);
frame.getContentPane().add(south, BorderLayout.SOUTH);
frame.getContentPane().add(east, BorderLayout.EAST);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private double output1, output2;
public TestPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 600);
}
public void setOutput1(double output1) {
this.output1 = output1;
repaint();
}
public void setOutput2(double output2) {
this.output2 = output2;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLACK);
g2d.drawOval(350, 500, 12, 12);
g2d.setColor(Color.RED);
g2d.fillRect(350, 0, 10, (int) output1);
g2d.fillOval(350, 0, 10, 10);
g2d.setColor(Color.BLUE);
g2d.fillRect(350, 0, 10, (int) output2);
g2d.fillOval(350, 0, 10, 10);
g2d.dispose();
}
}
public static void main(String[] args) {//to run the program
new C2F();
}
}

How do I get consistent rendering when scaling a JTextPane? [duplicate]

I submitted another version of this question and a sample program before: How do I get consistent rendering when scaling a JTextPane?
Recapitulating the problem: I would like to allow users to zoom into or out of a non-editable JTextPane. Running the example program submitted in the earlier question, which simply scaled the Graphics object, resulted in inconsistent spacing between runs of bold text and non-bold text.
The sample program below attempts to solve the problem by drawing the text pane to a BufferedImage at 100% and then scaling the image. This solves the problem of inconsistent spacing but the resulting text lacks crispness. Is there some combination of rendering hints (or some other change) that will result in nice crisp text?
Thanks in advance for any suggestions or comments on the feasibility of this approach.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.Box;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
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 ScaledJTextPane extends JTextPane
{
double scale_;
BufferedImage raster_;
public ScaledJTextPane()
{
scale_ = 1.0;
raster_ = null;
}
public void draw(Graphics g)
{
if (raster_ == null)
{
// Draw this text pane to a BufferedImage at 100%
raster_ = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = raster_.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
paint(g2);
}
Graphics2D g2 = (Graphics2D) g;
// Experiment with different rendering hints
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
// Scale the BufferedImage
g2.scale(scale_, scale_);
g2.drawImage(raster_, 0, 0, null);
}
public void setScale(double scale)
{
scale_ = scale;
raster_ = null;
}
private static void createAndShowGUI()
{
// Create and set up the window.
JFrame frame = new JFrame("ScaledJTextPane using BufferedImage");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final ScaledJTextPane scaledTextPane = new ScaledJTextPane();
StyledDocument doc = scaledTextPane.getStyledDocument();
Style defaultStyle = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
Style boldStyle = doc.addStyle("bold", defaultStyle);
StyleConstants.setBold(boldStyle, true);
scaledTextPane.setFont(new Font("Dialog", Font.PLAIN, 14));
String boldText = "Four score and seven years ago ";
String plainText = "our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.";
try
{
doc.insertString(doc.getLength(), boldText, boldStyle);
doc.insertString(doc.getLength(), plainText, defaultStyle);
}
catch (BadLocationException ble)
{
System.err.println("Couldn't insert text into text pane.");
}
final JComboBox zoomCombo=new JComboBox(new String[] {"75%",
"100%", "150%", "175%", "200%"});
final JPanel panel = new JPanel()
{
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
scaledTextPane.draw(g);
}
};
zoomCombo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String s = (String) zoomCombo.getSelectedItem();
s = s.substring(0, s.length() - 1);
double scale = new Double(s).doubleValue() / 100;
scaledTextPane.setScale(scale);
panel.invalidate();
panel.repaint();
}
});
zoomCombo.setSelectedItem("100%");
JPanel optionsPanel = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.anchor = GridBagConstraints.WEST;
optionsPanel.add(zoomCombo, c);
c.gridx++;
c.weightx = 1;
c.fill = GridBagConstraints.HORIZONTAL;
optionsPanel.add(Box.createHorizontalGlue(), c);
// Add content to the window.
scaledTextPane.setBounds(0, 0, 450, 300);
panel.setOpaque(true);
panel.setBackground(Color.WHITE);
frame.getContentPane().add(panel, BorderLayout.CENTER);
frame.getContentPane().add(optionsPanel, BorderLayout.NORTH);
frame.setSize(900, 300);
//Display the window.
frame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
may be this http://java-sl.com/Scale_In_JEditorPane.html could help.
Sadly, scaling to a larger size from a fixed resolution will always result in some aliasing artifact. Here's an alternative approach that scales the font used by JTextPane.
For low-level control, consider TextLayout, which includes a FontRenderContext that can manage the anti-aliasing and fractional metrics settings, as seen in this example.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
/** #see https://stackoverflow.com/questions/4566211 */
public class ScaledJTextPane {
private static final int SIZE = 14;
private static final String FONT = "Dialog";
private static void createAndShowGUI() {
JFrame frame = new JFrame("ScaledJTextPane using BufferedImage");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JTextPane tp = new JTextPane();
tp.setFont(new Font(FONT, Font.PLAIN, SIZE));
tp.setPreferredSize(new Dimension(400, 300));
StyledDocument doc = tp.getStyledDocument();
Style defaultStyle = StyleContext.getDefaultStyleContext()
.getStyle(StyleContext.DEFAULT_STYLE);
Style boldStyle = doc.addStyle("bold", defaultStyle);
StyleConstants.setBold(boldStyle, true);
String boldText = "Four score and seven years ago ";
String plainText = "our fathers brought forth on this continent, "
+ "a new nation, conceived in Liberty, and dedicated to the "
+ "proposition that all men are created equal.";
try {
doc.insertString(doc.getLength(), boldText, boldStyle);
doc.insertString(doc.getLength(), plainText, defaultStyle);
} catch (BadLocationException ble) {
ble.printStackTrace(System.err);
}
final JPanel panel = new JPanel();
panel.add(tp);
final JComboBox zoomCombo = new JComboBox(new String[]{
"75%", "100%", "150%", "175%", "200%"});
zoomCombo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String s = (String) zoomCombo.getSelectedItem();
s = s.substring(0, s.length() - 1);
double scale = new Double(s).doubleValue() / 100;
int size = (int) (SIZE * scale);
tp.setFont(new Font(FONT, Font.PLAIN, size));
}
});
zoomCombo.setSelectedItem("100%");
JPanel optionsPanel = new JPanel();
optionsPanel.add(zoomCombo);
panel.setBackground(Color.WHITE);
frame.add(panel, BorderLayout.CENTER);
frame.add(optionsPanel, BorderLayout.NORTH);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
}
I would like to allow users to zoom into or out of a non-editable JTextPane.
Since the text pane is non-editable, maybe you can create an image of the text pane by using the Screen Image class. Then you can draw the image on a panel using the approriate scaling factor.

Categories