Example now I have a main frame contains jtable display all the customer information, and there was a create button to open up a new JFrame that allow user to create new customer. I don't want the user can open more than one create frame. Any swing component or API can do that? or how can disabled the main frame? Something like JDialog.
I think you should use this code for the main jframe when you trying to open new one :
this.setEnabled(false);
I would suggest that you make your new customer dialog a modal JDialog so that you do not allow input from other dialogs/frames in your app while it is visible. Take a look at the modality tutorial for details.
Sorry for the late answer but have you considered the Singleton design pattern? It will return the same instance of a class whenever you want the class. So if the user wants a frame to enter the details, there will only be one frame open (same instance)
It goes something like this:
private static MySingleFrame instance = null; //global var
private MySingleFrame() { } //private constructor
private static MySingleFrame getInstance()
{
if(instance == null)
{
instance = new MySingleFrame();
}
//returns the same instance everytime MySingleFrame.getInstance() is called
return instance;
}
just use firstFrame.setVisible(false) on the first frame. This will make it hidden..
if you want a more general approach you could have a reference to the current displayed frame somewhere and change it when a new frame requests to be shown
JFrame currentFrame;
void showRequest(JFrame frame)
{
currentFrame.setVisible(false);
currentFrame = frame;
currentFrame.setVisible(true);
}
You can use:
private void btn_NewFormActionPerformed(java.awt.event.ActionEvent evt) {
this.hide();
new Frm_NewFormUI().setVisible(true);
}
Related
I'm a little ignorant when it comes to events in Java, so I'm working on a project to help rectify that. As such, I am working on a project that is basically a pizzeria POS program. There's the main GUI, with the pre-configured "meal" options. I click on those, and their price and names are displayed in the JTable correctly. However, when I try doing that with a button in a different class, I get no errors and no entries into the JTable.
I'm using NetBeans GUI Builder btw.
This is currently what I have for the MainGUI class:
public class MainGUI extends javax.swing.JFrame {
public void getItems(String extName, double extPrice) {
itemName = extName; //instance variables
itemPrice = extPrice;
getTotal(itemPrice); //displays the total sum of items in textfield
orderTab.setValueAt(itemName, arrayCount, 0); //JTable.
orderTab.setValueAt(itemPrice, arrayCount, 1);
arrayCount++; //so next items clicked can displayed on next row
}
}
and for the other class
public class BuildPizzaGUI extends javax.swing.JFrame {
private void addButtonClick(java.awt.event.ActionEvent evt) {
MainGUI exporter = new MainGUI();
exporter.getItems(custName, custPrice);
setVisible(false); //closes window
}
}
I don't get any errors messages. I want the item name and price to be displayed, but currently, I don't get anything other than a closed window. Thanks.
MainGUI exporter = new MainGUI();
You can't keep creating a new instance of the MainGUI every time you click a button. If you do it means with every item you try to add you create a new JFrame.
Instead you need to pass a reference to the existing MainGUI class when you create your BuildPizzaGUI. Then when you click the button you reference this variable which will allow you to update the JTable in that class.
I have created a form with IntelliJ's GUI builder, it has a working main() method, the form works properly and has some listeners attached.
In addition to that I have a custom class where I want to call that GUI I created with IntelliJ's GUI builder. I can accomplish this by copying the code within the "main" method in the GUI's class and placing it in my custom class and if I run my custom class the form is indeed displayed.
But thats about all I can do with the created GUI, I can only call it. I can't do other things like dispose that GUI form instance (frame.dispose()) and open another form because I don't know how to get access to the frame instance from my custom class.
Can someone please assist me with this? I thought it would save me a lot of time if I used the GUI builder as opposed to writing the GUI code from scratch for several forms.
I solved the problem by creating a method in the GUI form class called load() which contains the JFrame setup
GUI Form Class
public void load()
{
JFrame frame = new JFrame( "Login Form" );
frame.setContentPane( new LoginForm().mainPanel );
frame.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
and then in my main class I called it with new LoginForm().load();.
In order to dispose of the initial GUI form and open another one I created a helper method inside the GUI form class called getMainFrame()
private JFrame getMainFrame()
{
return (JFrame) SwingUtilities.getWindowAncestor( this.mainPanel );
}
after that inside the GUI form class constructor there is logic to dispose of the frame when a condition is met
if (age.equals("42"))
{
//load the appropriate form
new MainForm().load();
//dispose of this current form
this.getMainFrame().dispose();
}
First, give a name to your root panel:
Then create a getter for it, and you can use it in a JFrame by
JFrame f = new JFrame();
f.add(new YourGuiClass().getMainPanel());
f.setVisible(true);
When you want to dispose it, dispose the JFrame instance should work.
Edit
You said you want to dispose the JFrame in your GUI form class logic, try this:
class YourGuiClass {
private JFrame f = new JFrame();
private JPanel mainPanel;
public void load() {
f.add(mainPanel);
f.setVisible(true);
}
public void dispose() {
f.dispose();
}
}
By this you can operate the GUI form class without knowing anything related to Swing in the main function:
public static void main(String... args) {
YourGuiClass myGuiClass = new YourGuiClass();
myGuiClass.load(); // it now shows itself
if (someLogic()) myGuiClass.dispose(); // you can
// also call this elsewhere as you like
}
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.
I'm new to Java and I've hit a brick wall. I want to access GUI components (that have been created in one class) from another class. I am creating a new GUI class from one class, like so;
GUI gui = new GUI();
and I can access the components in that class, but when I go to a different class I cant. I really just need to access the JTextAreas to update their content. Could someone point me in the right direction please, any help is greatly appreciated.
GUI Class:
public class GUI {
JFrame frame = new JFrame("Server");
...
JTextArea textAreaClients = new JTextArea(20, 1);
JTextArea textAreaEvents = new JTextArea(8, 1);
public GUI()
{
frame.setLayout(new FlowLayout(FlowLayout.LEADING, 5, 3));
...
frame.setVisible(true);
}
}
First respect encapsulation rules. Make your fields private. Next you want to have getters for the fields you need to access.
public class GUI {
private JTextField field = new JTextField();
public GUI() {
// pass this instance of GUI to other class
SomeListener listener = new SomeListener(GUI.this);
}
public JTextField getTextField() {
return field;
}
}
Then you'll want to pass your GUI to whatever class needs to access the text field. Say an ActionListener class. Use constructor injection (or "pass reference") for the passing of the GUI class. When you do this, the GUI being referenced in the SomeListener is the same one, and you don't ever create a new one (which will not reference the same instance you need).
public class SomeListener implements ActionListener {
private GUI gui;
private JTextField field;
public SomeListener(GUI gui) {
this.gui = gui;
this.field = gui.getTextField();
}
}
Though the above may work, it may be unnecesary. First think about what exactly it is you want to do with the text field. If some some action that can be performed in the GUI class, but you just need to access something in the class to perform it, you could just implement an interface with a method that needs to perform something. Something like this
public interface Performable {
public void someMethod();
}
public class GUI implements Performable {
private JTextField field = ..
public GUI() {
SomeListener listener = new SomeListener(GUI.this);
}
#Override
public void someMethod() {
field.setText("Hello");
}
}
public class SomeListener implements ActionListener {
private Performable perf;
public SomeListener(Performable perf) {
this.perf = perf;
}
#Override
public void actionPerformed(ActionEvent e) {
perf.someMethod();
}
}
Several approaches are possible:
The identifier gui is a reference to your GUI instance. You can pass gui to whatever class needs it, as long as you respect the event dispatch thread. Add public accessor methods to GUI as required.
Declarations such as JTextArea textAreaClients have package-private accessibility. They can be referenced form other classes in the same package.
Arrange for your text areas to receive events from another class using a PropertyChangeListener, as shown here.
The best option to access that text areas is creating a get method for them. Something like this:
public JTextArea getTextAreaClients(){
return this.textAreaClients;
}
And the same for the other one.So to access it from another class:
GUI gui = new GUI();
gui.getTextAreaClients();
Anyway you will need a reference for the gui object at any class in which you want to use it, or a reference of an object from the class in which you create it.
EDIT ---------------------------------------
To get the text area from GUI to Server you could do something like this inside of Create-Server.
GUI gui = new GUI();
Server server = new Server();
server.setTextAreaClients(gui.getTextAreaClients());
For this you should include a JTextArea field inside of Server and the setTextAreaClients method that will look like this:
JTextArea clients;
public void setTextAreaClients(JTextArea clients){
this.clients = clients;
}
So in this way you will have a reference to the JTextArea from gui.
here i add a simple solution hope it works good,
Form A
controls
Textfield : txtusername
FormB fb = new FormB();
fb.loginreset(txtusername); //only textfield name no other attributes
Form B
to access FormA's control
public void ResetTextbox(JTextField jf)
{
jf.setText(null); // or you can set or get any text
}
There is actually no need to use a class that implements ActionListener.
It works without, what might be easier to implement:
public class SomeActionListener {
private Gui gui;
private JButton button1;
public SomeActionListener(Gui gui){
this.gui = gui;
this.button1 = gui.getButton();
this.button1.addActionListener(l -> System.out.println("one"));
}
}
and then, like others have elaborated before me in this topic:
public class GUI {
private JButton button = new JButton();
public GUI() {
// pass this instance of GUI to other class
SomeActionListener listener = new SomeActionListener(GUI.this);
}
public JButton getButton() {
return button;
}
}
SEE UPDATE AT THE BOTTOM!!
I've tried to figured out how to do this for a couple of days but so far I have had no luck.
Basically what I want to do is have a combobox, which when an option is selected loads an applet, and passes a value to the applet.
Here is the code for the ComboBox class, which is supposed to open the other class in a new window. The other class is the main class for an applet. They are both in the same project but in different packages. I know that there aren't any errors with the rest of the code.
//where I evaluate the selection and then open SteadyStateFusionDemo
// more selections just showing one code block
combo.addItemListener(new ItemListener(){
public void itemStateChanged(ItemEvent ie){
String str = (String)combo.getSelectedItem();
if (str.equals("NSTX")) {
machine = "A";
JFrame frame = new JFrame ("MyPanel2");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
SteadyStateFusionDemo d = new SteadyStateFusionDemo();
frame.getContentPane().add (new SteadyStateFusionDemo());
d.init();
frame.pack();
frame.setVisible (true);
And just to cover everything here is the beginning of the init() method of SteadyStateFusionDemo as well as the main method in the class. Too much code to post otherwise. There are several different privates before the init method.
//method that initializes Applet or SteadyStateFusionDemo class
public void init() {
//main method of the SteadyStateFusionDemo class
public static void main (String[] args) {
JFrame frame = new JFrame ("MyPanel");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add (new SteadyStateFusionDemo());
frame.pack();
frame.setVisible (true);
What am I doing wrong? Why doesn't my class load?
UPDATED: Changed the code so that a JFrame opens and then the JApplet loads inside. I have successfully done this in a test Java applet but for some odd reason it won't work with this Applet. I even set up the test in a similar way (The code for this is virtually the same, except with different class names, and of course a much, much shorter init() method). Can someone help me figure out why this isn't working? Also, a JFrame will open if I delete the lines referring to SteadyStateFusionDemo, but once I reference it won't work. Why does this happen?
UPDATE:
Based on your feedback, it seems you are trying to achieve the following:
Use the code of an existing Applet (found here) in a Desktop application (i.e. in a JFrame).
Converting an Applet to a Desktop application is an "undertakable" task, the complexity of which depends on how much "Applet-specific" stuff is used by the Applet. It can be as simple as creating a JFrame and adding myFrame.setContentPane(new myApplet().getContentPane()); or as complex as...hell.
This tutorial might be a good place to start.
After taking a look at the Applet at hand, it seems to be fairly easy to convert it. The only complicating factor is the use Applet's methods getCodeBase() and getImage(URL) (somewhere in the code). These two methods result in a NullPointerException if the Applet is not deployed as...an Applet.
So, what you can do is override those two methods in order to return the intended values (without the exception). The code could look like this:
/* Import the necessary Applet entry-point */
import ssfd.SteadyStateFusionDemo;
/* Subclass SSFD to override "problematic" methods */
SteadyStateFusionDemo ssfd = new SteadyStateFusionDemo() {
#Override
public URL getCodeBase() {
/* We don't care about the code-base any more */
return null;
}
#Override
public Image getImage(URL codeBase, String imgPath) {
/* Load and return the specified image */
return Toolkit.getDefaultToolkit().getImage(
this.getClass().getResource("/" + imgPath));
}
};
ssfd.init();
/* Create a JFrame and set the Applet as its ContentPane */
JFrame frame = new JFrame();
frame.setContentPane(ssfd);
/* Configure and show the JFrame */
...
The complete code for an example JFrame Class can be found here.
Of course, you need to have all Classes from the original Applet accessible to your new Class (e.g. put the original Applet in your classpath).