I have a main JFrame and three java class that contains different pie charts and these piechart are in panel. I want to call the three pie classes in main jframe. How can l do that?
// I have three of these Chart classes creating different charts inside panels
public class PiePanel extends Observer {
Singleton connCC = Singleton.getInstance();
Connection con = null;
Statement stm = null;
PiePanel(Subject s) {
panel = new JPanel();
sub = s;
}
#Override
public void update() {
try {
con = connCC.getDBconnection();
stm = con.createStatement();
ResultSet rs = stm.executeQuery("Select pet_name as pet, count(pet_ID) AS 'count' from Pet group by pet_name");
DefaultPieDataset dataset = new DefaultPieDataset();
while (rs.next()) {
dataset.setValue(rs.getString("pet"), Integer.parseInt(rs.getString("count")));
}
JFreeChart pieChart = ChartFactory.createPieChart("Header", dataset, true, true, false);
PiePlot plot = (PiePlot) pieChart.getPlot();
plot.setSimpleLabels(true);
PieSectionLabelGenerator gen = new StandardPieSectionLabelGenerator(
"{0}: {1} ({2})", new DecimalFormat("0"), new DecimalFormat("0%"));
plot.setLabelGenerator(gen);
panel.add(new ChartPanel(pieChart) {
#Override
public Dimension getPreferredSize() {
return new Dimension(335, 235);
}
});
panel.validate();
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
}
}
//below is a class that puts all the panels inside a list
public class Subject {
private List<Observer> panel = new ArrayList<Observer>();
public Subject(){
panel.add(new BarPanel(this));
panel.add(new AreaPanel(this));
panel.add(new PiePanel(this));
}
public List<Observer> getChart(){
return panel;
}
}
//main
public class Main {
public static void main(String[] args) {
Subject s = new Subject();
while (true) {
String input = JOptionPane.showInputDialog(null, "Input value:");
if ("d".equals(input) || "w".equals(input)) {
try {
//String value = Integer.parseInt(input);
s.setState(input);
} catch (Exception e) {
System.exit(0);
}
} else {
System.out.println("Wrong Input!");
System.exit(0);
}
}
}
}
Now i want to pass this list in another JFrame class just as in the picture.
Your problem is that you're adding three components in a default fashion to a container that uses BorderLayout, and this results in each added component in the BorderLayout.CENTER covering all the other components added previously. If you want to display three components you can:
Use BorderLayout constants to add the components to different locations within the BorderLayout-using container, or
use a different layout, here perhaps a GridLayout(3, 1), or
if you want a more complex GUI that shows more components, then nest JPanels, each using its own layout manager.
For example, if you want to display the pie charts to the side for instance, then I'd put them into a JPanel that uses a GridLayout, and then add that GridLayout using JPanel to the BorderLayout-using main GUI in the BorderLayout.LINE_END position, or whatever location you desire.
If on the other hand your goal is to swap out one JPanel for another in response to an event, then use a CardLayout to allow easy and efficient swapping of components.
Related
I am writing a program where I need to open a JFrame if a button is clicked. I set the default close operation to Dispose_on_close so that when I close the window the program doesn't shutdown completely.
In the frame that will be opened, i want to put a JTable, so I wrote two methods, a createFrame() method and a mechanicListTableProperties() which is the method that creates the JTable and adds elements to it. I then call the mechanicListTableProperties inside the createFrame() and the createFrame inside the actionPerformed() method. When I open the frame 1 time, the table is shown inside the window, but if I close and reopen the frame, the table is also readded and I see 2 tables, when I am trying to just see the one table again. Here is my source code:
public class SeeMechanicsButtonHandler implements ActionListener {
JFrame mechanicListFrame;
boolean isOpen = false;
JTable mechanicListTable;
JPanel tablePanel = new JPanel(new GridLayout());
JScrollPane sp;
List<String> names = new ArrayList<String>();
String[] namesArray;
public void createFrame() {
mechanicListFrame = new JFrame();
mechanicListFrame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
mechanicListFrame.setSize(new Dimension(500,500));
mechanicListFrame.add(tablePanel);
mechanicListFrame.setVisible(true);
//Prevents the window from being opened multiple times
mechanicListFrame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e) {
isOpen = false;
}
});
}
public void mechanicListTableProperties(){
mechanicListTable = new JTable(){
public boolean isCellEditable(int row, int column) {
return false;
}
};
DefaultTableModel model = new DefaultTableModel();
model.addColumn("Nome", namesArray);
//Creates a column with title as Nome and lines as the array
mechanicListTable.setModel(model); //adds column to the the table
mechanicListTable.setBounds(30, 40, 200, 300); //table size
mechanicListTable.setFont(new Font("Arial Rounded MT", Font.BOLD, 15));
// adding it to JScrollPane
sp = new JScrollPane(mechanicListTable);
tablePanel.add(sp);
}
public void actionPerformed(ActionEvent e) {
if(!isOpen) {
try {
//SQL code to get the data from mechanics table
ResultSet rs = ServerConnection.createQueryStatement("SELECT * FROM mechanics");
while (rs.next()){
//loop to add each entry in the table to an array list
names.add(rs.getString("nome"));
}
//creates an array to put the values from the arraylist
namesArray = new String[names.size()];
for (int iterate = 0; iterate < names.size(); iterate++){
//loop that iterates through the arraylist and puts the values in the array
namesArray[iterate] = names.get(iterate);
System.out.println(namesArray[iterate]);
//prints to the console for testing purposes
}
} catch (SQLException e1) {
e1.printStackTrace();
}
createFrame();
isOpen = true;
}
}
}
I want to build a bingo got the following source code, which should create a JFrame with 25 buttons placed in a 5x5 matrix. But none of my button gets drawn on the window in any kind.
I ve created a Jpanel on which the buttons are placed, the locations and such are not specific, finetuning will come later, first thing is to even get them drawn on the window.
Bingo Buttons is a class which extends JFrame and simply adds two methods, one to toggle its status from true to false and the other way around and also an method (isSet) to check if the buttons is currently true or false.
bingoField is an String Array which holds nothing but the data which the buttons should get.
I dont get why it does nothing, please help me out. Any kind of help is highly appreciated!
public class BingoFrame extends JFrame {
public static final int BINGOSIZE=25;
public static final int BUTTON_X=50;
public static final int BUTTON_Y=50;
public BingoFrame() {
setResizable(false);
String[] bingoField = null;
BingoButton[] buttons=new BingoButton[25];
try {
bingoField = Utils.getRandomBingoField("Test");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
this.setTitle("BS Bingo");
this.setResizable(false);
this.setLocation(50, 50);
this.setSize(600, 800);
this.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
getContentPane().setLayout(null);
JPanel buttonPanel = new JPanel();
buttonPanel.setBounds(0, 0, 594, 772);
getContentPane().add(buttonPanel);
buttonPanel.setLayout(null);
for(int i=0;i<BINGOSIZE;i++) {
buttons[i] = new BingoButton("Text");
}
//decorate buttons and add an action listener
for(int i=0;i<BINGOSIZE;i++) {
final BingoButton temp = buttons[i];
temp.setText(bingoField[i]);
temp.setBackground(Color.white);
temp.setForeground(Color.blue);
temp.setPreferredSize(new Dimension(BUTTON_X,BUTTON_Y));
temp.addActionListener(new ActionListener() {
boolean toggle = false;
#Override
public void actionPerformed(ActionEvent e) {
if (!temp.isSet()) {
temp.setBackground(Color.blue);
temp.setForeground(Color.white);
} else {
temp.setBackground(Color.white);
temp.setForeground(Color.blue);
}
temp.toggle();
}
});
buttons[i]=temp;
}
//set Location for the buttons
for(int i=0;i<5;i++) {
buttons[i].setLocation(100,(50*i)+10*(i+1));
}
for(int i=5;i<10;i++) {
buttons[i].setLocation(160,(50*i)+10*(i+1));
}
for(int i=10;i<15;i++) {
buttons[i].setLocation(220,(50*i)+10*(i+1));
}
for(int i=15;i<20;i++) {
buttons[i].setLocation(280,(50*i)+10*(i+1));
}
for(int i=20;i<25;i++) {
buttons[i].setLocation(340,(50*i)+10*(i+1));
}
//add buttons to the panel
for(int i=0;i<BINGOSIZE;i++) {
buttonPanel.add(buttons[i]);
}
this.setVisible(true);
I got the answer.
I ve changed the Layout of the Panel to Grid Layout. This alligns the buttons just where they should be in a 5x5 matrix and also with the wanted gap between. This makes also the code for the positioning completly obsolete.
By simply changing the Layout to GridLayout all of my Problems were gone.
I want to print multiple label according to the number(no string allowed) you wrote in a text field first. I want it to be dynamical. I want it to change every time you type something in the text field.
So far it can read if it's a number or a string and throw exception if the text doesn't match the requirement.
I've try multiple thing to print multiple Jlabel on the screen, but it didn't work so far.
Here's the code: can you help me?
The main window class
public class MainWindow extends JFrame {
private MainPanel mp = new MainPanel();
public MainWindow()
{
this.setVisible(true);
this.setTitle("Calculateur sur 100");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(200, 400);
this.setLocationRelativeTo(null);
this.setContentPane(mp);
}}
The mainPanel class
public class MainPanel extends JPanel implements ActionListener, MouseListener, KeyListener {
private JTextField tI = new JTextField("Pourcentage");
private JOptionPane jop3 = new JOptionPane();
public MainPanel()
{
this.add(tI);
tI.addKeyListener(this);
tI.addMouseListener(this);
}
//Mathematic calculation
private double onHundred(int tot, int now)
{
return (tot / 100) * now;
}
public void keyReleased(KeyEvent e)
{
boolean ok = true;
try
{
int numbs = Integer.parseInt(tI.getText());
}
catch(Exception s)
{
tI.setText("");
jop3.showMessageDialog(null, "Veuillez entrer seulement des chiffres", "Erreur", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if(ok)
{
System.out.print("Supposed to print");
JLabel[] label = new JLabel[Integer.parseInt(tI.getText())];
for(int i = Integer.parseInt(tI.getText()); i <= 0; i--)
{
label[i] = new JLabel(i + " = " + Math.ceil(onHundred(Integer.parseInt(tI.getText()), i)));
label[i].setVisible(true);
this.add(label[i]);
}
}
}
You MainWindow class should look something like this:
public class MainWindow extends JFrame {
private MainPanel mp = new MainPanel();
public static void main(String[] args) {
new MainWindow();
}
public MainWindow() {
setContentPane(mp);
setTitle("Calculateur sur 100");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
}
Note the order: setContentPane then pack then setVisible. pack replaces setSize as it determines the preferred size of the window based on its components.
I modified your MainPanel class:
public class MainPanel extends JPanel {
private JTextField tI = new JTextField("Pourcentage");
JPanel labelPanel = new JPanel();
public MainPanel() {
setLayout(new BorderLayout());
tI.getDocument().addDocumentListener(new MyDocumentListener());
add(tI, BorderLayout.PAGE_START);
add(labelPanel);
}
private int check() {
int numL;
try {
numL = Integer.parseInt(tI.getText());
} catch (NumberFormatException exc) {
return 0;
}
return numL > 100? 100 : numL;
}
private void update(int numL) {
labelPanel.removeAll();
for (int i = 0; i < numL; i++)
labelPanel.add(new JLabel(String.valueOf(i+1)));
JFrame mainWindow = ((JFrame) SwingUtilities.getWindowAncestor(this));
mainWindow.pack();
mainWindow.repaint();
}
class MyDocumentListener implements DocumentListener {
#Override
public void insertUpdate(DocumentEvent e) {
update(check());
}
#Override
public void removeUpdate(DocumentEvent e) {
update(check());
}
#Override
public void changedUpdate(DocumentEvent e) {
}
}
}
Explanation:
The main panel has the text field separately from another panel which updates dynamically to contain the labels.
The text field uses a DocumentListener instead of a KeyListener to listen to changes in its contents. This is the correct approach for many reasons I will not get into here unless really necessary.
Whenever the text changes, a check method verifies that the input is a number. If it's not it returns 0. If it's more than 100 it returns 100. You can change this behavior as you need.
The value from check is passed to update which clears all the previous labels and reconstructs them. (You can do a bit of optimization here if you want by keeping labels in memory but not displaying them. If the cap is 100 as in my example this won't be noticeable.). The main frame then recalculates the space it needs for all the labels and then repaints.
The labels appear next to each other because the default layout for JPanel is FlowLayout. You can change this as needed.
First - you have Integer.parseInt(tI.getText()) a number of times within the same keyReleased function. When you have done the first check to assign it to int numbs, then use numbs from then on, instead of referring back to tI.getText(). Theoretically the user input can change while you are processing your array, which will cause runtime exceptions or undesired results. Hint - declare numbs directly under ok.
Second - after you add controls programmatically, you need to invalidate the control on to which you are adding them, ie your MainPanel. The invalidate directive tells the control that it is not drawn correctly and needs to be repainted (do this at the completion of your loop). Look through the documentation for JPanel for invalidate and paint.
I have a JPanel inside a Anchor Pane inside a JavaFX project. The problem I'm having is the content that's loaded inside the panel is not confined to the panel and cuts off text once it reaches the edge of the panel instead of moving on to the next line.
This is fine however if I test the panel inside a Jframe.
The Anchor panel was created and placed in the user interface using Scene Builder for JavaFX.
Below is the code where I make labels of ranging font sizes(this is to created a Word Cloud) and place them in a JPanel and then return this panel.
public JPanel nnsePairWordCloud() throws SQLException, InstantiationException, IllegalAccessException {
Database databaseConnection = new Database();
databaseConnection.getConnection();
ResultSet nnsePairs = databaseConnection.getNNSEPairInfoFromDatabase();
ResultSet nnseScores = databaseConnection.getNNSESimilarityResultsFromDatabase();
//adding words from the database to the array that will make up the word cloud
while(nnsePairs.next()) {
String wordPair = nnsePairs.getString(1);
WORDS.add(wordPair);
}
//adding each pairs weighting from the database - this will determine the size of the word
while(nnseScores.next()) {
Double wordResult = nnseScores.getDouble(1);
WEIGHTINGS.add(wordResult);
}
System.out.println("cloud data got");
JPanel panel = new JPanel();
panel.setSize(380, 275);
Cloud cloud = new Cloud();
// cloud.setMinWeight(-1);
//cloud.setMaxWeight(1);
cloud.setMaxTagsToDisplay(300);
//Random random = new Random();
for (int i =0; i<WORDS.size(); i++) {
cloud.addTag(new Tag(WORDS.get(i), WEIGHTINGS.get(i)));
}
for (Tag tag : cloud.tags()) {
final JLabel label = new JLabel(tag.getName());
label.setOpaque(false);
label.setFont(label.getFont().deriveFont((float) tag.getWeight() * 10));
panel.add(label);
}
//frame.add(panel);
//frame.setSize(800, 600);
//frame.setVisible(true);
return panel;
}
And here's the code where the panel is returned to and set - creates a SwingNode first and then loads the content. I had to do it this way so I could load the content in the JavaFX UI.
final SwingNode nodeForWordCloud = new SwingNode();
createAndSetSwingContentForWordCloud(nodeForWordCloud);
wordCloudBox.getChildren().add(nodeForWordCloud);
private void createAndSetSwingContentForWordCloud(final SwingNode swingNode) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
swingNode.setContent(new WordCloud().initUI());
} catch (SQLException ex) {
Logger.getLogger(WordNetPairPageController.class.getName()).log(Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
Logger.getLogger(WordNetPairPageController.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(WordNetPairPageController.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
Figured it out.
If I use a JavaFX FlowPane instead then it solves both the problems I was having. The content now flows within the pane and doesn't cut off and the content loads straight away as its no longer a swing component so it doesn't have to run on a separate thread.
Anyone having similar problems look up how the different layouts in Java FX work as this will help you figure out which one to use. These panels work very differently than they do in Swing.
I have 2 classes.
when I put bold 3 lines in the method addCourses() the dialog does not show combobox in the Panel
but when I remove from addCourses and put those bold lines in the constructor, JComboBox are shown in the Panel.
But data will not show because data items updates to ComboBox will happen after Constructor is created.
How can I solve this problem.
this.mainPanel.add(courseCombo, BorderLayout.NORTH);
this.mainPanel.add(sessionCombo, BorderLayout.CENTER);
this.mainPanel.add(courseButton, BorderLayout.SOUTH);
public class Updator {
CourseListFrame clf = new CourseListFrame();
for(...){
clf.addContentsToBox(displayName, className);
}
clf.addCourses();
}
and second class is
public class CourseListFrame extends JDialog implements ActionListener {
public JPanel mainPanel = new JPanel(new BorderLayout(2, 2));
public JButton courseButton = new JButton(("Submit"));
public JComboBox courseCombo;
public JComboBox sessionCombo;
public Multimap<String, String> map; // = HashMultimap.create();
public static CourseListFrame courseListDialog;
public CourseListFrame() {
super(this.getMainFrame());
this.getContentPane().add(mainPanel);
map = HashMultimap.create();
courseCombo = new JComboBox();
courseCombo.addItem("Select Courses");
courseCombo.addActionListener(this);
sessionCombo = new JComboBox();
}
public void addContentsToBox(String course, String session) {
map.put(course, session);
courseCombo.addItem(course);
}
public void actionPerformed(ActionEvent e) {
JComboBox cb = (JComboBox) e.getSource();
String str = (String) cb.getSelectedItem();
setSessionCombo(str);
}
public void setSessionCombo(String course) {
if (map.containsKey(course)) {
sessionCombo.removeAllItems();
Iterator it = map.get(course).iterator();
while (it.hasNext()) {
sessionCombo.addItem(it.next());
}
}
}
public void addCourses() {
this.mainPanel.add(courseCombo, BorderLayout.NORTH);
this.mainPanel.add(sessionCombo, BorderLayout.CENTER);
this.mainPanel.add(courseButton, BorderLayout.SOUTH);
}
public static void showCourseListDialog() {
if (courseListDialog == null) {
courseListDialog = new CourseListFrame();
}
courseListDialog.pack();
courseListDialog.setVisible(true);
courseListDialog.setSize(260, 180);
}
}
The reason why they arent showing is because you are probably calling the static showCourseListDialog() to show your dialog. This method will test whether your static courseListDialog is null, and if so, create one and set that dialog visible, not the clf that you instantiated.
If in your showCourseListDialog() you call the addCourses() method after instantiating your 'singleton', you should be OK:
public static void showCourseListDialog() {
if (courseListDialog == null) {
courseListDialog = new CourseListFrame();
courseListDialog.addCourses();// <<---- this is key!
}
courseListDialog.pack();
courseListDialog.setVisible(true);
courseListDialog.setSize(260, 180);
}
That said, by having the static courseListDialog, it is apparent that you want that dialog to be a singleton. If that is the case, I would at least make your constructor private. You want to proactively avoid the situation that you are getting into where you can construct multiple instances of a singleton. You still would have a race condition to deal with in your showCourseListDialog, but as you will only be calling this method in the EDT, you should be safe.
Take a look at this and other topics on Singleton development in Java (and dont forget to read the con arguments where it is described as an anti-pattern)