Java GUI internal classse to separate files - java

I am writing a java program which have a big amount of different GUI objects and GUI class file became huge. I wanted to ask if there is a way to separate these internal files in different files and if so, how to do that.
The general structure of the GUI(Runner)class is following
public class Gui extends JFrame{
<componendt definition>
public Gui()
{
<component initialization>
<containers and adding objects to container>
<attaching listeners>
// for example
generate_button.addActionListener(new generate_ButtonHandler());
}
// I want to separate these classes in different files
class generate_ButtonHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
<some suff>
}
}
public static void main(String[] args) {
JFrame f = new Gui();
f.setVisible (true);
f.setDefaultCloseOperation (EXIT_ON_CLOSE);
}
}
Or may be there is another solution how to handle these big files

You could try implement each UI part as separate component, and encapsulate most
code in the component. That will reduce amount of service code.

Related

Changing size of Swing JPanel inside of an Eclipse plugin's ViewPart (despite SwingUtilities.invokeLater(Runnable()))

Today, I am working on an Eclipse plugin project, where I am using the standard SWT_AWT bridge in order to plug my Swing components in:
public class MyView extends ViewPart {
public static final String ID = "HelloRCP.view";
Frame frame;
public void createPartControl(Composite parent) {
Composite composite = new Composite(parent, SWT.EMBEDDED | SWT.NO_BACKGROUND);
this.frame = SWT_AWT.new_Frame(composite);
SwingUtilities.invokeLater(new Runnable() {
private MainPanel swingPanel;
public void run() {
this.swingPanel = new MainPanel();
frame.add(swingPanel);
}
});
this.setResizeListener();
}
public void setFocus() {}
private void setResizeListener() {
this.frame.addComponentListener(new frameResizeListener(this));
}
public Frame getFrame() { return this.frame; }
}
I would like to get the "frameResizeListener" to somehow trigger an update of all subsequent Swing components (e.g. JPanels) constructed by the Swing Runnable instance, this upon the ViewPart's size-change, in order to achieve some kind of responsive design.
Somehow then, the underlying JPanels need to get to know about the ViewPart's Frame size...
I have read my fair share of SO Q&As, and only found the answer that "you need to pass a parameter at construction time". But my problem with this is that my usecase happes once the Components in question are already created and living...
The only solution that I see, so far, seems to break Thread-safety, by writing a shared file or property, and then signalling the Runnable to read it once done.
Can anyone else think of a better option please?
Thank you very much in advance for your support ! :) :)
Regards,
Peter

Proper way to Create a Swing Java Application

I had some previous experience to swing applications at school, so I know how they work and will be fine designing them, but I am unsure of the best way to set my application up.
We only created smaller programs at school so we had almost all of our code in the constructor, but I want to create something larger, and am unsure of how I should set things up.
I have my base class with the constructor that will create my JFrame that I will use throughout the application, but what classes do I make to add my components, or use action listeners? I am unsure exactly of the proper way to do this, so a guiding step would be great.
Here is my class declaration/constructor:
public class SwingApp1 extends JFrame{
public SwingApp1() {
setTitle("Greens Tracker");
setSize(800,500);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
}
Now what do I put in my main, and in what manor should I be adding components?
Any help is appreciated, thanks!
Good way of setting up your JFrame is
public GUI() {
buildGUI();
}
private void buildGUI() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setSize(500, 300);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new GUI().setVisible(true);
}
});
}
I hope it helped :)
The program starts at the main as:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new SwingApp1().setVisible(true);
}
});
}
which can be abbreviated since Java 8 as:
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new SwingApp1().setVisible(true));
}
The JFrame constructor could be as follows. A setVisible I leave to the call,
and pack() will layout the contents.
public SwingApp1() {
setTitle("Greens Tracker");
setSize(800,500);
... add components, maybe in a separate method.
pack();
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
Actually look into MVC, Model View Controller.
I generally maky an XyzApplication class as controller, the JFrame being the main view and the separately kept data (in the application) the model.
It should be mentioned, that JavaFX may be slightly more advisable, say without FXML layout files. A bit more learning involved, but nicer behavior.
Other advise would be to use a build infrastructure like maven. That helps with libraries ("dependencies") and provides "best practices" like build directories (src/main/java, src/test/java, src/main/resources ...).
Of course a version control system like git or mercurial.

How to call a GUI (Swing) from a Class to the Main Class?

I've seen similar questions answered but could not find an answer to my question. I have a Main Class, which has it's own JFrame. However, I've created a different Class where I've created another JFrame that prompts the user for some data. The Main Class is the main app. The secondary class is supposed to pop up before the main class GUI runs. I've created 2 different packages for each one of the Classes.
So, I'm trying to call an Object of the secondary Class from Main Class but the interface does not appear. I do not get any errors in the code and the App runs as if the Object of secondary Class is not being called at all. I am new to Java and would appreciate some lights on this.
My code is as follows:
Main Class
public class TempConverter extends javax.swing.JFrame {
public TempConverter() {
initComponents();
}
// More code
public static void main(String args[]) {
DemoUserData test = new DemoUserData();
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
test.setVisible(true);
new TempConverter().setVisible(true);
}
});
}
Secondary Class
public class DemoUserData extends javax.swing.JPanel {
public DemoUserData() {
initComponents();
}
}
Your JFrame is the main window. Before it is shown at the very early start a splash screen maybe shown, normally a small rectange with a logo.
It however seems, you want some input dialog, like say a login. That cannot be a JPanel, but must be a top-level window: JFrame or JDialog. Or one of the JOptionPane dialogs (asking string input, or whatevever).
Maybe you should make a JFrame for your current JPanel, run that.
.
DemoUserDataFrame test = new DemoUserDataFrame(this);
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
test.setVisible(true);
}
});
public class DemoUserDataFrame extends JFrame {
//private final JFrame tempConverter;
public DemoUserDataFrame(final JFrame tempConverter) {
//this.tempConverter = tempConverter;
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
tempConverter.setVisible(true);
}
});
}
...
}
In the above, closing test, will make the main JFrame visible.
In order to have a better overview, have the classes not refer one to another, you might look into the Model-View-Controller concept. Then there is one global "Controller" class as intermediator for all business logic. It holds the data (Model), and so on.

MVC/MVP and scalability

I've been working on a project while implementing the MVP design-pattern (at least to my knowledge) where i just have my one controller/presenter class which handles all of the actions from UI point of view using inner classes
public class PresenterClass {
public PresenterClass(ViewClass view) {
view.getButtonComponent().addActionListener(new ButtonListener());
view.getMenuItem().addActionListener(new MenuItemListener());
}
class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
//Do some action with the button
}
}
class MenuItemListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
//Do some action with the menu item
}
}
}
Worth it to know that each new class listener is created for any new component that needs it and it isn't just a generic listener for all Buttons, so you can end up with a lot of inner classes which is what is happening in my project. My project isn't massive but it's growing and while i don't think it would be big enough to be completely unmanageable i have thought about how i could handle it if i needed to handle hundreds of different components? So this leads to the question of:
How do you handle large scalability while implementing an MVC or MVP design pattern?

Trouble Adding text to JTextArea (append or settext)

So the program I am making uses 2 threads: One for the GUI and one to do the work.
I want updates from the work thread/class to print out on JTextArea in GUI class.
Everything I tried didn't seem to work. I added lines to print out text on the console right after lines to add text to the JTextArea to make sure it had got to the line but everytime console got text but no changes happened to JTextArea in the GUI.
public static void consoleText(String consoleUpdate){
GUI.console.append(consoleUpdate);
}
I tried this in the work class but nothing happened.
Anyone know how to fix my problem?
Edit:
MAIN.JAVA
public class main {
public static void main(String[] args) {
Thread t1 = new Thread(new GUI());
t1.start();
}
GUI.JAVA
public class GUI extends JFrame implements Runnable{
public static JTextArea console;
private final static String newline = "\n";
public void run(){
GUI go = new GUI();
go.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
go.setSize(350, 340);
go.setVisible(true);
}
public GUI(){
setLayout(new FlowLayout());
console = new JTextArea(ConsoleContents, 15, 30);
add(console);
}
WORK.JAVA
...{
consoleText("\nI want this text on the JText Area");
}
public static void consoleText(String consoleUpdate){
GUI.console.append(consoleUpdate);
}
First, as has been said, your GUI should only run on the Event dispatch thread.
As it is written, your GUI class does two things : it's a frame, and a runnable, and both
are used completely independently. As a matter of fact, calling "run" on a your GUI object creates another, unrelated GUI object. That's probably the reason why you see nothing.
So I suggest making your main the following:
... main(...) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
GUI gui= new GUI();
gui.setVisible(true); // and other stuff
}
});
}
(I would also suggest getting rid of all "static" fields BTW. It's probably the source
of your problems, along with the weird place of the "run" method).
Now, your "consoleText" method, which I assume you call from another thread, should not
modify the text directly, but call SwingUtilities.invokeLater() to do so :
public void consoleText(final String consoleUpdate){
SwingUtilities.invokeLater(new Runnable() {
public void run() {
console.append(consoleUpdate);
}
});
}
(the "final" declaration is important, as it allows the Runnable to use the consoleUpdate variable).

Categories