This is a program to display a pie chart. I also have a button. But the program I have written, creates two separate frames and one frame is for the pie chart and the other is for the button. How do I put both button and pie chart on the same frame?? Can you please rectify my program.
import java.awt.*;
import org.jfree.chart.*;
import org.jfree.chart.title.*;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.ui.*;
import java.io.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.filechooser.*;
public class Pie{
public static void getFile(File f)
{
System.out.println("File is: "+f.getName());
}
public static void main(String[] args)
{
JPanel panel=new JPanel();
panel.setLayout(null);
JButton b=new JButton("Open File");
b.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
JFileChooser chooser=new JFileChooser();
int ret = chooser.showDialog(null, "Open file");
if (ret == JFileChooser.APPROVE_OPTION)
{
File file = chooser.getSelectedFile();
getFile(file);
}
}
}
);
b.setBounds(50,40,100,35);
panel.add(b);
DefaultPieDataset pieDataset = new DefaultPieDataset();
ieDataset.setValue("A", new Integer(10));
pieDataset.setValue("B", new Integer(20));
pieDataset.setValue("C", new Integer(30));
pieDataset.setValue("D", new Integer(10));
pieDataset.setValue("E", new Integer(20));
pieDataset.setValue("F", new Integer(10));
FreeChart chart = ChartFactory.createPieChart("Pie Chart using JFreeChart", pieDataset, true,true,true);
ChartFrame frame1=new ChartFrame("Pie Chart",chart);
frame1.add(panel);
frame1.setVisible(true);
frame1.setSize(600,600);
}
}
Don't use absolute layout unless it is really necessary. Rely on layout managers, pref/min/max size and constraints to size and position components. This also means that you should not call setBounds/setSize/setLocation on components, let the layout manager do this for you.
Init the UI from the EDT (Event dispatching tread)
You don't do anything with your FileChooser currently
Try to avoid static and instead use new Something()
Don't use new Integer() but rather use Integer.valueOf() (and this is valid for all the primitive wrapping classes, Boolean, Short, Long, ...)
I am not sure how you get two frames, but I got your code working by modifying it this way.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.data.general.DefaultPieDataset;
public class Pie {
private static void initUI() {
JPanel panel = new JPanel(new FlowLayout());
final JButton b = new JButton("Open File");
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JFileChooser chooser = new JFileChooser();
int ret = chooser.showDialog(b, "Open file");
if (ret == JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
// Don't know what you want to do
}
}
});
panel.add(b);
DefaultPieDataset pieDataset = new DefaultPieDataset();
pieDataset.setValue("A", Integer.valueOf(10));
pieDataset.setValue("B", Integer.valueOf(20));
pieDataset.setValue("C", Integer.valueOf(30));
pieDataset.setValue("D", Integer.valueOf(10));
pieDataset.setValue("E", Integer.valueOf(20));
pieDataset.setValue("F", Integer.valueOf(10));
JFreeChart chart = ChartFactory.createPieChart("Pie Chart using JFreeChart", pieDataset, true, true, true);
JFrame frame1 = new JFrame();
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ChartPanel chartPanel = new ChartPanel(chart);
// chartPanel.setPreferredSize(new Dimension(600, 600));
frame1.getContentPane().add(chartPanel, BorderLayout.CENTER);
frame1.getContentPane().add(panel, BorderLayout.SOUTH);
frame1.pack();
frame1.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
initUI();
}
});
}
}
There is a class called ChartPanel. It is a sub class of JPanel class.
JPanel chartPanel = new ChartPanel(chart);
Then you can add this panel to the frame. hope this helps........
Replace this line
ChartFrame frame1=new ChartFrame("Pie Chart",chart);
with
panel.add(chart)
Kindly let me know the result
Related
I have written a Java GUI program which opens a text file and reads the data in the left panel. Now I want to display a graph of the data read from the same file on the right panel.
I have used JFileChooser to open files and read the data and display them on a text area. I want the data read from the file to be displayed using a two dimensional X-Y graph. The axis of the graph should be labeled using the label information specified in the data file. The values on the X-axis should begin from the x-axis start value specified, with intervals which increment at a rate determined by the x-axis interval value. The values on the Y-axis will need to be determined from the data itself. Each point plotted on the graph should be joined using a single line.
I have used several methods but none worked. I have tried reading each line on the text file as arrays and use the arrays as the dataset, but it didn't work as well. Please help me plot a graph from the data on the text file. Any help would be appreciated. Thanks.
P.S The graph should be plotted using AWT/Swing libraries only.
The data on the file is as follows:
Title: Effect of Age on Ability
Xlabel: Age
Ylabel: Ability
start: 0
interval: 15
0, 3, 4.2, 7, 5.1, 10, 3.2
Following are my code which I have written so far:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.List;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Scanner;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
#SuppressWarnings("serial")
public class GUI extends JFrame {
private String[] readLines = new String[6];
public GUI() {
// Setting Title, size and layout
setTitle("Data Visualiser");
setSize(950, 1000);
setLayout(new BorderLayout());
// Creates a menubar for a JFrame
final JMenuBar menuBar = new JMenuBar();
// Add the menubar to the frame
setJMenuBar(menuBar);
// Define and add two drop down menu to the menubar, "file" and "help"
JMenu fileMenu = new JMenu("File");
JMenu helpMenu = new JMenu("Help");
menuBar.add(fileMenu);
menuBar.add(helpMenu);
// adding menu items and icons to the "file" drop down menu,
final JMenuItem openAction = new JMenuItem("Open", new ImageIcon("images/Open-icon.png"));
final JMenuItem saveAction = new JMenuItem("Save", new ImageIcon("images/save-file.png"));
final JMenuItem exitAction = new JMenuItem("Exit", new ImageIcon("images/exit-icon.png"));
final JMenuItem aboutAction = new JMenuItem("About", new ImageIcon("images/about-us.png"));
//////////////////////////////////////////////////////////////////////////////////////////////
// Create a text area.
final JTextArea textArea = new JTextArea("");
textArea.setFont(new Font("Serif", Font.BOLD, 16));
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.setEditable(false);
JScrollPane textScrollPane = new JScrollPane(textArea);
// textArea.add(textScrollPane, BorderLayout.CENTER); //add the
// JScrollPane to the panel
// Scrollbars
textScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
textScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
textScrollPane.setPreferredSize(new Dimension(350, 550));
textScrollPane.setBorder(
BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Textual Representation"),
BorderFactory.createEmptyBorder(5, 5, 5, 5)));
// Create an graphics pane.
JPanel graphicsArea = new JPanel();
//graphicsArea.setFont(new Font("Serif", Font.BOLD, 16));
JScrollPane graphicsScrollPane = new JScrollPane(graphicsArea);
// Scrollbars
graphicsScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
graphicsScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
graphicsScrollPane.setPreferredSize(new Dimension(550, 550));
graphicsScrollPane.setBorder(
BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Graphical Representation"),
BorderFactory.createEmptyBorder(5, 5, 5, 5)));
// Put the graphics pane and the text pane in a split pane.
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, textScrollPane, graphicsScrollPane);
splitPane.setOneTouchExpandable(true);
splitPane.setResizeWeight(0.5);
JPanel rightPane = new JPanel(new GridLayout(1, 0));
rightPane.add(splitPane);
// Put everything together.
JPanel leftPane = new JPanel(new BorderLayout());
add(rightPane, BorderLayout.LINE_END);
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// file menu shortcut
fileMenu.setMnemonic(KeyEvent.VK_F);
fileMenu.add(openAction);
// openAction.addActionListener(this);
openAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if (arg0.getSource().equals(openAction)) {
// using JFileChooser to open the text file
JFileChooser fileChooser = new JFileChooser();
if (fileChooser.showOpenDialog(fileChooser) == JFileChooser.APPROVE_OPTION) {
// fileChooser.setCurrentDirectory(new
// File(System.getProperty("user.home"))); // setting
// current
// directory
File file = fileChooser.getSelectedFile();
BufferedReader br = null;
try {
// FileReader fr = new FileReader(file);
Scanner f = new Scanner(file);
for (int i = 0; i < 6; i++) {
readLines[i] = f.nextLine();
textArea.setText(textArea.getText() + readLines[i] + "\n");
String array[] = readLines[i].split(" ");
}
} catch (FileNotFoundException e) {
JOptionPane.showMessageDialog(new JFrame(), "File not found!", "ERROR!",
JOptionPane.ERROR_MESSAGE); // error message
// if file not
// found
} catch (NullPointerException e) {
// System.out.println(e.getLocalizedMessage());
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
});
fileMenu.add(saveAction);
fileMenu.add(exitAction);
// exit button shortcut
exitAction.setMnemonic(KeyEvent.VK_X);
exitAction.addActionListener(new ActionListener() {
// setting up exit button
public void actionPerformed(ActionEvent arg0) {
if (arg0.getSource().equals(exitAction)) {
System.exit(0);
}
}
});
fileMenu.addSeparator();
helpMenu.addSeparator();
helpMenu.add(aboutAction);
// about button shortcut
aboutAction.setMnemonic(KeyEvent.VK_A);
aboutAction.addActionListener(new ActionListener() {
// clicking on about button opens up a dialog box which contain
// information about the program
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(menuBar.getComponent(0),
"This program is based on the development of a data visualization tool. \n"
+ "The basic concept is to produce a piece of software which reads in raw textual data, \n"
+ "analyses that data, then presents it graphically to the user.",
"About Us", JOptionPane.PLAIN_MESSAGE);
}
});
}
}
Starting from your example, note the following:
Use a ChartPanel for your graphicsArea; then, your openAction() can simply invoke setChart().
Parse the chosen file in creatChart(); the title and data lines are shown, but the remaining attributes are left as an exercise.
Consider using Properties for your file format;
For greater flexibility, use Action as shown here.
To change the chart panel's default size, override getPreferredSize() as shown here.
Swing GUI objects should be constructed and manipulated only on the event dispatch thread.
P.S. The graph should be plotted using AWT/Swing libraries only.
For a single chart, replace ChartPanel with JPanel and override paintComponent() to perform the rendering. You can transform coordinates using the approach is outlined here or here.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
//* #see https://stackoverflow.com/a/36764715/230513 */
public class GUI extends JFrame {
public GUI() {
super("Data Visualiser");
setDefaultCloseOperation(EXIT_ON_CLOSE);
final JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu fileMenu = new JMenu("File");
JMenu helpMenu = new JMenu("Help");
menuBar.add(fileMenu);
menuBar.add(helpMenu);
final JMenuItem openAction = new JMenuItem("Open", new ImageIcon("images/Open-icon.png"));
final JMenuItem saveAction = new JMenuItem("Save", new ImageIcon("images/save-file.png"));
final JMenuItem exitAction = new JMenuItem("Exit", new ImageIcon("images/exit-icon.png"));
final JMenuItem aboutAction = new JMenuItem("About", new ImageIcon("images/about-us.png"));
final JTextArea textArea = new JTextArea(8, 16);
textArea.setFont(new Font("Serif", Font.BOLD, 16));
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.setEditable(false);
JScrollPane textScrollPane = new JScrollPane(textArea);
textScrollPane.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder("Textual Representation"),
BorderFactory.createEmptyBorder(5, 5, 5, 5)));
ChartPanel graphicsArea = new ChartPanel(null);
graphicsArea.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder("Graphical Representation"),
BorderFactory.createEmptyBorder(5, 5, 5, 5)));
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, textScrollPane, graphicsArea);
splitPane.setOneTouchExpandable(true);
splitPane.setResizeWeight(0.5);
add(splitPane, BorderLayout.LINE_END);
fileMenu.setMnemonic(KeyEvent.VK_F);
fileMenu.add(openAction);
openAction.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
if (arg0.getSource().equals(openAction)) {
JFileChooser fileChooser = new JFileChooser(new File("."));
if (fileChooser.showOpenDialog(fileChooser) == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
graphicsArea.setChart(creatChart(file));
}
}
}
private JFreeChart creatChart(File file) {
String title = null;
String xAxisLabel = null;
String yAxisLabel = null;
BufferedReader in = null;
int start = 0;
int interval = 0;
String data = null;
String line = null;
try {
in = new BufferedReader(new FileReader(file));
while ((line = in.readLine()) != null) {
textArea.append(line + "\n");
if (line.startsWith("Title")) {
title = line.split(":")[1].trim();
}
// parse other lines here
if (!line.contains(":")) {
data = line;
}
}
} catch (IOException ex) {
ex.printStackTrace(System.err);
}
XYSeries dataset = new XYSeries(file.getName());
for (String s : data.split(",")) {
dataset.add(start, Double.valueOf(s));
start += interval;
}
return ChartFactory.createXYLineChart(title,
xAxisLabel, yAxisLabel, new XYSeriesCollection(dataset));
}
});
fileMenu.add(saveAction);
fileMenu.add(exitAction);
exitAction.setMnemonic(KeyEvent.VK_X);
exitAction.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
if (arg0.getSource().equals(exitAction)) {
System.exit(0);
}
}
});
fileMenu.addSeparator();
helpMenu.addSeparator();
helpMenu.add(aboutAction);
aboutAction.setMnemonic(KeyEvent.VK_A);
aboutAction.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(null,
"Visualization tool.",
"About Us", JOptionPane.PLAIN_MESSAGE);
}
});
pack();
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
new GUI();
});
}
}
I am getting files from JFileChooser and showing them by reading with BufferedImage and putting in JLabels but there is a problem that my images are not completely shown in JLabels. Here is my code
public class ImagePreview
{
JPanel PicHolder= new JPanel();
public ImagePreview()
{
JButton GetImages = new JButton("Browse Images");
GetImages.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent evt)
{
CreatePreviews();
};
});
PicHolder.add(GetImages);
JFrame MainFrame = new JFrame("Image Preview");
MainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MainFrame.getContentPane().add(PicHolder);
MainFrame.pack();
MainFrame.setVisible(true);
}
public void CreatePreviews()
{
JFileChooser chooser = new JFileChooser();
chooser.setMultiSelectionEnabled(true);
File[] selectedCarImages = chooser.getSelectedFiles();
for(int a=0; a<selectedImages.length; a++)
{
try
{
BufferedImage myPicture = ImageIO.read(new File(selectedImages[a].getAbsolutePath()));
JLabel picLabel = new JLabel(new ImageIcon(myPicture));
PicHolder.add(picLabel);
}
}
}
public static void main(String[] args)
{
java.awt.EventQueue.invokeLater(() -> {
new ImagePreview();
});
}
}
When I run this code, it shows user selected images but they are kind of automatically croped and not showing completely in JLabels.
What's wrong here? Why JLabels do not show full images?
You're adding all the components and images to a single panel having the default FlowLayout. Instead, use GridLayout for the picture labels and add the browse button to the frame's default BorderLayout, as shown below.
As tested:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class ImagePreview {
JFrame mainFrame = new JFrame("Image Preview");
JPanel picHolder = new JPanel(new GridLayout(0, 1));
public ImagePreview() {
JButton getImages = new JButton("Browse Images");
getImages.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent evt) {
CreatePreviews();
}
});
mainFrame.add(getImages, BorderLayout.NORTH);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.add(new JScrollPane(picHolder));
mainFrame.pack();
mainFrame.setLocationByPlatform(true);
mainFrame.setVisible(true);
}
public void CreatePreviews() {
JFileChooser chooser = new JFileChooser();
chooser.setMultiSelectionEnabled(true);
chooser.showOpenDialog(mainFrame);
File[] selectedImages = chooser.getSelectedFiles();
for (int a = 0; a < selectedImages.length; a++) {
try {
BufferedImage myPicture = ImageIO.read(new File(selectedImages[a].getAbsolutePath()));
JLabel picLabel = new JLabel(new ImageIcon(myPicture));
picHolder.add(picLabel);
mainFrame.pack();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(() -> {
new ImagePreview();
});
}
}
I have 4 JPanels. In one of the panel I have a combo Box.Upon selecting "Value A" in combo box Panel2 should be displayed.Similarly if I select "Value B" Panel3 should be selected....
Though action Listener should be used in this context.How to make a call to another tab with in that action listener.
public class SearchComponent
{
....
.
public SearchAddComponent(....)
{
panel = addDropDown(panelList(), "panel", gridbag, h6Box);
panel.addComponentListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ItemSelectable is = (ItemSelectable)actionEvent.getSource();
Object name=selectedString(is);
}
});
}
public static final Vector<String> panelList(){
List<String> panelList = new ArrayList<String>();
panelList.add("A");
panelList.add("B");
panelList.add("C");
panelList.add("D");
panelList.add("E");
panelList.add("F);
Vector<String> panelVector = null;
Collections.copy(panelVector, panelList);
return panelVector;
}
public Object selectedString(ItemSelectable is) {
Object selected[] = is.getSelectedObjects();
return ((selected.length == 0) ? "null" : (ComboItem)selected[0]);
}
}
Use a Card Layout. See the Swing tutorial on How to Use a Card Layout for a working example.
Try This code:
import java.awt.EventQueue;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import javax.swing.BorderFactory;
import javax.swing.border.Border;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JComboBox;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import java.awt.Container;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class CardLayoutExample {
JFrame guiFrame;
CardLayout cards;
JPanel cardPanel;
public static void main(String[] args) {
//Use the event dispatch thread for Swing components
EventQueue.invokeLater(new Runnable()
{
#Override
public void run()
{
new CardLayoutExample();
}
});
}
public CardLayoutExample()
{
guiFrame = new JFrame();
//make sure the program exits when the frame closes
guiFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
guiFrame.setTitle("CardLayout Example");
guiFrame.setSize(400,300);
//This will center the JFrame in the middle of the screen
guiFrame.setLocationRelativeTo(null);
guiFrame.setLayout(new BorderLayout());
//creating a border to highlight the JPanel areas
Border outline = BorderFactory.createLineBorder(Color.black);
JPanel tabsPanel = new JPanel();
tabsPanel.setBorder(outline);
JButton switchCards = new JButton("Switch Card");
switchCards.setActionCommand("Switch Card");
switchCards.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent event)
{
cards.next(cardPanel);
}
});
tabsPanel.add(switchCards);
guiFrame.add(tabsPanel,BorderLayout.NORTH);
cards = new CardLayout();
cardPanel = new JPanel();
cardPanel.setLayout(cards);
cards.show(cardPanel, "Fruits");
JPanel firstCard = new JPanel();
firstCard.setBackground(Color.GREEN);
addButton(firstCard, "APPLES");
addButton(firstCard, "ORANGES");
addButton(firstCard, "BANANAS");
JPanel secondCard = new JPanel();
secondCard.setBackground(Color.BLUE);
addButton(secondCard, "LEEKS");
addButton(secondCard, "TOMATOES");
addButton(secondCard, "PEAS");
cardPanel.add(firstCard, "Fruits");
cardPanel.add(secondCard, "Veggies");
guiFrame.add(tabsPanel,BorderLayout.NORTH);
guiFrame.add(cardPanel,BorderLayout.CENTER);
guiFrame.setVisible(true);
}
//All the buttons are following the same pattern
//so create them all in one place.
private void addButton(Container parent, String name)
{
JButton but = new JButton(name);
but.setActionCommand(name);
parent.add(but);
}
}
I have a JFrame that displays JPanels depending on the MenuItem you click. It works, but now I need to call a method once a JPanel is added to the frame and it is being shown (because I'm using JFreeChart inside that panel and I have to call chartPanel.repaint() when the JPanel is visible):
this.getContentPane().add( myjpanel, BorderLayout.CENTER ); //this = JFrame
this.validate();
myjpanel.methodCalledOnceDisplayed();
Does it seem ok? Is myjpanel being shown really? It seems it is not:
public void methodCalledOnceDisplayed() {
chartPanel.repaint()
}
This is not working (chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotInfo(0) is throwing IndexOutOfBoundsException). That means that the JPanel was not visible when repaint was called, I've tested the following:
public void methodCalledOnceDisplayed() {
JOptionPane.showMessageDialog(null,"You should see myjpanel now");
chartPanel.repaint()
}
Now it works, I see myjpanel behind the alert, just as expected, chartPanel is repainted and no Exception occurs.
EDIT: SSCCE (jfreechart and jcommon needed: http://www.jfree.org/jfreechart/download.html)
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.CombinedDomainXYPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.ChartPanel;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Window extends JFrame {
private JPanel contentPane;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Window frame = new Window();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Window() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 700, 500);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JButton clickme = new JButton("Click me");
clickme.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
contentPane.removeAll();
MyJPanel mypanel = new MyJPanel();
contentPane.add( mypanel, BorderLayout.CENTER );
validate();
mypanel.methodCalledOnceDisplayed();
}
});
contentPane.add( clickme, BorderLayout.NORTH );
JPanel example = new JPanel();
example.add( new JLabel("Example JPanel") );
contentPane.add( example, BorderLayout.CENTER );
}
}
class MyJPanel extends JPanel implements ChartMouseListener {
private ChartPanel chartPanel;
private JFreeChart chart;
private XYPlot subplotTop;
private XYPlot subplotBottom;
private CombinedDomainXYPlot plot;
public MyJPanel() {
this.add( new JLabel("This JPanel contains the chart") );
createCombinedChart();
chartPanel = new ChartPanel(chart);
chartPanel.addChartMouseListener(this);
this.add( chartPanel );
}
private void createCombinedChart() {
plot = new CombinedDomainXYPlot();
plot.setGap(30);
createSubplots();
plot.add(subplotTop, 4);
plot.add(subplotBottom, 1);
plot.setOrientation(PlotOrientation.VERTICAL);
chart = new JFreeChart("Title", new Font("Arial", Font.BOLD,20), plot, true);
}
private void createSubplots() {
subplotTop = new XYPlot();
subplotBottom = new XYPlot();
subplotTop.setDataset(emptyDataset("Empty 1"));
subplotBottom.setDataset(emptyDataset("Empty 2"));
}
private XYDataset emptyDataset( String title ) {
TimeSeries ts = new TimeSeries(title);
TimeSeriesCollection tsc = new TimeSeriesCollection();
tsc.addSeries(ts);
return tsc;
}
#Override
public void chartMouseMoved(ChartMouseEvent e) {
System.out.println("Mouse moved!");
}
#Override
public void chartMouseClicked(ChartMouseEvent arg0) {}
public void methodCalledOnceDisplayed() {
JOptionPane.showMessageDialog(null,"Magic!"); //try to comment this line and see the console
chartPanel.repaint();
//now we can get chart areas
this.chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotInfo(0).getDataArea();
this.chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotInfo(1).getDataArea();
}
}
See what happens with and without the JOptionPane.
An explanation of why is this happening would be great.
You may get some insight from the variation below. Note
Swing GUI objects should be constructed and manipulated only on the event dispatch thread (EDT) for the reason suggested here.
The EDT continues to process events, as shown in the example, even while user interaction is limited to the modal dialog.
Invoking repaint() should not be required when using ChartPanel.
Prefer CardLayout or JTabbedPane over manual container manipulation.
Rather than invoking setPreferredSize(), override getPreferredSize(), as discussed here.
Addendum: You have removed the two lines … that are showing the problem.
ChartRenderingInfo is dynamic data that doesn't exist until the chart has been rendered. The modal dialog handles events while the chart is updated in the background; without it, you can schedule your method by wrapping it in a Runnable suitable for invokeLater():
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
myPanel.methodCalledOnceDisplayed();
}
});
A better scheme is to access the ChartRenderingInfo in listeners where you know the data is valid, i.e. listeners implemented by ChartPanel.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CombinedDomainXYPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.Day;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;
/**
* #see https://stackoverflow.com/a/14894894/230513
*/
public class Test extends JFrame {
private JPanel panel;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Test frame = new Test();
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public Test() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final MyJPanel myPanel = new MyJPanel();
panel = new JPanel() {
#Override
public Dimension getPreferredSize() {
return myPanel.getPreferredSize();
}
};
panel.setBorder(new EmptyBorder(5, 5, 5, 5));
panel.setLayout(new BorderLayout());
add(panel);
myPanel.start();
JButton clickme = new JButton("Click me");
clickme.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
panel.removeAll();
panel.add(myPanel, BorderLayout.CENTER);
validate();
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
myPanel.methodCalledOnceDisplayed();
}
});
}
});
panel.add(clickme, BorderLayout.NORTH);
JPanel example = new JPanel();
example.add(new JLabel("Example JPanel"));
panel.add(example, BorderLayout.CENTER);
}
private static class MyJPanel extends JPanel {
private static final Random r = new Random();
private ChartPanel chartPanel;
private JFreeChart chart;
private XYPlot subplotTop;
private XYPlot subplotBottom;
private CombinedDomainXYPlot plot;
private Timer timer;
private Day now = new Day(new Date());
public MyJPanel() {
this.add(new JLabel("Chart panel"));
createCombinedChart();
chartPanel = new ChartPanel(chart);
this.add(chartPanel);
timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
update(subplotTop);
update(subplotBottom);
}
});
timer.start();
}
public void start() {
timer.start();
}
private void update(XYPlot plot) {
TimeSeriesCollection t = (TimeSeriesCollection) plot.getDataset();
for (int i = 0; i < t.getSeriesCount(); i++) {
TimeSeries s = t.getSeries(i);
s.add(now, Math.abs(r.nextGaussian()));
now = (Day) now.next();
}
}
private void createCombinedChart() {
plot = new CombinedDomainXYPlot();
plot.setGap(30);
createSubplots();
plot.add(subplotTop, 4);
plot.add(subplotBottom, 1);
plot.setOrientation(PlotOrientation.VERTICAL);
chart = new JFreeChart("Title",
JFreeChart.DEFAULT_TITLE_FONT, plot, true);
plot.setDomainAxis(new DateAxis("Domain"));
}
private void createSubplots() {
subplotTop = new XYPlot();
subplotBottom = new XYPlot();
subplotTop.setDataset(emptyDataset("Set 1"));
subplotTop.setRenderer(new XYLineAndShapeRenderer());
subplotTop.setRangeAxis(new NumberAxis("Range"));
subplotBottom.setDataset(emptyDataset("Set 2"));
subplotBottom.setRenderer(new XYLineAndShapeRenderer());
subplotBottom.setRangeAxis(new NumberAxis("Range"));
}
private XYDataset emptyDataset(String title) {
TimeSeriesCollection tsc = new TimeSeriesCollection();
TimeSeries ts = new TimeSeries(title);
tsc.addSeries(ts);
return tsc;
}
public void methodCalledOnceDisplayed() {
PlotRenderingInfo plotInfo =
this.chartPanel.getChartRenderingInfo().getPlotInfo();
for (int i = 0; i < plotInfo.getSubplotCount(); i++) {
System.out.println(plotInfo.getSubplotInfo(i).getDataArea());
}
JOptionPane.showMessageDialog(null, "Magic!");
}
}
}
Addendum: One additional iteration to illustrate ChartMouseListener and clean up a few loose ends.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.entity.ChartEntity;
import org.jfree.chart.plot.CombinedDomainXYPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.Day;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;
/**
* #see https://stackoverflow.com/a/14894894/230513
*/
public class Test {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Test t = new Test();
}
});
}
public Test() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final MyJPanel myPanel = new MyJPanel();
f.add(myPanel, BorderLayout.CENTER);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
myPanel.start();
}
private static class MyJPanel extends JPanel {
private static final Random r = new Random();
private ChartPanel chartPanel;
private JFreeChart chart;
private XYPlot subplotTop;
private XYPlot subplotBottom;
private CombinedDomainXYPlot plot;
private Timer timer;
private Day now = new Day(new Date());
public MyJPanel() {
createCombinedChart();
chartPanel = new ChartPanel(chart);
this.add(chartPanel);
timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
update(subplotTop);
update(subplotBottom);
now = (Day) now.next();
}
});
chartPanel.addChartMouseListener(new ChartMouseListener() {
#Override
public void chartMouseClicked(ChartMouseEvent e) {
final ChartEntity entity = e.getEntity();
System.out.println(entity + " " + entity.getArea());
}
#Override
public void chartMouseMoved(ChartMouseEvent e) {
}
});
}
public void start() {
timer.start();
}
private void update(XYPlot plot) {
TimeSeriesCollection t = (TimeSeriesCollection) plot.getDataset();
for (int i = 0; i < t.getSeriesCount(); i++) {
TimeSeries s = t.getSeries(i);
s.add(now, Math.abs(r.nextGaussian()));
}
}
private void createCombinedChart() {
plot = new CombinedDomainXYPlot();
createSubplots();
plot.add(subplotTop, 4);
plot.add(subplotBottom, 1);
plot.setOrientation(PlotOrientation.VERTICAL);
chart = new JFreeChart("Title",
JFreeChart.DEFAULT_TITLE_FONT, plot, true);
plot.setDomainAxis(new DateAxis("Domain"));
}
private void createSubplots() {
subplotTop = new XYPlot();
subplotBottom = new XYPlot();
subplotTop.setDataset(emptyDataset("Set 1"));
subplotTop.setRenderer(new XYLineAndShapeRenderer());
subplotTop.setRangeAxis(new NumberAxis("Range"));
subplotBottom.setDataset(emptyDataset("Set 2"));
subplotBottom.setRenderer(new XYLineAndShapeRenderer());
subplotBottom.setRangeAxis(new NumberAxis("Range"));
}
private XYDataset emptyDataset(String title) {
TimeSeriesCollection tsc = new TimeSeriesCollection();
TimeSeries ts = new TimeSeries(title);
tsc.addSeries(ts);
return tsc;
}
}
}
The JPanel is not visible until Thread.sleep finishes. Why? What am I
doing wrong?
don't block Event Dispatch Thread, Thread.sleep(int) block EDT, Swing GUI waiting untill this delay ended, and all change made during Thread.sleep(int) would not be visible on the screen, use Swing Timer instead, otherwise all changes to the Swing GUI must be wrapped into invokeLater()
Swing is single threaded and all updates to the visible GUI (or stated out of invokeLater) must be done on EDT, more in Concurency in Swing
for better help sooner post an SSCCE, short, runnable, compilable
It seems it is solved thanks to invokeLater:
public void methodCalledOnceDisplayed() {
SwingUtilities.invokeLater( new Runnable() {
#Override
public void run() {
chartPanel.repaint();
chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotInfo(0).getDataArea();
chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotInfo(1).getDataArea();
}
});
}
Now there is no IndexOutOfBoundsException: Index: 0, Size: 0
An explanation of why is this happening would be great
In the last question I was asking the community why my JPopupMenu did not appear on the screen.
I was unable to come up with a simple , runnable, compilable example.
So, here is what I did for you guys:
Is the area too small to draw a popup?
I want my popup to be like this:
The code of what I did is visible in the first photo.
Code:
/* The old code entered here has been removed */
Complete code can be found here
edit 2
I copied the various JRadioButtonMenuItem and the setupJPopup() into a new file and ran. It works. Why doesn't it work in ScreenRecorder class?
Code
package demo;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class PopupTrial {
public PopupTrial(){
setupJPopup();
JFrame frame = new JFrame();
try{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(Exception e){
}
frame.getContentPane().add(label);
label.addMouseListener(new MouseAdapter(){
#Override
public void mouseClicked(MouseEvent e){
popup.show(e.getComponent(), e.getX(), e.getY());
}
});
frame.setVisible(true);
frame.setSize(300, 300);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
new PopupTrial();
}
});
}
public void setupJPopup(){
encodingGroup.add(avi);
encodingGroup.add(quicktime);
popup.add(avi);
popup.add(quicktime);
popup.addSeparator();
recordingAreaGroup.add(entireScreen);
recordingAreaGroup.add(custom);
popup.add(entireScreen);
popup.add(custom);
popup.addSeparator();
cursorGroup.add(selectBlackCursor);
cursorGroup.add(selectWhiteCursor);
cursorGroup.add(selectNoCursor);
selectCursor.add(selectBlackCursor);
selectCursor.add(selectWhiteCursor);
selectCursor.add(selectNoCursor);
popup.add(selectCursor);
popup.pack();
}
JLabel label = new JLabel("Click Me");
ButtonGroup recordingAreaGroup = new ButtonGroup();
ButtonGroup cursorGroup = new ButtonGroup();
ButtonGroup encodingGroup = new ButtonGroup();
JPopupMenu popup = new JPopupMenu();
JRadioButtonMenuItem avi = new JRadioButtonMenuItem("AVI",true);
JRadioButtonMenuItem quicktime = new JRadioButtonMenuItem("QuickTime",false);
JRadioButtonMenuItem entireScreen = new JRadioButtonMenuItem("Entire Screen",true);
JRadioButtonMenuItem custom = new JRadioButtonMenuItem("Custom...",false);
JMenuItem selectCursor = new JMenu("Select a cursor");
JRadioButtonMenuItem selectWhiteCursor = new JRadioButtonMenuItem("White Cursor",true);
JRadioButtonMenuItem selectBlackCursor = new JRadioButtonMenuItem("Black Cursor",false);
JRadioButtonMenuItem selectNoCursor = new JRadioButtonMenuItem("No Cursor",false);
}
No, the size of the JFrame isn't related to why the PopupMenu isn't showing. Here's an example showing something similar to what you want (and using similar methods) working:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PopupMenu extends Box{
Dimension preferredSize = new Dimension(400,30);
public PopupMenu(){
super(BoxLayout.Y_AXIS);
final JPopupMenu menu = new JPopupMenu("Options");
for(int i = 1; i < 20; i++)
menu.add(new JMenuItem("Option" + i));
JLabel clickMe = new JLabel("ClickMe");
clickMe.setAlignmentX(RIGHT_ALIGNMENT);
clickMe.addMouseListener(new MouseAdapter(){
#Override
public void mouseClicked(MouseEvent e) {
menu.show(e.getComponent(), e.getX(), e.getY());
}});
add(clickMe);
}
public Dimension getPreferredSize(){
return preferredSize;
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new PopupMenu());
frame.validate();
frame.pack();
frame.setVisible(true);
}
}