Dispose_on_Close closes JFrame but it is still active - java

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;
}
}
}

Related

How to change selected index in JComboBox when refreshing panel?

I am making a simple sudoku and when I want to start a new game, I reload the panel. I first remove it and then add it to the frame. The problem is that I can choose the difficulty for new game, but it always selects the first "Easy" dificulty, not selected. So if I change it in JComboBox to "medium", when page is reloaded it will load the game with "Easy", not "medium".
What should I do so my refreshed panel will accept changed difficulty?
Here are methods that are used for this in my program:
JComboBox difficulty = new JComboBox();
DefaultComboBoxModel difficultyModel = new DefaultComboBoxModel();
difficultyModel.addElement("Easy");
difficultyModel.addElement("Medium");
difficultyModel.addElement("Hard");
difficulty.setModel(tezavnostModel);
difficulty.setSelectedIndex(0);
difficulty.setPreferredSize(new Dimension(100, 25));
newGame.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
mainFrame.reloadSudokuBoard();
sudokuBoard.pickDifficulty(getDifficulty()));
}
});
public String getDifficulty() {
return (String)difficulty.getSelectedItem();
}
public void board(int[][] numbers, int zeros) {
int numberZeros = setDifficulty(sudokuForm.getDifficulty());
int[][] boardNumbers = gameNumbers();
public void reloadSudokuBoard() {
String newDifficulty = (sudokuForm.getDifficulty());
remove(sudokuBoard);
sudokuBoard.board(sudokuBoard.gameNumbers(), sudokuBoard.setDifficulty(newDifficulty ));
add(sudokuBoard, BorderLayout.WEST);
SwingUtilities.updateComponentTreeUI(sudokuBoard);
}
Hope this helps.
public void reloadSudokuBoard() {
int index = difficulty.getSelectedIndex();
String newDifficulty = (sudokuForm.getDifficulty());
remove(sudokuBoard);
sudokuBoard.board(sudokuBoard.gameNumbers(), sudokuBoard.setDifficulty(newDifficulty ));
add(sudokuBoard, BorderLayout.WEST);
SwingUtilities.updateComponentTreeUI(sudokuBoard);
difficulty.setSelectedIndex(index);
}
Before removing components, you can use the getSelectedIndex to get the index that was selected. After the element have been added, the setSelectedIndex will fix it

Variable has strange behaviour when using event listener on JTable (Java with swing)

Would really appreciate some help.
Short version Basically I can call a method with a hardcoded string as argument, but I can't use one specific global string variable (even though I can print it and checked that it is a string, and it is recognised)
Long version:
So I'm trying to get a function to work in a basic bank application and this drives me absolutely nuts.
I have classes for the logic of the bank, customers, and accounts. It's working as intended. The problem lies in the Gui class.
I'm using JTable to show the list of customers. Each customer has a personal number that I store in a global variable. I use this variable as an argument for the methods I'm calling. For example bank.findCustomer(personalNumber).
I can print the current selected personal number each time I click on a row in the table. That works fine. I have checked that it's indeed a string. But as soon as I create a Customer object to change the name (using a method from the customer class), I can't use the global variable of the selected personal number.
It seems so strange that I can hardcode the string but I can't pass the variable string.
My guess is that the string is somehow "locked up" in a synchronous(?) event or that the even listeners are in conflict. I have tried 1000 different things to get it to work. It feels like I'm bashing my head against a the wall...
I get the null-pointer exception when trying to call customer.setName() inside the actionPerformed method. If I use it outside this method, it works?
Here is the code:
class Gui implements ActionListener {
private BankLogic bank;
private JFrame frame;
protected JTable table;
protected JMenuBar menuBar;
protected JMenu mainMenu, customerMenu, accountMenu;
protected JPopupMenu popupMenu;
protected JMenuItem addCustomerItem, removeCustomerItem, editCustomerItem, showCustomersItem,
createSavingsAccountItem, createCreditAccountItem, showAccountsItem,
removeAccountItem, depositToAccountItem;
protected JButton refreshButton;
protected DefaultTableModel defModel;
String pNumOfCustomerSelected;
protected int accNumOfAccountSelected;
private JScrollPane scroll;
private ArrayList<String> customerDataList;
protected String test = "14";
Gui() {
bank = new BankLogic();
// dummy customers
bank.createCustomer("Donald", "Duck", "12");
bank.createCustomer("Dauda", "Dabo", "14");
bank.createSavingsAccount("12");
bank.createCreditAccount("12");
// for testing
pNumOfCustomerSelected = "12";
// === MAIN MENU === //
// Item for menu
addCustomerItem = new JMenuItem("Add customer");
addCustomerItem.addActionListener(this);
// Menu to hold items
mainMenu = new JMenu("Menu");
// Menu bar to hold menu
menuBar = new JMenuBar();
// Install components
mainMenu.add(addCustomerItem);
menuBar.add(mainMenu);
// === POPUP MENU === //
// Items for popup menu
editCustomerItem = new JMenuItem("Edit customer name(s)");
editCustomerItem.addActionListener(this);
// Popup menu
popupMenu = new JPopupMenu();
// Install compeonents
popupMenu.add(editCustomerItem);
// === TABLE === //
// Model for table
defModel = new DefaultTableModel();
defModel.addColumn("First name");
defModel.addColumn("Last name");
defModel.addColumn("Personal number");
// Table
table = new JTable(defModel);
fillTable();
// Scroll feature for table
scroll = new JScrollPane(table);
// refresh button
refreshButton = new JButton("Refresh");
refreshButton.addActionListener(this);
// Install popup menu
table.setComponentPopupMenu(popupMenu);
// Install mouse listener
table.addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent me) {
pNumOfCustomerSelected = (String) table.getValueAt(table.getSelectedRow(), 2);
System.out.println(pNumOfCustomerSelected); // works fine
}
});
// === MAIN FRAME === //
// Main frame
frame = new JFrame("Bank application");
// Layout for frame
frame.setLayout(new BorderLayout());
// Install components to frame
frame.add(scroll, BorderLayout.CENTER);
frame.add(refreshButton, BorderLayout.SOUTH);
frame.setJMenuBar(menuBar);
// Settings for main frame
frame.setSize(400, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
/**
* Fills the customer table with data
*/
public void fillTable(){
customerDataList = bank.getAllCustomers();
// Filling the table with rows (of customer info)
for(int i = 0; i < customerDataList.size(); i++){
String customerInfo = customerDataList.get(i);
String[] customerInfoComponents = splitString(customerInfo);
Vector row = new Vector();
row.add(customerInfoComponents[0]);
row.add(customerInfoComponents[1]);
row.add(customerInfoComponents[2]);
defModel.addRow(row);
}
}
/**
* Clears the table rows
*/
public void clearTable(){
int rowCount = defModel.getRowCount();
if(rowCount > 0) {
for (int i = 0; i < rowCount; i++) {
defModel.removeRow(0);
}
}
}
/**
*
* #param stringForProcess customer info
* #return an array of the words in the string (separated by " ")
*/
String[] splitString(String stringForProcess){
return stringForProcess.split("\\s+");
}
// action listener
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == addCustomerItem)
new AddCustomerWindow(bank, "Add customer");
else if(e.getSource() == refreshButton){
clearTable();
fillTable();
}
else if(e.getSource() == editCustomerItem){
Customer cust = bank.findCustomer(pNumOfCustomerSelected);
// Customer customer = bank.findCustomer("12"); // This works fine???
customer.setName("name"); // nullpointer
customer.setSurName("surname");
}
}
}

Why do my buttons wont show up?

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.

how to use for loop in a JButton

public void init(GUI gui){
// the class extends Jframe
gui.setSize(1024, 700);
gui.setPreferredSize(new Dimension(1024, 700));
gui.setResizable(false);
gui.setLocationRelativeTo(null);
gui.setTitle("Student Management System");
gui.setDefaultCloseOperation(EXIT_ON_CLOSE);
Admin_AllStudents_pnl=new JLayeredPane();
Admin_AllStudents_pnl.setSize(1024,700);
Admin_AllStudents_pnl.setLayout(null);
Admin_AllStudents_pnl.setVisible(false);
Admin_AllStudents_pnl.setOpaque(true);
// Admin_AllStudents_pnl.setBackground(Color.white);
String col[]={"ID","Name","Password","Cell","Adress"};
DefaultTableModel tablemodel=new DefaultTableModel(col,0);
All_Students=new JTable(tablemodel);
view_all=new JButton("View_All");
Admin_AllStudents_pnl.add(view_all);
view_all.setBorder(null);
view_all.setBounds(10,10,view_all.getPreferredSize().width,view_all.getPreferredSize().height);
view_all.addActionListener(new ActionListener(){
#Override
// Student and admin are both classes s gets an array list from the admin of all //the students.
//i need to display them in a table format so using for loop.
public void actionPerformed(ActionEvent ae) {
ArrayList<Student> s=new ArrayList<>();
s=admin.AllStudent();
System.out.println("size of s arraylist"+s.size());
for(int i=0;i<s.size();i++)
{
String Ids=s.get(i).getId();
String names=s.get(i).getName();
String passwords=s.get(i).getPass();
String cells=s.get(i).getCell();
String adresss=s.get(i).getAdress();
Object[] data={Ids,names,passwords,cells,adresss};
tablemodel.addRow(data);
}
}
});
Admin_AllStudents_pnl.add(All_Students);
gui.add(Admin_AllStudents_pnl);
only the for loop is not working whole code works fine without for loop every variable is already declared the code is about of 1000 lines so i cant upload all of it.

Displaying JPanel to JFrame another class

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.

Categories

Resources