Just to preface, I've looked for several hours trying to find a solution to this on here and several other sites. If you find a question I may have missed, please let me know.
Anywho, I'm trying to create a thumbnail viewer that displays 4 thumbnails (in jpanels) and 4 captions. I can draw out all 4 thumbnails, but they're all the same image (duplicates of the last one painted). I think it's part of how I'm trying to repaint them, but I can't figure out what to change. The imageAlbum is an ArrayList of jpg paths.
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
//import MainFrame.ImageComponent;
import javax.swing.JLabel;
public class Thumbnails extends JFrame {
final int IMG_WIDTH = 80;
final int IMG_HEIGHT = 60;
private BufferedImage image;
private ImageAlbum imageAlbum;
private JPanel contentPane;
private JPanel thmbnl_1;
private JPanel thmbnl_2;
private JPanel thmbnl_3;
private JPanel thmbnl_4;
private JLabel thmbnl_1Label;
private JLabel thmbnl_2Label;
private JLabel thmbnl_3Label;
private JLabel thmbnl_4Label;
/**
* Create the frame.
*/
public Thumbnails(ImageAlbum album) {
imageAlbum = album;
String captionUnavailable = "Caption is not available";
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JPanel panel = new JPanel();
contentPane.add(panel, BorderLayout.CENTER);
panel.setLayout(new GridLayout(4, 2, 0, 0));
thmbnl_1 = new JPanel();
thmbnl_1.setPreferredSize(new Dimension(80, 60));
panel.add(thmbnl_1);
thmbnl_2 = new JPanel();
thmbnl_2.setPreferredSize(new Dimension(80, 60));
panel.add(thmbnl_2);
thmbnl_1Label = new JLabel(captionUnavailable);
panel.add(thmbnl_1Label);
thmbnl_2Label = new JLabel(captionUnavailable);
panel.add(thmbnl_2Label);
thmbnl_3 = new JPanel();
thmbnl_3.setPreferredSize(new Dimension(IMG_WIDTH, IMG_HEIGHT));
panel.add(thmbnl_3);
thmbnl_4 = new JPanel();
thmbnl_4.setPreferredSize(new Dimension(IMG_WIDTH, IMG_HEIGHT));
panel.add(thmbnl_4);
thmbnl_3Label = new JLabel(captionUnavailable);
panel.add(thmbnl_3Label);
thmbnl_4Label = new JLabel(captionUnavailable);
panel.add(thmbnl_4Label);
setupThumbnails();
}// end Thumbnails(ImageAlbum album)
//
private void setupThumbnails() {
int albumSize = imageAlbum.getSize();
for(int i = 0; i < albumSize; i++) {
try {
image = resizeToThumbnail(ImageIO.read(new File(imageAlbum.getAlbum(i))));
switch(i) {
case 0:
thmbnl_1.setLayout(new BorderLayout());
thmbnl_1.add(new ImageComponent(image), BorderLayout.CENTER);
thmbnl_1Label.setText(imageAlbum.getCaption(i));
break;
case 1:
thmbnl_2.setLayout(new BorderLayout());
thmbnl_2.add(new ImageComponent(image), BorderLayout.CENTER);
thmbnl_2Label.setText(imageAlbum.getCaption(i));
break;
case 2:
thmbnl_3.setLayout(new BorderLayout());
thmbnl_3.add(new ImageComponent(image), BorderLayout.CENTER);
thmbnl_3Label.setText(imageAlbum.getCaption(i));
break;
case 3:
thmbnl_4.setLayout(new BorderLayout());
thmbnl_4.add(new ImageComponent(image), BorderLayout.CENTER);
thmbnl_4Label.setText(imageAlbum.getCaption(i));
break;
default:
break;
}// end switch-case
revalidate();
repaint();
}// end try-block
catch(IOException e) {
e.printStackTrace();
}// end catch-block
}// end for-loop
}// end setupCaptions()
//
public BufferedImage resizeToThumbnail(BufferedImage original) {
int type;
BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, original.getType());
Graphics2D g = resizedImage.createGraphics();
g.drawImage(original, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
g.dispose();
g.setComposite(AlphaComposite.Src);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
return resizedImage;
}// end resizeToThumbnail(...)
class ImageComponent extends JComponent {
/**
* Desc: constructor for ImageComponent
* #param: BufferedImage img
* #return: nothing
*/
public ImageComponent(BufferedImage img) {
image = img;
}// end ImageComponent()
/**
* Desc: draws out the image to the panel
* #param: Graphics g
* #return: void
*/
#Override
public void paintComponent(Graphics g) {
if(image == null)
return;
Graphics2D g2d = (Graphics2D) g;
// draw the image
g.drawImage(image, 0, 0, this);
g.dispose();
}// end paintComponents(Graphics g)
}// end class ImageComponent
}// end class class Thumbnails
EDIT
ImageAlbum class:
import java.util.*;
public class ImageAlbum {
private ArrayList imageAlbum;
private ArrayList imageCaptions;
private int size;
/**
* Desc: getter for album size
* #param: none
* #return: int
*/
public int getSize() {
return size;
}// end getSize()
/**
* Desc: getter for the image
* #param: int index
* #return: String
*/
public String getAlbum(int index) {
return imageAlbum.get(index).toString();
}// end getAlbum(int index)
/**
* Desc: getter for the image caption
* #param: int index
* #return: String
*/
public String getCaption(int index) {
return imageCaptions.get(index).toString();
}// end getCaption(int index)
/**
* Desc: default constructor for ImageAlbum
* #param: none
* #return: nothing
*/
public ImageAlbum() {
imageAlbum = new ArrayList();
imageCaptions = new ArrayList();
size = 0;
}// end ImageAlbum()
/**
* Desc: parameterized constructor for ImageAlbum
* #param: none
* #return: nothing
*/
public ImageAlbum(ArrayList tempImageAlbum, ArrayList tempImageCaptions) {
imageAlbum = tempImageAlbum;
imageCaptions = tempImageCaptions;
}// end ImageAlbum(...)
/**
* Desc: adds the image directory and caption to both array lists
* #param: String imageDirectory, String imageCaption
* #return: void
*/
public void add(String imageDirectory, String imageCaption) {
imageAlbum.add(imageDirectory);
imageCaptions.add(imageCaption);
size++;
}// end add(...)
/**
* Desc: clears imageAlbum and imageCaptions array lists
* #param: nothing
* #return: void
*/
public void clear() {
imageAlbum.clear();
imageCaptions.clear();
size = 0;
}// end clear()
}// end class ImageAlbum
FINAL EDIT
I'm obviously not understanding very well, so I've decided to take a different approach - I'm using JLabels and doing icons instead. Works great, thanks everyone for your help
Your panel is set for a BorderLayout, and you call panel.add() for each of your thumbnails. That method sets the given component into the middle of the BorderLayout, replacing whatever is there, so that's why you're just seeing the last one added. BorderLayout does not do what you want for the thumbnails.
I would expect you want GridLayout; it lays out components added to it in rows and columns. Set your panel to GridLayout (or whatever else you want to layout the thumbnails), and add the thumbnails to it. Then put panel wherever you want; by default, a JFrame has a Borderlayout on it, you probably want to put panel in the middle of that.
Related
I am trying to make a simple Java program with GUI using Java Swing.
I have painting panel (gPanel) in the center of the screen, panel with buttons (buttonSet) in the west and panel with labels (labelPanel) in the east. To paint over gPanel I use paintComponent method and since I have two buttons, which are supposed to draw different things (and change label on the right of the screen), I decided to put switch case in paintComponent method for it to choose the correct actual painting method.
When I run the program everything looks fine - program uses the first method to paint and there is a sampletext.png image shown in the middle of the screen with yellow background, as it should be. Button number 1 also uses this method to draw over gPanel, so pressing it draws the same thing.
Now Button number 2 uses the second painting method and this is where things go wrong. It draws sampleimage.png over the gPanel, but also parts of left and right panels (i.e. buttons from left buttonSet panel and orange colour that is background colour of side panels) are drawn, though it shouldn't happen. Also the whole gPanel becomes gray (I think it happens because of label on the right that becomes very long after pressing Button number 2, because when the label was shorter gPanel didn't turn gray and left the previously drawn things instead).
Pressing Button number 1 paints things from first method properly, so pressing it after pressing Button number 2 "reverts" the changes.
What do I have to do to make my second painting method work properly?
Also why adding border to buttonSet and labelPanel works but adding it to gPanel doesn't?
package com.inferjus.drawingproject;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.border.*;
/**
*
* #author inferjus
*/
public class DrawingProject
{
private JFrame frame;
private graphicPanel gPanel;
private JPanel buttonSet;
private JPanel labelPanel;
private JLabel label;
private int painter=0;
public static void main(String[] args)
{
DrawingProject program=new DrawingProject();
program.prepareGUI();
}
public int getPainter()
{
return painter;
}
public void setPainter(int x)
{
painter=x;
}
public void prepareGUI()
{
//setting JFrame and icon
frame=new JFrame("Drawing Project");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
try { frame.setIconImage(ImageIO.read(getClass().getResource("/resources/sampleicon.png")));}
catch (IOException e) { e.printStackTrace(); }
//border for components
Border bigBlackBorder=new LineBorder(Color.black, 3);
//setting JPanel (graphicPanel) for drawing images
gPanel=new graphicPanel();
gPanel.setBorder(bigBlackBorder); // <--- why it does not work?
//setting JPanel for buttons on the left of the screen
buttonSet=new JPanel();
buttonSet.setLayout(new BoxLayout(buttonSet, BoxLayout.Y_AXIS));
buttonSet.setBorder(bigBlackBorder);
//setting JButtons
JButton buttonOne=new JButton("Button number 1");
buttonOne.addActionListener(new buttonOneListener());
buttonSet.add(buttonOne);
buttonSet.setBackground(Color.orange);
JButton buttonTwo=new JButton("Button number 2");
buttonTwo.addActionListener(new buttonTwoListener());
buttonSet.add(buttonTwo);
//setting JLabels on the right of the screen
label=new JLabel("Default label");
label.setFont(new Font("Consolas", Font.PLAIN, 20));
labelPanel=new JPanel();
labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.Y_AXIS));
labelPanel.setBackground(Color.orange);
labelPanel.setBorder(bigBlackBorder);
JLabel popeLabelTitle=new JLabel("What does the label say?");
popeLabelTitle.setFont(new Font("Consolas", Font.BOLD, 24));
//adding JLabels to labelPanel
labelPanel.add(BorderLayout.NORTH, popeLabelTitle);
labelPanel.add(BorderLayout.CENTER, label);
//adding components to JFrame
frame.getContentPane().add(BorderLayout.CENTER, gPanel);
frame.getContentPane().add(BorderLayout.EAST, labelPanel);
frame.getContentPane().add(BorderLayout.WEST, buttonSet);
frame.setVisible(true);
}
class graphicPanel extends JPanel
{
private BufferedImage sampletext=null;
private BufferedImage sampleimage=null;
#Override
public void paintComponent(Graphics g)
{
//for Button One paint sampletext.png, for Button Two paint sampleimage.png
switch (painter)
{
case 0:
paintSampletext(g);
break;
case 1:
paintSampleimage(g);
break;
}
}
//paint yellow background and put sampletext.png in the middle
private void paintSampletext(Graphics g)
{
if (sampletext==null)
{
gPanel.setSampletextPNG();
}
g.setColor(Color.yellow);
g.fillRect(0,0, gPanel.getWidth(), gPanel.getHeight());
g.drawImage(sampletext, gPanel.getWidth()/2-sampletext.getWidth()/2, gPanel.getHeight()/2-sampletext.getHeight()/2, this);
g.setColor(Color.black);
g.drawRect(gPanel.getWidth()/2-sampletext.getWidth()/2, gPanel.getHeight()/2-sampletext.getHeight()/2, sampletext.getWidth(), sampletext.getHeight());
g.dispose();
}
//paint sampleimage.png over what is already displayed
private void paintSampleimage(Graphics g)
{
if (sampleimage==null)
{
gPanel.setSampleimagePNG();
}
int x=(int)((Math.random()*gPanel.getWidth())-sampleimage.getWidth());
int y=(int)((Math.random()*gPanel.getHeight())-sampleimage.getHeight());
g.drawImage(sampleimage, x, y, gPanel);
g.dispose();
}
public void setSampletextPNG()
{
try { sampletext=ImageIO.read(getClass().getResource("/resources/sampletext.png")); }
catch (IOException ex) { System.out.println("Image error"); }
}
public void setSampleimagePNG()
{
try { sampleimage=ImageIO.read(getClass().getResource("/resources/sampleimage.png")); }
catch (IOException ex) { System.out.println("Image error"); }
}
}
class buttonOneListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
label.setText("Reaction to button number 1: change of label.");
setPainter(0);
gPanel.repaint();
}
}
class buttonTwoListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
label.setText("Reaction to button number 2: change of label + drawing images over gPanel.");
setPainter(1);
gPanel.repaint();
}
}
}
Tree of my project:
DrawingProject
-JRE System Library
-src
--com.inferjus.drawingproject
---DrawingProject.java
--resources
---sampleicon.png
---sampleimage.png
---sampletext.png
what shows after running the program by default or after pressing Button One
what shows after pressing Button Two one time
what shows after pressing Button Two a few times
Introduction
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section.
I went ahead and created the following GUI. I created two BufferedImages for the text image and the plain image so I wouldn't have to read any external files.
Explanation
When I create a Swing GUI, I use the model-view-controller pattern. This pattern allows me to separate my concerns and focus on one part of the application at a time.
Model
I created a model class to hold the button flag and the two BufferedImages. This is the class where you would read the resources.
You can add the JFrame icon back to this class.
Model classes are plain Java getter/setter classes.
View
All Swing applications must start with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.
Class names are written in camel case and start with an upper case character. Method names are written in camel case and start with a lower case character. Field names follow the same rules as method names.
I separated the creation of the JFrame from the creation of the JPanels. This helps me to separate my concerns and makes it much easier to visually verify whether or not the code is correct. Aim to write short methods that do one thing and do it well.
You have to manually draw a border on a graphic JPanel. I added the code to your paintComponent method to paint a partial border.
Your paintComponent method should paint. Period. Nothing else. It must also start with a call to the super.paintComponent method to maintain the Swing paint chain.
I changed your JLabel in the right JPanel to a JTextArea. A JTextArea allows for longer messages to word wrap on multiple lines and not make your JFrame change size.
Controller
Your JButton controller classes were fine, except for the class names.
Code
Here's the complete runnable code. I made all the additional classes inner classes so I could post the code in one block.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class DrawingProject implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new DrawingProject());
}
private final DrawingModel model;
private GraphicPanel graphicPanel;
private JTextArea textArea;
public DrawingProject() {
this.model = new DrawingModel();
}
#Override
public void run() {
JFrame frame = new JFrame("Drawing Project");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
graphicPanel = new GraphicPanel(model);
frame.add(createButtonPanel(), BorderLayout.WEST);
frame.add(graphicPanel, BorderLayout.CENTER);
frame.add(createTextPanel(), BorderLayout.EAST);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBackground(Color.orange);
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
JButton buttonOne = new JButton("Button number 1");
buttonOne.addActionListener(new ButtonOneListener());
panel.add(buttonOne);
JButton buttonTwo = new JButton("Button number 2");
buttonTwo.addActionListener(new ButtonTwoListener());
panel.add(buttonTwo);
return panel;
}
private JPanel createTextPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
JLabel popeLabelTitle = new JLabel("What does the label say?");
popeLabelTitle.setFont(new Font(Font.MONOSPACED, Font.BOLD, 24));
panel.add(popeLabelTitle, BorderLayout.NORTH);
textArea = new JTextArea(4, 30);
textArea.setEditable(false);
textArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 20));
textArea.setText("Default label");
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
panel.add(textArea, BorderLayout.CENTER);
return panel;
}
public class GraphicPanel extends JPanel {
private static final long serialVersionUID = 1L;
private final DrawingModel model;
public GraphicPanel(DrawingModel model) {
this.model = model;
this.setPreferredSize(new Dimension(640, 480));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// Paint border
int width = getWidth();
int height = getHeight();
int lineThickness = 3;
g.setColor(Color.BLACK);
g.fillRect(0, 0, width, height);
g.setColor(Color.YELLOW);
g.fillRect(0, lineThickness, width, height - 2 * lineThickness);
switch (model.getPainter()) {
case 0:
paintSampleText(g);
break;
case 1:
paintSampleImage(g);
break;
}
}
private void paintSampleText(Graphics g) {
BufferedImage image = model.getSampleText();
int x = (getWidth() - image.getWidth()) / 2;
int y = (getHeight() - image.getHeight()) / 2;
g.drawImage(image, x, y, this);
}
private void paintSampleImage(Graphics g) {
BufferedImage image = model.getSampleImage();
int x = (int) ((Math.random() * getWidth()) - image.getWidth());
int y = (int) ((Math.random() * getHeight()) - image.getHeight());
g.drawImage(image, x, y, this);
}
}
public class ButtonOneListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
textArea.setText("Reaction to button number 1: change of label.");
model.setPainter(0);
graphicPanel.repaint();
}
}
public class ButtonTwoListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
textArea.setText("Reaction to button number 2: change of label + "
+ "drawing images over gPanel.");
model.setPainter(1);
graphicPanel.repaint();
}
}
public class DrawingModel {
private int painter;
private final BufferedImage sampleText;
private final BufferedImage sampleImage;
public DrawingModel() {
this.painter = 0;
this.sampleText = createBufferedImage(Color.BLUE);
this.sampleImage = createBufferedImage(Color.MAGENTA);
}
private BufferedImage createBufferedImage(Color color) {
BufferedImage image = new BufferedImage(64, 64,
BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.setColor(color);
g.fillRect(0, 0, image.getWidth(), image.getHeight());
g.dispose();
return image;
}
public int getPainter() {
return painter;
}
public void setPainter(int painter) {
this.painter = painter;
}
public BufferedImage getSampleText() {
return sampleText;
}
public BufferedImage getSampleImage() {
return sampleImage;
}
}
}
Update
In order to paint multiple images, you have to save the origin of the images in a List. I've modified the application model to hold a List of origin Point instances. I also corrected the code to create a random point.
Here's the GUI with multiple images.
Here's the modified code
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class DrawingProject implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new DrawingProject());
}
private final DrawingModel model;
private GraphicPanel graphicPanel;
private JTextArea textArea;
public DrawingProject() {
this.model = new DrawingModel();
}
#Override
public void run() {
JFrame frame = new JFrame("Drawing Project");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
graphicPanel = new GraphicPanel(model);
frame.add(createButtonPanel(), BorderLayout.WEST);
frame.add(graphicPanel, BorderLayout.CENTER);
frame.add(createTextPanel(), BorderLayout.EAST);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBackground(Color.orange);
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
JButton buttonOne = new JButton("Button number 1");
buttonOne.addActionListener(new ButtonOneListener());
panel.add(buttonOne);
JButton buttonTwo = new JButton("Button number 2");
buttonTwo.addActionListener(new ButtonTwoListener());
panel.add(buttonTwo);
return panel;
}
private JPanel createTextPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
JLabel popeLabelTitle = new JLabel("What does the label say?");
popeLabelTitle.setFont(new Font(Font.MONOSPACED, Font.BOLD, 24));
panel.add(popeLabelTitle, BorderLayout.NORTH);
textArea = new JTextArea(4, 30);
textArea.setEditable(false);
textArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 20));
textArea.setText("Default label");
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
panel.add(textArea, BorderLayout.CENTER);
return panel;
}
public class GraphicPanel extends JPanel {
private static final long serialVersionUID = 1L;
private final DrawingModel model;
public GraphicPanel(DrawingModel model) {
this.model = model;
this.setPreferredSize(new Dimension(640, 480));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
paintMyBorder(g);
if (model.getPainter() == 1) {
createSampleImage(g);
}
paintSampleText(g);
BufferedImage image = model.getSampleImage();
List<Point> origin = model.getImageOrigin();
for (Point point : origin) {
g.drawImage(image, point.x, point.y, this);
}
}
private void paintMyBorder(Graphics g) {
int width = getWidth();
int height = getHeight();
int lineThickness = 3;
g.setColor(Color.BLACK);
g.fillRect(0, 0, width, height);
g.setColor(Color.YELLOW);
g.fillRect(0, lineThickness, width, height - 2 * lineThickness);
}
private void paintSampleText(Graphics g) {
BufferedImage image = model.getSampleText();
int x = (getWidth() - image.getWidth()) / 2;
int y = (getHeight() - image.getHeight()) / 2;
g.drawImage(image, x, y, this);
}
private void createSampleImage(Graphics g) {
BufferedImage image = model.getSampleImage();
int x = (int) (Math.random() * (getWidth() - image.getWidth()));
int y = (int) (Math.random() * (getHeight() - image.getHeight()));
model.addNewImageOrigin(new Point(x, y));
}
}
public class ButtonOneListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
textArea.setText("Reaction to button number 1: change of label.");
model.setPainter(0);
graphicPanel.repaint();
}
}
public class ButtonTwoListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
textArea.setText("Reaction to button number 2: change of label + "
+ "drawing images over gPanel.");
model.setPainter(1);
graphicPanel.repaint();
}
}
public class DrawingModel {
private int painter;
private final BufferedImage sampleText;
private final BufferedImage sampleImage;
private final List<Point> imageOrigin;
public DrawingModel() {
this.painter = 0;
this.sampleText = createBufferedImage(Color.BLUE);
this.sampleImage = createBufferedImage(Color.MAGENTA);
this.imageOrigin = new ArrayList<>();
}
private BufferedImage createBufferedImage(Color color) {
BufferedImage image = new BufferedImage(64, 64,
BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.setColor(color);
g.fillRect(0, 0, image.getWidth(), image.getHeight());
g.dispose();
return image;
}
public void addNewImageOrigin(Point point) {
this.imageOrigin.add(point);
}
public int getPainter() {
return painter;
}
public void setPainter(int painter) {
this.painter = painter;
}
public BufferedImage getSampleText() {
return sampleText;
}
public BufferedImage getSampleImage() {
return sampleImage;
}
public List<Point> getImageOrigin() {
return imageOrigin;
}
}
}
I am trying to make a JComponent function as a gallery. It must able to display saved images on it which are going to be showed in a component living in a JScrollPane. I am also going to add the functionality to remove an image. I managed to display the image on the component. How should I approach this?
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
public class GalleryPanel extends JPanel
{
private static final long serialVersionUID = 1L;
private int currentImage;
private JLabel[] images;
private final int MAX_IMAGES = 12;
private JScrollPane scrollPane;
private JPanel imageGallery;
public void init()
{
setLayout(new BorderLayout());
images = new JLabel[MAX_IMAGES];
imageGallery = new JPanel();
imageGallery.setLayout(new GridLayout(12,1,10,10));
scrollPane = new JScrollPane();
scrollPane.setBackground(Color.RED);
scrollPane.add(imageGallery);
add(scrollPane, BorderLayout.CENTER);
setBackground(Color.GRAY);
}
public void addImageToGallery(File file)
{
if ( currentImage <= images.length - 1)
{
BufferedImage bufImage = null;
try
{
bufImage = ImageIO.read(file); //tries to load the image
}
catch (Exception e)
{
System.out.println("Unable to load file " + file.toString());
}
Image resizedImage = bufImage.getScaledInstance(bufImage.getWidth()/6, bufImage.getHeight()/6, Image.SCALE_SMOOTH);
ImageIcon icon = new ImageIcon(resizedImage);
images[currentImage] = new JLabel(icon, JLabel.CENTER);
scrollPane.add(images[currentImage]);
images[currentImage].setSize(120, 100);
scrollPane.add(images[currentImage]);
currentImage++;
//scrollPane.revalidate();
//scrollPane.repaint();
}
else
{
throw new ArrayIndexOutOfBoundsException("The gallery is full");
}
}
public final int getMaxImages()
{
return MAX_IMAGES;
}
public Dimension getPreferredSize()
{
return new Dimension(300, 700);
}
}
I created JImagePanel for my CBIR java application using JPanel, JList, JLabel and ListCellRenderer
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package javax.swing;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.util.Vector;
import javax.swing.border.LineBorder;
/**
*
* #author NiRRaNjAN RauT
*/
/**
* JImagePanel is used to display JList of BufferedImage
* This class is extended to JPanel
*/
public class JImagePanel extends JPanel {
/**
* JList is used to display display BufferedImage
*/
private JList imageList = null;
/**
* JScrollPane is used to add scroll bar to JList
*/
JScrollPane scroll_pane = null;
/**
* Vector<BufferedImage> is used to store the BufferedImages
*/
Vector<BufferedImage> listData = new Vector<BufferedImage>();
/**
* default constructor used to initialize JPanel
*/
public JImagePanel() {
this(null);
}
/**
* #param data
* This parameterized constructor is used to
* add the vector of BufferedImages to JList
*/
public JImagePanel(Vector<BufferedImage> data) {
setLayout(new BorderLayout());
if(data != null) {
listData = data;
}
imageList = new JList();
imageList.setFixedCellHeight(160);
imageList.setFixedCellWidth(160);
if(!listData.isEmpty()) {
imageList.setListData(listData);
}
imageList.setCellRenderer(new JCellRenderer());
imageList.setAutoscrolls(true);
imageList.setLayoutOrientation(JList.HORIZONTAL_WRAP);
imageList.setVisibleRowCount(-1);
scroll_pane = new JScrollPane(imageList);
this.add(scroll_pane, BorderLayout.CENTER);
this.setBorder(new LineBorder(Color.BLUE));
}
/**
* #param selection
* The parameter selection is used to set multi selection on or off
* When true, it allows to select multiple images in JList using
* Ctrl key.
*/
public void setMultiSelection(boolean selection) {
if(selection) {
imageList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
} else {
imageList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
}
public int[] getSelectedIndices() {
return imageList.getSelectedIndices();
}
public int getImageSize() {
return imageList.getModel().getSize();
}
/**
* #param image
* This is used to add BufferedImage to JList
* User can add new images to JList at runtime.
*/
public void addImageToList(BufferedImage image) {
listData.add(image);
imageList.setListData(listData);
}
/**
* The method is used to clear the old list data.
* It sets the list data to empty list.
*/
public void clear() {
listData.clear();
imageList.setListData(listData);
}
/**
* #param data
* This method is used to set list data to JList
* The data should be Vector of BufferedImage
*/
public void setListData(Vector<BufferedImage> data) {
if(data == null || data.isEmpty()) {
System.err.println("Empty Data");
return;
}
listData = data;
imageList.setListData(listData);
}
}
For this Panel ListCellRenderer component is required which is given below.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package javax.swing;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.border.EmptyBorder;
/**
*
* #author NiRRaNjAN RauT
*/
/**
* JCellRenderer is extended to JLabel
* It is used to display the image on JList by implementing ListCellRenderer
*/
public class JCellRenderer extends JLabel implements ListCellRenderer {
/**
* The width and height is used to set size of a JLabel.
* It is default set to 200 * 200
*/
private static final int width = 140, height = 140;
/**
* default constructor used to set size of JLabel and set Border to JLabel.
*/
public JCellRenderer() {
setSize(width, height);
setOpaque(true);
setBorder(new EmptyBorder(10, 10, 10, 10));
}
/**
* #return Component
* it returns JLabel for a cell.
* The image from JList is set as icon on JLabel so that it displays the image as a JList item.
*/
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
try {
if(value instanceof BufferedImage) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
g.drawImage((BufferedImage) value, 0, 0, width, height, null);
g.dispose();
setIcon(new ImageIcon(image));
}
if(isSelected) {
setBackground(Color.DARK_GRAY);
} else {
setBackground(Color.LIGHT_GRAY);
}
} catch(Exception ex) {
System.err.println("" + ex.getMessage());
}
return this;
}
}
and This is how to use it.
JFrame frame = new JFrame("Image Panel Demo");
frame.setResizable(true);
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JImagePanel panel = new JImagePanel();
panel.setMultiSelection(true);
frame.setLayout(new BorderLayout());
frame.add(panel, BorderLayout.CENTER);
frame.setVisible(true);
try {
File files[] = new File("/SOFTWARES/NETBEANS_PROJECTS/BE/S_CBIR/dataset").listFiles();
for(File file : files) {
BufferedImage image = ImageIO.read(file);
panel.addImageToList(image);
}
} catch (Exception e) {
e.printStackTrace(System.err);
}
Hope it'll help.
scrollPane.add(images[currentImage]);
images[currentImage].setSize(120, 100);
scrollPane.add(images[currentImage]);
Don't add components directly to a scroll pane.
A JScrollPane uses a JViewport to hold the component to be displayed.
So if you want to use a JList you would use:
JList<Icon> list = new JList<Icon>();
JScrollPane scrollPane = new JScrollPane( list );
frame.add( scrollPane );
Then you add the Icon (not a JLabel) to the JList. A JList already has a custom renderer to display an Icon.
Read the section from the Swing tutorial on How to Use Lists for more information and working examples.
The tutorial also has a section on How to Use Scroll Panes you should read.
Right, so I've been given this new project where I have to create one of those turtle programs were the user inputs 'forward 10' and the turtle paints a line on the screen. We were given a big chunk of code to start off with which took a bit of the fun out of it and I also cant fully get my head around how to update what the actual graphics panel. Here's the code we were given:
`import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
import javax.swing.JTextField;
/**
* Represents the graphics display panel within the turtle program. This panel contains an image which is updated to reflect user commands.
*
* #author mdixon
*
*/
#SuppressWarnings("serial")
public class GraphicsPanel extends JPanel {
int currentX = 0,currentY = 0;
JTextField commandLine;
/**
* The default BG colour of the image.
*/
private final static Color BACKGROUND_COL = Color.DARK_GRAY;
/**
* The underlying image used for drawing. This is required so any previous drawing activity is persistent on the panel.
*/
private BufferedImage image;
/**
* Draw a line on the image using the given colour.
*
* #param color
* #param x1
* #param y1
* #param x2
* #param y2
*/
public void createLine(int x2, int y2) {
System.out.println("current x position: " + currentX + "\ncurrent y position: " + currentY);
Graphics g = image.getGraphics();
g.drawLine(currentX, currentY, x2, y2);
//g.drawString("bloop" , currentX, currentY);
currentX = x2;
currentY = y2;
}
/**
* Clears the image contents.
*/
public void clear() {
Graphics g = image.getGraphics();
g.setColor(BACKGROUND_COL);
g.fillRect(0, 0, image.getWidth(), image.getHeight());
}
public void setColour(Color colour){
Graphics g = image.getGraphics();
g.setColor(colour);
}
#Override
public void paint(Graphics g) {
super.paintComponent(g);
// render the image on the panel.
g.drawImage(image, 0, 0, null);
}
/**
* Constructor.
*/
GraphicsPanel() {
setPreferredSize(new Dimension(500, 300));
image = new BufferedImage(500, 300, BufferedImage.TYPE_INT_RGB);
// Set max size of the panel, so that is matches the max size of the image.
setMaximumSize(new Dimension(image.getWidth(), image.getHeight()));
clear();
createLine(currentX + 100,currentY); //THIS WORKS AND UPDATES THE GRAPHICS PANEL
}
}`
I have already done some changes to it but only minor.
From a different panel which contains a JtextField and a JButton
So I call the other panel using this:
GraphicsPanel graphic = new GraphicsPanel();
graphic.createLine(graphic.currentX + 100,graphic.currentY);
I know this actually gets to createLine because I added a console output which shows the change in current x and y positions.
So yeah, If anybody can help with updating the graphics panel when calling it from a different panel it would be greatly appriciated.
Update to code:
Main:
`
import java.awt.*;
import javax.swing.*;
public class driver {
public static void main(String[] args) {
JFrame frame = new JFrame("Turtle");
frame.setSize(525, 375);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
WindowsPanel Window = new WindowsPanel();
frame.setJMenuBar(Window.createMenuBar());
frame.setContentPane(Window.createContentPane());
GraphicsPanel panel = new GraphicsPanel(); // creates panel
panel.setLayout(new BorderLayout());
frame.getContentPane().add(panel, BorderLayout.CENTER); // adds panel to frame
CommandPanel panel1 = new CommandPanel(); // creates panel
panel1.setLayout(new GridLayout(1, 2));
frame.getContentPane().add(panel1, BorderLayout.SOUTH); // adds panel to frame
frame.setVisible(true);
}
}
import java.awt.Component;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.*;
public class CommandPanel extends JPanel {
GraphicsPanel graphic = new GraphicsPanel();
private JTextField commandLine;
private JButton commandProcess;
CommandPanel() {
add(commandLine = new JTextField(40), Component.TOP_ALIGNMENT);
add(commandProcess = new JButton("Submit Command"),
Component.TOP_ALIGNMENT);
commandProcess.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String commands = commandLine.getText();
try{
String[] userCommand = new String[2];
userCommand = commands.split(" ");
String action = userCommand[0];
int amount = Integer.parseInt(userCommand[1]);
switch (action) {
case ("forward"):
newX = graphic.currentX + amount;
newY = graphic.currentY - amount;
graphic.createLine(newX,newY);
break;
case ("blue"):
graphic.setColour(Color.BLUE);
break;
default:
System.out.println("Invalid command!");
}
} catch (ArrayIndexOutOfBoundsException e1){
System.out.println("both sides of the command mus be inputted");
}
}
});
}
}
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
import javax.swing.JTextField;
/**
* Represents the graphics display panel within the turtle program. This panel contains an image which is updated to reflect user commands.
*
* #author mdixon
*
*/
#SuppressWarnings("serial")
public class GraphicsPanel extends JPanel {
int currentX = 0,currentY = 0;
/**
* The default BG colour of the image.
*/
private final static Color BACKGROUND_COL = Color.DARK_GRAY;
/**
* The underlying image used for drawing. This is required so any previous drawing activity is persistent on the panel.
*/
BufferedImage image;
/**
* Draw a line on the image using the given colour.
*
* #param color
* #param x1
* #param y1
* #param x2
* #param y2
*/
public void createLine(int x2, int y2) {
Graphics g = image.getGraphics();
g.drawLine(currentX, currentY, x2, y2);
currentX = x2;
currentY = y2;
}
/**
* Clears the image contents.
*/
public void clear() {
Graphics g = image.getGraphics();
g.setColor(BACKGROUND_COL);
g.fillRect(0, 0, image.getWidth(), image.getHeight());
}
public void setColour(Color colour){
Graphics g = image.getGraphics();
g.setColor(colour);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
#Override
public void paint(Graphics g) {
super.paint(g);
// render the image on the panel.
g.drawImage(image, 0, 0, null);
}
/**
* Constructor.
*/
GraphicsPanel() {
setPreferredSize(new Dimension(500, 300));
image = new BufferedImage(500, 300, BufferedImage.TYPE_INT_RGB);
// Set max size of the panel, so that is matches the max size of the image.
setMaximumSize(new Dimension(image.getWidth(), image.getHeight()));
clear();
currentX = 200;
currentY = 200;
}
}
`
All the valid code, should work with copy/paste
I'm making a function grapher that take 4 parameters and size for the Panel, but I don't know how to create a Panel class that will draw the information from the Grapher class. Can some one help please?(The parameters are not important, I just want to learn how to make a Graph Panel for later use)
Panel Class
import java.awt.BorderLayout;
public class Panel extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
}
/**
* Create the frame.
*/
public Panel(int w, int h) {
setVisible(true);
setSize(w,h);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, w, h);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setBackground(Color.WHITE);
setContentPane(contentPane);
contentPane.setLayout(null);
JPanel panel = new JPanel();
panel.setBackground(Color.WHITE);
panel.setBorder(new EmptyBorder(0, 0, 0, 0));
panel.setBounds(0, 0, w, h);
contentPane.add(panel);
}
public void paint(Graphics g) {
super.paint(g);
//g.drawLine(110, 112,129, 132);
}
public Graphics getGraphics(Graphics g){
return g;
}
}
Grapher class
import java.awt.EventQueue;
public class Grapher {
private int panelWidth;
private int panelHeight;
int x1;
int x2;
int y1;
int y2;
int a;
int b;
int c;
int d;
private JFrame frmChinhsFunctionGrapher;
private JTextField textFieldXMin;
private JTextField textFieldXMax;
private JTextField textFieldYMin;
private JTextField textFieldYMax;
private JTextField textFieldA;
private JTextField textFieldB;
private JTextField textFieldC;
private JTextField textFieldD;
private JLabel lblPeriod;
private JLabel lblYIntercept;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Grapher window = new Grapher();
window.frmChinhsFunctionGrapher.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Grapher() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frmChinhsFunctionGrapher = new JFrame();
frmChinhsFunctionGrapher.setTitle("Chinh's function grapher\r\n");
frmChinhsFunctionGrapher.setBounds(100, 100, 450, 300);
frmChinhsFunctionGrapher.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmChinhsFunctionGrapher.getContentPane().setLayout(null);
textFieldXMin = new JTextField();
textFieldXMin.setText("-200");
textFieldXMin.setBounds(66, 8, 86, 20);
frmChinhsFunctionGrapher.getContentPane().add(textFieldXMin);
textFieldXMin.setColumns(10);
JLabel lblXMin = new JLabel("X min");
lblXMin.setBounds(10, 11, 46, 14);
frmChinhsFunctionGrapher.getContentPane().add(lblXMin);
JLabel lblXMax = new JLabel("X max");
lblXMax.setBounds(10, 42, 46, 14);
frmChinhsFunctionGrapher.getContentPane().add(lblXMax);
textFieldXMax = new JTextField();
textFieldXMax.setText("200");
textFieldXMax.setBounds(66, 39, 86, 20);
frmChinhsFunctionGrapher.getContentPane().add(textFieldXMax);
textFieldXMax.setColumns(10);
textFieldYMin = new JTextField();
textFieldYMin.setText("-200");
textFieldYMin.setBounds(66, 70, 86, 20);
frmChinhsFunctionGrapher.getContentPane().add(textFieldYMin);
textFieldYMin.setColumns(10);
textFieldYMax = new JTextField();
textFieldYMax.setText("200");
textFieldYMax.setBounds(66, 101, 86, 20);
frmChinhsFunctionGrapher.getContentPane().add(textFieldYMax);
textFieldYMax.setColumns(10);
JLabel lblYMin = new JLabel("Y min");
lblYMin.setBounds(10, 73, 46, 14);
frmChinhsFunctionGrapher.getContentPane().add(lblYMin);
JLabel lblYMax = new JLabel("Y max");
lblYMax.setBounds(10, 104, 46, 14);
frmChinhsFunctionGrapher.getContentPane().add(lblYMax);
JLabel lblParameters = new JLabel("Parameters");
lblParameters.setBounds(320, 11, 93, 14);
frmChinhsFunctionGrapher.getContentPane().add(lblParameters);
textFieldA = new JTextField();
textFieldA.setText("100");
textFieldA.setBounds(360, 39, 64, 20);
frmChinhsFunctionGrapher.getContentPane().add(textFieldA);
textFieldA.setColumns(10);
JLabel lblNewLabel = new JLabel("Graph's Height");
lblNewLabel.setBounds(263, 42, 72, 14);
frmChinhsFunctionGrapher.getContentPane().add(lblNewLabel);
textFieldB = new JTextField();
textFieldB.setText("10");
textFieldB.setBounds(360, 70, 64, 20);
frmChinhsFunctionGrapher.getContentPane().add(textFieldB);
textFieldB.setColumns(10);
textFieldC = new JTextField();
textFieldC.setText("100");
textFieldC.setBounds(360, 101, 64, 20);
frmChinhsFunctionGrapher.getContentPane().add(textFieldC);
textFieldC.setColumns(10);
textFieldD = new JTextField();
textFieldD.setText("1");
textFieldD.setBounds(360, 132, 64, 20);
frmChinhsFunctionGrapher.getContentPane().add(textFieldD);
textFieldD.setColumns(10);
JButton btnGraph = new JButton("Graph");
btnGraph.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
getInput();
Panel pn = new Panel(panelWidth, panelHeight);
Graphics gs = pn.getGraphics();
gs.drawLine(100, 100, 200, 200);
}
});
btnGraph.setBounds(10, 228, 89, 23);
frmChinhsFunctionGrapher.getContentPane().add(btnGraph);
lblPeriod = new JLabel("Period");
lblPeriod.setBounds(263, 73, 46, 14);
frmChinhsFunctionGrapher.getContentPane().add(lblPeriod);
lblYIntercept = new JLabel("Vertical shift");
lblYIntercept.setBounds(263, 104, 72, 14);
frmChinhsFunctionGrapher.getContentPane().add(lblYIntercept);
JLabel lblHorizontalShift = new JLabel("Horizontal shift");
lblHorizontalShift.setBounds(263, 135, 86, 14);
frmChinhsFunctionGrapher.getContentPane().add(lblHorizontalShift);
}
public void getInput(){
x1 = Integer.parseInt(textFieldXMin.getText());
x2 = Integer.parseInt(textFieldXMax.getText());
y1 = Integer.parseInt(textFieldYMin.getText());
y2 = Integer.parseInt(textFieldYMax.getText());
a = Integer.parseInt(textFieldA.getText());
b = Integer.parseInt(textFieldB.getText());
c = Integer.parseInt(textFieldC.getText());
d = Integer.parseInt(textFieldD.getText());
panelWidth = Math.abs(x2 - x1);
panelHeight = Math.abs(y2 - y1);
}
}
There are quite some issues with your code
You should not use the null layout. You should not extent JFrame and even if you do it, you should not override the paint method of JFrame. You should create the GUI on the Event Dispatch Thread. You should have an idea of how you are going to define which area of the function is plotted into which area of the panel. (Plotting a function like sin(x) will result in a straight, horizontal line, because the values will alternate between -1 and 1, and thus, span a range of only 3 pixels...)
However, once I created a https://stackoverflow.com/help/mcve showing a very simple plotter that can be used to plot arbitrary functions. Maybe you find parts of it "inspiring".
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
* Main class of the simple function plotter. Contains the
* main method and creates the GUI
*/
public class SimplePlotMain
{
/**
* Entry point
*
* #param args not used
*/
public static void main(String[] args)
{
// Create the GUI on the Event-Dispatch-Thread
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGUI();
}
});
}
/**
* Creates the frame containing the simple plotter
*/
private static void createAndShowGUI()
{
// Create the main frame
JFrame frame = new JFrame("SimplePlot");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout());
frame.setSize(800,600);
// Create the SimplePlotPanel and add it to the frame
SimplePlotPanel plotPanel = new SimplePlotPanel();
frame.getContentPane().add(plotPanel, BorderLayout.CENTER);
// Create the Function that should be plotted, and assign
// it to the SimplePlotPanel
Function function = new Function()
{
#Override
public double compute(double argument)
{
return Math.sin(argument)*argument;
}
};
plotPanel.setFunction(function);
// Create a simple control panel and add it to the frame
JComponent controlPanel = createControlPanel(plotPanel);
frame.getContentPane().add(controlPanel, BorderLayout.EAST);
// As the last action: Make the frame visible
frame.setVisible(true);
}
/**
* Creates a panel containing some Spinners that allow defining
* the area in which the function should be shown
*
* #param plotPanel The SimplePlotPanel, to which the settings
* will be transferred
* #return The control-panel
*/
private static JComponent createControlPanel(
final SimplePlotPanel plotPanel)
{
JPanel controlPanel = new JPanel(new BorderLayout());
JPanel panel = new JPanel(new GridLayout(0,2));
controlPanel.add(panel, BorderLayout.NORTH);
// Create spinners for the minimum and maximum
// X- and Y-values
final JSpinner minXSpinner = new JSpinner(
new SpinnerNumberModel(-1.0, -1000.0, 1000.0, 0.1));
final JSpinner maxXSpinner = new JSpinner(
new SpinnerNumberModel( 1.0, -1000.0, 1000.0, 0.1));
final JSpinner minYSpinner = new JSpinner(
new SpinnerNumberModel(-1.0, -1000.0, 1000.0, 0.1));
final JSpinner maxYSpinner = new JSpinner(
new SpinnerNumberModel( 1.0, -1000.0, 1000.0, 0.1));
// Add the spinners and some labels to the panel
panel.add(new JLabel("minX"));
panel.add(minXSpinner);
panel.add(new JLabel("maxX"));
panel.add(maxXSpinner);
panel.add(new JLabel("minY"));
panel.add(minYSpinner);
panel.add(new JLabel("maxY"));
panel.add(maxYSpinner);
// Create a ChangeListener that will be added to all spinners,
// and which transfers the settings to the SimplePlotPanel
ChangeListener changeListener = new ChangeListener()
{
#Override
public void stateChanged(ChangeEvent event)
{
double minX = ((Double)minXSpinner.getValue()).doubleValue();
double maxX = ((Double)maxXSpinner.getValue()).doubleValue();
double minY = ((Double)minYSpinner.getValue()).doubleValue();
double maxY = ((Double)maxYSpinner.getValue()).doubleValue();
plotPanel.setRangeX(minX, maxX);
plotPanel.setRangeY(minY, maxY);
}
};
minXSpinner.addChangeListener(changeListener);
maxXSpinner.addChangeListener(changeListener);
minYSpinner.addChangeListener(changeListener);
maxYSpinner.addChangeListener(changeListener);
// Set some default values for the Spinners
minXSpinner.setValue(-10.0);
maxXSpinner.setValue( 10.0);
minYSpinner.setValue(-10.0);
maxYSpinner.setValue( 10.0);
return controlPanel;
}
}
/**
* Interface for a general function that may be plotted with
* the SimplePlotPanel
*/
interface Function
{
/**
* Compute the value of the function for the given argument
*
* #param argument The function argument
* #return The function value
*/
double compute(double argument);
}
/**
* The panel in which the function will be plotted
*/
class SimplePlotPanel extends JPanel
{
private static final long serialVersionUID = -6588061082489436970L;
/**
* The function that will be plotted
*/
private Function function;
/**
* The minimal x value that is shown
*/
private double minX = -1.0f;
/**
* The maximal x value that is shown
*/
private double maxX = 1.0f;
/**
* The minimal y value that is shown
*/
private double minY = -1.0f;
/**
* The maximal y value that is shown
*/
private double maxY = 1.0f;
/**
* Set the Function that should be plotted
*
* #param function The Function that should be plotted
*/
public void setFunction(Function function)
{
this.function = function;
repaint();
}
/**
* Set the x-range that should be plotted
*
* #param minX The minimum x-value
* #param maxX The maximum y-value
*/
public void setRangeX(double minX, double maxX)
{
this.minX = minX;
this.maxX = maxX;
repaint();
}
/**
* Set the y-range that should be plotted
*
* #param minY The minimum y-value
* #param maxY The maximum y-value
*/
public void setRangeY(double minY, double maxY)
{
this.minY = minY;
this.maxY = maxY;
repaint();
}
/**
* Overridden method from JComponent: Paints this panel - that
* is, paints the function into the given graphics object
*/
#Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
Graphics2D g = (Graphics2D)gr;
g.setColor(Color.WHITE);
g.fillRect(0,0,getWidth(),getHeight());
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
paintAxes(g);
paintFunction(g);
}
/**
* Converts an x-coordinate of the function into an x-value of this panel
*
* #param x The x-coordinate of the function
* #return The x-coordinate on this panel
*/
private int toScreenX(double x)
{
double relativeX = (x-minX)/(maxX-minX);
int screenX = (int)(getWidth() * relativeX);
return screenX;
}
/**
* Converts an y-coordinate of the function into an y-value of this panel
*
* #param y The y-coordinate of the function
* #return The y-coordinate on this panel
*/
private int toScreenY(double y)
{
double relativeY = (y-minY)/(maxY-minY);
int screenY = getHeight() - 1 - (int)(getHeight() * relativeY);
return screenY;
}
/**
* Converts an x-coordinate on this panel into an x-coordinate
* for the function
*
* #param x The x-coordinate on the panel
* #return The x-coordinate for the function
*/
private double toFunctionX(int x)
{
double relativeX = (double)x/getWidth();
double functionX = minX + relativeX * (maxX - minX);
return functionX;
}
/**
* Paints some coordinate axes into the given Graphics
*
* #param g The graphics
*/
private void paintAxes(Graphics2D g)
{
int x0 = toScreenX(0);
int y0 = toScreenY(0);
g.setColor(Color.BLACK);
g.drawLine(0,y0,getWidth(),y0);
g.drawLine(x0,0,x0,getHeight());
}
/**
* Paints the function into the given Graphics
*
* #param g The graphics
*/
private void paintFunction(Graphics2D g)
{
g.setColor(Color.BLUE);
int previousScreenX = 0;
double previousFunctionX = toFunctionX(previousScreenX);
double previousFunctionY = function.compute(previousFunctionX);
int previousScreenY = toScreenY(previousFunctionY);
for (int screenX=1; screenX<getWidth(); screenX++)
{
double functionX = toFunctionX(screenX);
double functionY = function.compute(functionX);
int screenY = toScreenY(functionY);
g.drawLine(previousScreenX, previousScreenY, screenX, screenY);
previousScreenX = screenX;
previousScreenY = screenY;
}
}
}
First, I would say delete the main() method in the panel class. It has nothing to do with answering your question, but I think it'll cause problems and/or confusion.
What you need to do is
1) add a reference in the panel class to the Grapher class so that the panel paint method can call the Grapher class
2) set the reference to point to the instance of the Grapher class
3) have the Panel paint method invoke a method in the Grapher class to draw the graph.
1) Add a reference
public class Panel extends JFrame {
private Grapher myGrapher = null; //add this line
private JPanel contentPane;
2) Set the reference
public Panel(Grapher graph, int w, int h) { //change this line
myGrapher = graph; //add this line
setVisible(true);
and
public void actionPerformed(ActionEvent arg0) {
getInput();
Panel pn = new Panel(this, panelWidth, panelHeight); //change this line
//Graphics gs = pn.getGraphics(); //remove this line
//gs.drawLine(100, 100, 200, 200); //remove this line
}
3) Invoke the method
public void paint(Graphics g) {
super.paint(g);
//g.drawLine(110, 112,129, 132);
if(myGrapher != null) //add this line
{
myGrapher.drawGraph(g); //add this line
}
}
and in the Grapher class, add the method
void drawGraph(Graphics g) {
g.drawLine(100, 100, 200, 200);
//whatever else you need to draw the graph
}
Good luck!
i'm trying to put an image as a background of my interface in java , i tried to write a class that does that and using it , but is there a simpler way to do that .
here 's the code i used:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class BackgroundImagePanelExample {
// Set up contraints so that the user supplied component and the
// background image label overlap and resize identically
private static final GridBagConstraints gbc;
static {
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.fill = GridBagConstraints.BOTH;
gbc.anchor = GridBagConstraints.NORTHWEST;
}
/**
* Wraps a Swing JComponent in a background image. Simply invokes the overloded
* variant with Top/Leading alignment for background image.
*
* #param component - to wrap in the a background image
* #param backgroundIcon - the background image (Icon)
* #return the wrapping JPanel
*/
public static JPanel wrapInBackgroundImage(JComponent component,
Icon backgroundIcon) {
return wrapInBackgroundImage(
component,
backgroundIcon,
JLabel.TOP,
JLabel.LEADING);
}
/**
* Wraps a Swing JComponent in a background image. The vertical and horizontal
* alignment of background image can be specified using the alignment
* contants from JLabel.
*
* #param component - to wrap in the a background image
* #param backgroundIcon - the background image (Icon)
* #param verticalAlignment - vertical alignment. See contants in JLabel.
* #param horizontalAlignment - horizontal alignment. See contants in JLabel.
* #return the wrapping JPanel
*/
public static JPanel wrapInBackgroundImage(JComponent component,
Icon backgroundIcon,
int verticalAlignment,
int horizontalAlignment) {
// make the passed in swing component transparent
component.setOpaque(false);
// create wrapper JPanel
JPanel backgroundPanel = new JPanel(new GridBagLayout());
// add the passed in swing component first to ensure that it is in front
backgroundPanel.add(component, gbc);
// create a label to paint the background image
JLabel backgroundImage = new JLabel(backgroundIcon);
// set minimum and preferred sizes so that the size of the image
// does not affect the layout size
backgroundImage.setPreferredSize(new Dimension(1, 1));
backgroundImage.setMinimumSize(new Dimension(1, 1));
// align the image as specified.
backgroundImage.setVerticalAlignment(verticalAlignment);
backgroundImage.setHorizontalAlignment(horizontalAlignment);
// add the background label
backgroundPanel.add(backgroundImage, gbc);
// return the wrapper
return backgroundPanel;
}
public static void main(String[] args) {
JFrame frame = new JFrame("Background Image Panel Example");
// Create some GUI
JPanel foregroundPanel = new JPanel(new BorderLayout(10, 10));
foregroundPanel.setBorder(
BorderFactory.createEmptyBorder(10, 10, 10, 10));
foregroundPanel.setOpaque(false);
foregroundPanel.add(new JLabel("Comment:"), BorderLayout.NORTH);
foregroundPanel.add(new JScrollPane(new JTextArea(3, 10)),
BorderLayout.CENTER);
foregroundPanel.add(
new JLabel(
"Please enter your comments in text box above."
+ " HTML syntax is allowed."), BorderLayout.SOUTH);
frame.setContentPane(wrapInBackgroundImage(foregroundPanel,
new ImageIcon(
BackgroundImagePanelExample.class.getResource("backgd.jpg"))));
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
thanks
I'm guessing you're getting java.lang.NullPointerException because backgd.jpg can't be found by getResource(). You might be able to put the image file alongside the source file and rebuild the project. Alternatively, you can load it from the file system as a temporary measure while you sort things out.
frame.setContentPane(wrapInBackgroundImage(
foregroundPanel, new ImageIcon("image.jpg")));
I dont actually see what are you asking. If you are asking, whether there is simpler way to build swing apps - than answer is YES. Use NetBeans IDE with Swing builder which produces very reasonable generated code and lets you edit whole bunch of componenets. Hand written Swing is more often "broken" than generated code from NetBeans, and much much more time consuming ...
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ImageTest {
public static void main(String[] args) {
ImagePanel panel = new ImagePanel(new ImageIcon("images/background.png").getImage());
JFrame frame = new JFrame();
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
}
class ImagePanel extends JPanel {
private Image img;
public ImagePanel(String img) {
this(new ImageIcon(img).getImage());
}
public ImagePanel(Image img) {
this.img = img;
Dimension size = new Dimension(img.getWidth(null), img.getHeight(null));
setPreferredSize(size);
setMinimumSize(size);
setMaximumSize(size);
setSize(size);
setLayout(null);
}
public void paintComponent(Graphics g) {
g.drawImage(img, 0, 0, null);
}
}
public class BackgroundPanel extends JPanel {
private static final long serialVersionUID = 1L;
Image image;
public BackgroundPanel() {
super();
initialize();
}
/**
* This method initializes this
*
* #return void
*/
private void initialize() {
try {
image = new ImageIcon(getClass().getResource("background.jpg")).getImage();
} catch (Exception e) {
/*handled in paintComponent()*/
}
this.setSize(800, 470);
this.setLayout(null);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if(image != null) {
g.drawImage(image, 0,0,this.getWidth(),this.getHeight(),this);
}
}
}