How to close JInternal Frame Dynamically when object is created at runtime - java

I am opening a JInternal Frame by getting its name from JTextField
and ** then creates its object at runtime**, the problem is that if I
write 10 times different Internal Frame name in textBox and then click the button it opens the new JInternal Frame everytime.
Now i want whenever a new JInternal Frame is open, the previous
JInternalFrame should be close automatically.
I know it's pretty easy to do that but my case is difficult because of i
create its object at run time, how can i do it.
My code behine the Button is following
private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {
String st = TextField.getText().toString(); // in TextField i enter the JInternal Frame Name
String clazzname = "practice."+st; // practice is the package name
try
{
JInternalFrame obj1 = (JInternalFrame) Class.forName( clazzname ).newInstance();
obj1.setVisible(true);
jPanel1.add(obj1); // now in there i want that whenever i click the button , it check either is there any Jinternal frame is open already or not if yes then close the previously open JFrame
}
catch(Exception e)
{
System.out.println("error "+e);
}
}

I know it's pretty easy to do that but my case is difficult because i creats its object at run time, how can i do it.
There's nothing magical about runtime that makes this any different from how you'd normally close it. The secret is in having a reference to the JInternalFrame readily available. A solution is to use a JInternalFrame field, a non-static instance variable, to hold the reference and not use a local variable as you're currently doing. The key here is to understand that references are what matter, much more so than variables. If you need a reference variable that persists when the method ends, then the variable cannot be declared within the method but should be on class scale.
Something like:
public class MyGui {
// instance field to hold reference to currently displayed JInternalFrame
private JInternalFrame currentInternalFrame = null;
private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {
if (currentInternalFrame != null) {
currentInternalFrame.dispose(); // clear current one
}
String st = TextField.getText().toString(); // in TextField i enter the JInternal Frame Name
String clazzname = "practice."+st; // practice is the package name
try {
// JInternalFrame obj1 = (JInternalFrame) Class.forName( clazzname ).newInstance();
currentInternalFrame = (JInternalFrame) Class.forName( clazzname ).newInstance();
currentInternalFrame.setVisible(true);
jPanel1.add(currentInternalFrame);
} catch(Exception e) {
System.out.println("error "+e);
}
}
}
Note that this code has not been tested and is not here for a copy-and paste solution but to give you a general idea.
Another unrelated issue is on program design: users don't usually like windows opening and closing, and perhaps a better program structure for your user is to swap JPanel views via a CardLayout (please read the CardLayout Tutorial for more on this).

Related

How to transport information from one class to another in order to show it without using static?

I am programming an application that deals with orders from a database. It has several pages, a navigation, a header that always should show information about the actual order you are working with and a content area, in which the details of said order get shown:
My MainProgram extends a JFrame and contains a CardLayout, in which the other pages are hosted, so when the user clicks on the page in the navigation, only the view of the content-area changes. Logo, header and the navigation stay the same. The header keeps displaying the order number.
As there are several different pages that contain details about the same order, I need to "send / transfer" information about the order from one page to the other so I can show some information in the header and in the content area from the order object.
But I am not getting this to work as intended, mostly to my misunderstand of static and when to use it, where objects get created exactly and also the complexity of my program: I am using a class that is intended for the navigation and therefore should also handle
the information transfer from one page to the other.
Since I am using a database, creating a MVCE will be hard, so instead I will show the important parts of my program.
MainProgram.java
Here the navigation and the content panel (centerPanel) get created, also the CardLayout. centerPanel and the CardLayout are static, so I can call this from other classes and switch the page that is shown (probably not a good idea?):
NavigationPanel navigationPanel = new NavigationPanel();
public static JPanel centerPanel = new JPanel();
public static CardLayout contentCardsLayout = new CardLayout();
I create the pages and put them into my CardLayout:
OverviewPage overviewPage = new OverviewPage();
BasicDataPage basicDataPage = new BasicDataPage();
centerPanel.setLayout(contentCardsLayout);
overviewPage.setName("overviewPage");
basicDataPage.setName("basicDataPage");
centerPanel.add(overviewPage, "overviewPage");
centerPanel.add(basicDataPage, "basicDataPage");
The main method, where I create a MainProgram object:
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
MainProgram window = new MainProgram();
window.setVisible(true);
window.initialize();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
OverviewPage.java
The overview page contains a JTable which gets populated from a database. If the user double-clicks an entry, he gets transfered to the BasicDataPage where he can see the details of the order.
But in order to show the details, I need to somehow transfer the information of the order object into the target class and thats the point I am struggling with!
// I tried several things like object into constructor, static object, creating a method etc...
if (mouseEvent.getClickCount() == 2 && row != -1) {
String workNumberOfOrderObject = (String) table.getValueAt(row, 0);
OrderObject orderObject = GetOrderObject.getOrderObjectFromDatabase(workNumberOfOrderObject);
BasicDataPage basicDataPage = new BasicDataPage();
basicDataPage.recieveOrderObject(orderObject);
workNumberPanel.recieveOrderObject(orderObject);
workNumberPanel.setTxtWorkNumber(workNumberOfOrderObject);
MainProgram.contentCardsLayout.show(MainProgram.centerPanel, "basicDataPage");
}
I tried "sending" the order object to the BasicDataPage via the constructor and set the text in the JTextFields in the BasicDataPage accordingly. This did not work, the textfields simply stayed empty altough I can System.out.println(orderObject.toString()) the recieved object.
BasicDataPage.java
I also tried creating a method receiveOrderObject that I use in the OverviewPage, which should set the textfields of the basicDataPage AND the workNumberPanel, but the fields stay empty:
WorkNumberPanel workNumberPanel = new WorkNumberPanel();
JTextField txtCarWidth = new JTextField(TEXTFIELD_LENGTH);
JTextField txtCarDepth = new JTextField(TEXTFIELD_LENGTH);
JTextField txtCarHeight = new JTextField(TEXTFIELD_LENGTH);
public void recieveOrderObject(OrderObject orderObject){
txtCarDepth.setText(orderObject.getCar_depth());
}
Before posting my question I've read several Q/As here on SO like this:
Accessing UUID from another class in Java ... suggesting to use static for global variables.
I know that static variables are class variables, that all instances can use and only one version exists of. So I tried to send a static object from one class to the other.
But since I am using JTextFields, I had to mix static and non-static content, which either did not work at all or the textfields disappeared.
I have the feeling that I am getting a very basic concept in java wrong, so any help, no matter in which direction, is appreciated!
EDIT:
Based on Reşit Dönüks answer, I was able to fill the textfields by making BasicDataPage and loadBasicData(orderObject) in MainProgram static. Now I can do MainProgram.loadBasicData(orderObject); ... and the textfields in the BasicDataPage get filled as intended.
Is this a valid approach or do I get problems for using static for GUI-Elements? ..... Don't!
I realized that, your are creating BasicDataPage in each double click.
if (mouseEvent.getClickCount() == 2 && row != -1) {
String workNumberOfOrderObject = (String) table.getValueAt(row, 0);
OrderObject orderObject = GetOrderObject.getOrderObjectFromDatabase(workNumberOfOrderObject);
BasicDataPage basicDataPage = new BasicDataPage();
This is the main problem. Do not create BasicDataPage there, just reach the created instance and set the order object to that. My solution is below.
public class MainProgram implements OrderView{
//remove statics here
private JPanel centerPanel = new JPanel();
private CardLayout contentCardsLayout = new CardLayout();
private BasicDataPage basicPage;
public MainProgram() {
//other codes
OverviewPage overviewPage = new OverviewPage();
basicPage = new BasicDataPage();
centerPanel.setLayout(contentCardsLayout);
overviewPage.setName("overviewPage");
basicDataPage.setName("basicDataPage");
centerPanel.add(overviewPage, "overviewPage");
centerPanel.add(basicPage, "basicDataPage");
//oher codes
}
#Override
public void loadOrder(OrderObject order) {
basicPage.recieveOrderObject(orderObject);
contentCardsLayout.show(centerPanel, "basicDataPage");
}
}
public interface OrderView {
public void loadOrder(OrderObject order);
}
public class OverviewPage {
OrderView orderView;
public OverviewPage(OrderView orderView) {
this.orderView = orderView;
}
//in ActionPerformed
if (mouseEvent.getClickCount() == 2 && row != -1) {
String workNumberOfOrderObject = (String) table.getValueAt(row, 0);
OrderObject orderObject = GetOrderObject.getOrderObjectFromDatabase(workNumberOfOrderObject);
orderView.loadOrder(orderObject);
workNumberPanel.recieveOrderObject(orderObject);
workNumberPanel.setTxtWorkNumber(workNumberOfOrderObject);
}
}
As pointed already, Singleton is the way to go. I would just like to point out a mistake in the code provided in the answer before.
private static MainFrameinstance = null;
Rename MainFrameinstance to instance or vice-versa; because the same variable is checked by the getInstance() method.

How to return to the class from a jframe in netbeans

I'm new to netbeans. Below is my scenario :
I have created a normal java file in which I'm calling a jframe. jframe have a textbox and submit button.
What I want is that after calling the jframe from the java file, jframe opens up. Then after typing the text in the textbox, when we click on the submit button I should return back to that java file (to the line after I called the jframe) with the text typed. So, that I can use that text in my java file further.
But what is happening now is that when I call the jframe with the below command, jframe opens up and after that rest of the code in the java file gets executed. The java is not waiting for the jframe to return the data.
new Frame1(new javax.swing.JFrame(), false).setVisible(true);
And below is the code in jframe. But don't know how to return it and use it in java file
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String s1 = jTextField1.getText();
argA[0] = s1;
}
So, please let me know how can I do it ?
Thanks to all in Advance
Make two methods,
first one be a main method which create the frame.
second one do the things when Jframe done its work.
and the case
String s1 = jTextField1.getText();
argA[0] = s1;
just write
argA[0] = jTextField1.getText();
make argA as a instance variable then you can call it without to return things.
OR
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
to
private String jButton1ActionPerformed(java.awt.event.ActionEvent evt)
{
return YourStringHere;
}
By the way, by use netbeans, coding via GUI design mode is more easier to learn.

Making a program using a GUI and MySQL database

i have a question regarding a program i am working on. It`s a database manager for a MqSQL db , written in Java. So i have the following program structure.
So i have a main class that extends JFrame, whichh is the main frame of the interface, like this (removed the unecessary code not relevant to the discussion) :
public class MainInterface extends JFrame {
public MainInterface {
................
MainInterface.setLayout(new FlowLayout());
MainInterface.setVisible(true);
TopToolbar toolbar;
try {
toolbar = new TopToolbar();
MainInterface.add(toolbar);
ResultsPanel Results = new ResultsPanel();
MainInterface.add(Results);
} catch (IOException e) {
e.printStackTrace();
}
}
TopToolbar and ResultsPanel are 2 other classes that extend JPanel, the TopToolbar class having a JToolBar with buttonsadded to it (Move Forward, MoveBack, Add entry)
public class TopToolbar extends JPanel implements ActionListener {
TopToolBar()
{
//constructor in which i was adding button to the toolbar, not relevat
}
}
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if (MoveFirst.equals(cmd)){
try {
DatabaseAccess disp = new DatabaseAccess();
disp.getResults();
int id = disp.return_id();
System.out.println(id);
} catch (//exceptions) {
e1.printStackTrace();
}
}
That is the ActionListener event for the next button, which should trigger reading the next entry in the db
DatabaseAccess is another class with initializes the DB connection , and has these 2 methods :
public void getResults() throws SQLException {
Connection con = (Connection) DriverManager.getConnection(URL, user, "")
sql = (Statement) con.createStatement();
result_set = sql.executeQuery("select * from persons");
while (result_set.next()) {
id = result_set.getInt(1);
name = result_set.getString(2);
}
}
public int return_id(){
return id;
}
The return_ID method returns (and it does work) the ID (first key in the database, will obviously add methods for the rest of the entries in the db).
Now i want to show the ID in the final JPanel, the one called ResultsSet (just 3 JLabels and 3 TextFields for the ID , Name etc., in a GridLayout).
Since the dababase class creation (and subsequently the methods forr reading the db and returning the result) is done inside the ActionPerformed method inside the TopToolBar Jpanel, i can`t access it from the MainInterface JFrame and then use something like
ResultsPanel DispResults = new ResultsPanel();
add(DispResults);
DispResults.setID(id_Value)
where setID would be a method in the ResultsPanel that uses the JTextBox setText to set the text .
Hoope i`ve managed to explain my issue as clear as i can.
I disagree with several of your choices.
You should not extend JFrame. Create a JPanel and give it to a JFrame to display.
I would dissociate the database interactions from the Swing UI. Create them as interface-based POJOs on their own, without a UI. Get them tested, written, and working perfectly.
Once the database interactions are perfect, give an instance of that object to the class that controls the application. Give it a text-only interface for driving the database actions.
Once the controller is obeying every text command perfectly, using your fully tested database component, then have it create an instance of your JPanel and give it to a JFrame. It will make the same calls to its controller owner that your text UI has already executed successfully.
Computer science is all about decomposition. You solve big problems by breaking them into smaller ones.
If you'd like to see a great example of what your app might look like, download SQL Squirrel.

How to make program return ID after the button will be pressed?

This program return 0, need to stop/pause program, press button and then return ID.
static int ID=0;
static String log="";
static String pass="";
static SessionFactory factory;
public static int enterStudent(JPanel panel){
panel.setLayout(null);
JLabel jLabel=new JLabel("Login");
panel.add(jLabel);
jLabel.setBounds(10,10,100,30);
JLabel jLabel1=new JLabel("Password");
panel.add(jLabel1);
jLabel1.setBounds(110,10,100,30);
final JTextArea textArea=new JTextArea();
textArea.setBounds(10,50,100,50);
panel.add(textArea);
final JTextArea textArea2=new JTextArea();
textArea2.setBounds(110,50,100,50);
panel.add(textArea2);
JButton enterButton=new JButton("Enter");
enterButton.setBounds(10,100,200,50);
panel.add(enterButton);
try {
factory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
}
ActionListener
enterButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e2) {
log=textArea.getText();
pass=textArea2.getText();
Session session = factory.openSession();
Transaction tx = null;
try{
tx = session.beginTransaction();
List students = session.createQuery("FROM Student").list();
for (Iterator iterator =
students.iterator(); iterator.hasNext();){
Student student = (Student) iterator.next();
if((student.getLogin().equals(log))&&(student.getPassword().equals(pass))){
ID=student.getId();//this should be returned
JOptionPane.showMessageDialog(null,"return="+ID);
break;
}
}
tx.commit();
}catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
}finally {
session.close();
}
}
});
return ID; //returns 0
}
This is function for LogIn, check login and pass in DATABASE. Need return ID of student, but program returns 0
You can't return anything from an ActionListener since its method, actionPerformed(...) is defined to return void, nothing. But fortunately you don't need to. This is a Swing GUI, and inside of your ActionListener, display the ID within a JLabel by calling myLabel.setText(...) or display it elsewhere where it needs to be displayed. Or if you don't want to display it, then call some class's setId(...) method.
Note that the true canonical answer to this question would be to use an M-V-C or Model-View-Control type design pattern, and in your ActionListener (part of the control), set the model's id field to the value found in the database. The GUI should have listeners attached to the model that would update the GUI's state (the data it displays) if the model's state changes. But for your simple program this would probably be a bit of over-kill.
Other side recommendations:
Your code shows a significant over-use of static modifier, and doing this can make it hard to extend or enhance your program, or get it to easily work with other classes.
Your code does not follow Java naming rules, and you will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.
While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
Edit: I now see that you're trying to return an int from the enterStudent method via the JButton's ActionListener. This won't work as written because you're returning the id field before the ActionListener has completed. Solutions include use a callback method of some sort, one that is perhaps passed into your enterStudent's method parameter, or else if you use a modal dialog such as is available with a JOptionPane. Otherwise, based on this increase in complexity, then yes, you're best off using an M-V-C structure which itself is based on use of listeners (callbacks).
That means program control is not reaching this block hence your ID is getting the default defined value which is 0.
if((student.getLogin().equals(log))&&(student.getPassword().equals(pass))){
ID=student.getId();//this should be returned
JOptionPane.showMessageDialog(null,"return="+ID);
break;
}
here the if condition is not getting true which means either of getLogin() and getPassword is not having values as "".

Java: How can I detect the user has finalised their save name without using an actionListener?

Basically I wan't to obtain a string from the user, I have created a class called "frames" in which I have a load of methods such as exitChoice(), infoPop(), ect... I wish to create one called getText(), and this is what I have so far:
public String getText()
{
JDialog textBox = new JDialog(frame, "Save Name", true);
JTextField inputField = new JTextField(18);
inputField.setText(save == null ? "new save" : save.saveName);
textBox.setBounds(width, height, 275, 70);
textBox.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
textBox.setLayout(new FlowLayout());
textBox.setAlwaysOnTop(true);
textBox.setResizable(false);
textBox.add(inputField);
textBox.setVisible(true);
return inputField.getText();
}
now I know this won't work, It simply gets the game stuck and I have to terminate it externally, I also understand why it doesn't work, that isn't the problem, I also know how to add a JButton, an action listener and work it from there,
Basically I am trying to create a clean simple method which obtains a String from the user which is ALL contained within the method.
Ideally I would like to write a line which reads along the lines of
//EDIT: I know the method getText() does exist, sorry if it is misleading, I will ammend it
//String saveName = new JTextField.getText();
String saveName = new JTextInputGetterBoxThing();
but as far as I have found so far this doesn't appear to exist, does anybody have any ideas? or ideally know of a one liner that I have missed?
I think what you want is the JOptionPane.showInputDialog method. Something like this?
public class GetUserInput {
public static String getUserInput() {
return JOptionPane.showInputDialog("Type Something");
}
public static void main(String[] args) {
System.out.println("User Input: " + getUserInput());
}
}
This shows a dialog with the prompt "Type Something" and a text field for entry. Whatever the user types in the text field is returned by getUserInput().
Honestly I'm not sure of having fully understood your problem. Anyway,
here's a tutorial on how to make dialogs properly in Swing.
If you use
int ret = JOptionPane.showOptionDialog(new JDialog(), ...);
Your application main frame input is blocked until the JDialog showed is closed.
If you don't want to use an ActionListener or something similare (DocumentListener, ...) you can force the user to insert a value in the JTextField, press the ok button and the when showOptionDialog return, manually retrieve the text of the JTextField with getText().
EDIT:
I try to extend my answer a little bit.
Extends a JDialog to create the desired dialog:
public class CustomDialog extends JDialog{
private JPanel panel;
private JTextField field;
public CustomDialog(){
panel = new JPanel(); //create a panel possibly with a LayoutManager
field = new JTextField();
}
public JTextField getField(){
return this.field;
}
}
Then show the dialog where you need it, and check the field text when it returns:
CustomDialog dialog = new CustomDialog();
int ret = JOptionPane.showOptionDialog(dialog, ...);
String text = dialog.getField().getText();
public String getSaveName()
{
boolean textGot = false;
String returnText = null;
while (!textGot)
{
returnText = (String) JOptionPane.showInputDialog(hub.frame, "Enter the name of your save:\n", "Save Box",
JOptionPane.PLAIN_MESSAGE, null, null, save == null ? "new save" : save.saveName);
if ((returnText != null) && (returnText.length() > 0))
{
textGot = true;
}
}
return returnText;
}
Here is the final method I am using, much cleaner than the old setup I had which involved creating a tiny frame, and adding a textfield and a button with a listener!

Categories