Parsing data back to mainPanel (java/swing) - java

Set up:
I have a mainPanel with a tabbedPane on it, i have a separate JPanel 'extra', extra creates an objects and i wish to pass that object back through to the mainPanel where i can actually use it/add it to the data structure.
Frame > Panel > TabbedPane > Panel (Separate Class, instantiated as new object)
I tried to add a listener in mainPanel that checks if a boolean in PanelExtra changes and then runs a method etc, but it didn't work.
I would make a method in mainPanel to accept the object but i don't know how to refer back to it. (getRootPane() didn't return anything)
Also im not sure if im using correct terminology, while i was taught Java in a command line Unix environment, Swing is very new to me.
I tried Listeners, Observers and am currently considering an object created at root and passed DOWN through all objects (As java passes by reference, i could pass information back as far as i want) If that isn't an entirely stupid idea, let me know and we can all go about our lives. If there is a better way to do it that'd be great.
(File overview)
[programApp]>[programView>tabbedPane]>[panel]
Panel is created using new, and exists in a separate class.
I want to pass data back from Panel to programView (projectNameView as it is in netbeans)
I will attempt to add as much information as i can.

You can use the MVC-pattern for that.
Actually there are couple of variants depending on your preferences or exact task.
For very simple case you can just use class with static fields to pass objects.
Another way is to define your own listeners like:
private myPanel extends JPanel implements Notification {
...
and where you create that panel:
myPanel.addNotificationReciever(mainPanel);
Later you just call fireNotification or whatever and implement similar listener for your mainPanel.

SirVaulterScoff gave the best answer in my opinion, but I thought I'd add some more (can't add comments yet, so I'm creating a new answer).
You should also read the Observer-Observable pattern (Wikipedia article), which is used along with the MVC pattern. It will be useful when linking your MVC classes together, to make sure everything is as loosely coupled as possible.
As a side comment: MVC is really a pattern you should focus on if you are to create applications with a user interface. It will save you many headaches, and will make your application easier to maintain and extend.

Related

Differences between containers

I have read many different topics and information sources but I can't really understand the differences of containers in java I know JPanel, JFrame and Container are similar and should be used at different levels within the construction of a program and I know there is JWindow and acts relatively the same. I am fairly new to programming so I am just unfamiliar with the setup. Here is what I have found out/assumed about each one, please correct me if i'm wrong.
JPanel is for the integration between JFrame or a Container typically separating different sections for labels, buttons, sliders etc...
JFrame acts as a receiver of JPanels and can construct them based on instructions from the coder, JFrame can also take the same labels, buttons, sliders etc....
Container is the same as JFrame though I am assuming container is a parent of JFrame.
I'm unsure of JWindow I just found out about this one.
Both JPanel and JFrame are Containers, yet more specialized for specific purposes. And yes, you have to assemble them correctly so they act as your user interface.
But as Container does not do much on it's own you probably never put that into your UI directly. Use it as base class to construct more specialized other classes.
To move along get some simple example running, you could follow the Java Tutorials.

Unable to get values from another jFrame

I want to fill values of multiple jTextBox from a jFrame into another, using accessor methods like
String getNameVal()
{
return jTextBox1.getText();
}
How to call these methods from another jFrame?
Suggestions:
It sounds like your GUI code is geared towards making JFrames, and if so, you will want to avoid this. You are painting yourself in a corner by having your class extend JFrame, forcing you to create and display JFrames, when often more flexibility is called for. In fact, I would venture that most of the Swing GUI code that I've created and that I've seen does not extend JFrame, and in fact it is rare that you'll ever want to do this.
More commonly your GUI classes will be geared towards creating JPanels, which can then be placed into JFrames or JDialogs, or JTabbedPanes, or swapped via CardLayouts, wherever needed. This will greatly increase the flexibility of your GUI coding.
This question has direct bearing on your problem. I will guess that your main problem isn't how to give classes getter methods, and how to have other classes call the getter methods. More often then not, when faced with the issue of extracting information from one GUI view to another, the issue is one of when to extract the information. If you displayed your second window as a non-modal JFrame, and then had the calling class immediately extract the data from that second JFrame, you'd get nonsense data, because you'd be extracting data before the user would have time to interact with the 2nd window and enter data.
One possible solution to this when using non-modal windows to get information from the user is to use a WindowListener so you can be notified when the user has completed his dealing with the second window, and so now data can be safely extracted.
Often better is for the 2nd window not be non-modal, as JFrames are, but instead to be a modal window such as a modal JDialog. When the calling code displays a modal dialog, all code flow in the calling code stops until the dialog is no longer visible. In this situation, no WindowListener is needed since you will know exactly when the dialog has been dealt with -- on the code line immediately after you set it visible -- and so can extract your data from it with ease.
A nice variant on this has already been mentioned in by Andrew Thompson in comments -- use a JOptionPane. Don't poo-poo this option since JOptionPanes are powerful tools, likely much more powerful than you realize as they can hold fully formed complex JPanel views, and behave just as described above, as modal dialogs.
If you need more specific help, then please don't hesitate to comment to this answer. Also if so, then consider creating and posting a Minimal, Complete, and Verifiable Example Program where you condense your code into the smallest bit that still compiles and runs, has no outside dependencies (such as need to link to a database or images), has no extra code that's not relevant to your problem, but still demonstrates your problem.
Edit
For my mcve code examples of the above suggestions, please my answers to the following StackOverflow Questions:
Using a modal JDialog to extract information
Using a JOptonPane to extract information
I assume the textfields are present in frame1 and you want to access them in frame2. The following can be a way to achieve this:
First create getters for all JTextFields that you have in your frame1. Alternatively you can have them in a panel and call getComponents() method.
Create a private variable of JFrame type in your frame2.
Modify the constructor of frame2 to receive the frame1 object and assign it to the private variable of JFrame type.
Now you can create a close() method in frame2 which disposes the frame2 and sets frame1 to visible.
But in my opinion you should create a class which handles the data in these textfields. Initialize the class object in any button click of frame1 and check for any inconsistency in the input. I can guess there is something wrong with your design.

Swing desktop app - how to organise my code

We are going to use Swing for our next project which will be a lightweight desktop app.
I've been reading the Swing tutorials on Oracle's website and have started to get the hang of it.
I was told that instead of switching JFrame I need to work within one JFrame and switch JPanels.
My questions to you would be the following.
Can I create the JPanel designs (or their templates) in design mode (WYSIWYG editor) and call jframe.setContentPane(nameOfJPanel) or do I do them programatically in code?
Secondly, how do I structure my code... If I dynamically add new JPanels and bind their events to an event handler.. all my logic and code will be in one HUGE class with tens of methods. I just don't know how to proceed and nowhere can I find an example with multiple (more than 6 let's say) panels on the internet.
To WYSIWYG or not WYSIWYG
This is a debatable question at the best of times.
I encourage all my junior developers to start out hand coding UIs as it teaches them important basics about how to use layout managers and how to handle compound layouts.
This tends to take longer as you need to verify the layout with each change.
I personally use the form editor in Netbeans for most of my general work, but will hand tweak UI's
Structure
Think about boundaries of responsibility, reuse and reduce strategies.
What you don't want is some huge master class that does EVERYTHING. It will be difficult to maintain and update (I live with this horror every day).
Instead, identify the distinct areas of responsibility and either use getters and setters or models to move the data around the application. The more you can decouple your code, the easier it will be to update and modify.
Identify like work and model it as interfaces and abstract classes where you can. Basically where ever you start thinking about coping code is probably a good indication that your design is off and you should consider implementing abstract classes to cover the overlap.
Take advantage of the Action API for replicating commonly used concepts (copy and paste is an example of this. You would want menu items, possible toolbar items and maybe even popup items, these can all be handled by the same Action class).
Separate the data from view. As I said before, take advantage of models. The data shouldn't care how it is collected or modified, only that it can be. Equally, the view shouldn't care about how the data is managed, only that it is.
If possible, define interfaces between the separate areas of your application. This way you can further decouple of the application and no one part becomes reliant on any one implementation (hello my world :P)
Don't be tempted to simply dig through a component hierarchy to gain access to that field, it will produce a nightmare if you need to change the code!!
The JFrame will be the main window of your app and the panels will be the brick composing it.
You should create each panel in its own class and you can arrange them by functionality in packages. You'll have panels for holding content of logical part of your application and panels that contains real stuff.
A logical panel could be the main view and the menu bar. An application panel would be a form, a menu, a canvas...
You'll have to put application panels inside logical panel and to change the content of the logical in response to users actions.
You should study how layouts work in order to compose the view inside the JFrame and to layout components inside panels.
For example the BorderLayout is a classic when defining the main area of an application:
- menu and toolbar on top
- browser on the left
- status bar at the bottom
- main panel on the center
You can use WYSIWYG editor, but avoid doing all design inside the same class. Else you'll have an horrible HUGE class. Create your panels in separate classes and compose them in your main view.
You can use empty panels as placeholder to help you create the structure of your application.
You'll have to bind your domain data to the view in order to not mix the two layer.
Bind means that you will write a way to go from a java bean to a form and the reverse.
Basic binding is handwritten, but some tools exists to do that.
If it is a small application, it is maybe better for you to handwrite everything.
Building a Swing application can be very tricky (you'll have to know about the event dispatch thread, layout management, event management, widgets (label are trivial, but JTable can be very complicated to handle);
I'll recommend to find a book about the topic, and to find some open source swing application in order to study how it structured, before you start your project.
This is how I organize my code:
class Panel1 extends JPanel{
//code for panel1 and its Components
}
class Panel2 extends JPanel{
//code for panel2 and its components
}
// and it follows.
class ApplicationFrame extends JFrame{
/// LOGIC to switch between panels
}
class Main{
//contains main() function
}
Any HAND-CRAFTED GUI code, is better than a COMPUTER GENERATED WYSIWYG -APP Code.

Java/Swing - how to reduce size of JDialog constructor?

I am building a graphical user interface in Java and I was wondering if anyone can give me some directions.
Specifically, When clicking on a button in this GUI a big JDialog (it's a class that extends a JDialog) opens up for the user to enter some information, see some information, click on some things etc.
This class has multiple JLabels and other components in it. My question is how would one create such an instance? Right now I have everything in the constructor, making it a 500(!) lines constructor. There has to be an alternative to that!
The constructor is about 300 lines of code of components placement and settings for them and another 200 lines for the listeners give or take.
Also another question that comes in mind is that right now I open this window from another class by calling
MyClassExtendsJDIalog temp = new MyClassExtendsJDIalog();
but I don't use this "temp" variable at all in the class that I create it, as the constructor of "temp" does EVERYTHING. It seems like I am, again, doing something the wrong way.
Thanks for reading this.
If you want split up the code to make it more readable and manageable you can allways group the fields into subclasses of JPanel, i.e. Panel1, Panel2 etc and then just add those in the JDialog subclass constructor. But setting up a GUI in swing takes a lot of lines, yes...
as for the temp variable not being used, I'm guessing you call show() in the constructor?
Normally I would not do that, but instead call it in the code creating the dialog, ie.
MyDialog dialog = new MyDialog();
dialog.setVisible(true);
Without seeing your code it's difficult to give you specific tips on how to improve your code and design.
I agree, ~500 lines in your constructor intuitively feels like a problem. At a minimum, you might want to defer some of that work until after the instance has been created. Moving this into a init() method (or series of methods) is one approach.
You also might want to consider designing your class such that it contains a JDialog instead of extending one (See Composition over inheritance for a discussion on this topic) I suspect otherwise you are conflating the concerns of several classes.
Finally, you might want to review the Java Swing Tutorial for general tips and techniques for creating Swing based user interfaces.
Yes you are doing something wrong, but you are in good (or bad) company.
You should apply the rules of good OO design and clean code to your swing classes as to anything else.
What exactly you can do is hard to tell without looking at the 300+ lines of code (and I really don't want to see the ;-) but here are somethings that are probably applicable.
My main design rule is the Single Responsibilite Principle. According to your description (and my guesswork), you are doing the following in your constructor:
* creating (including configuring) components
* placing them in some kind of layout
* registering Listeners
* implementing Listners
These are 4 completely different concerns.
After some heavy refactoring you might end up with something like this:
You might want to have a factory that creates your components.
You might have a Layouter class that takes a component or a group of components (like label plus matching textbox) and places them on a panel.
You might have a class takes components (and maybe models or whatever) and wires them together using Listeners.
And a class that gets passed all this uses it in a suitable way and spits out a JDialog with the panel with all your components on.
Note: Idealy nothing extends JDialog anymore. You should only extend Janything if you intend to build a new Swing component.
This example is using Scala but it still should offer some inspiration: http://blog.schauderhaft.de/2011/06/26/clean-code-with-swing-and-scala/

Swing - Organization of JFrames (or JDialogs???) in my program

I have a main controller class that shows a JFrame containing a JTable and, for each row in this table, I have to show a specific "form" on doubleclick.
This secondary window will need information about the specific row selected on the main JTable, as well as some objects saved as fields in the controller class.
An conceptual example of what I need to do is the following:
I have a set of Shops (listed in the JTable in the main JFrame) and, on double click on a row, another window has to appear, allowing for a management of the Shop (sending orders, checking deliveries, etc...).
My question, me being such a newbie with Swing, is: what is the best organization for a common pattern like this one?
Should I model another JFrame and pass as arguments all the data that I could happen to need (I really don't like this), or should I pass only a reference to the Controller class (this would be against the MVC pattern, I think).
Or maybe I should use a JDialog instead of another JFrame? The thing is that, really, the functionality that I need from this second window are a little too big for a dialog, I think...
I am confused, any tip/suggestion/advice will be much appreciated!
Thank you
Regards
Or maybe I should use a JDialog instead of another JFrame?
Bingo.
I actually don't like the idea of having a listener inside my Model class (aka Shop) – implementing the ActionListener. I think I would extend the JDialog class (let’s call it MyJDialog) then when a row is double clicked … create a new instance of MyJDialog class and pass in the Shop object in the constructor. Within the MyJDialog class you can modify the Shop object by calling mutators (setters). Moreover, the Shop class should have a way of notifying observers when a property is changed – take a look at PropertyChangeSupport.

Categories

Resources