I have a weird Problem with my Java GUI.
I can access the Methods in the Main Class from another Class but i cannot access the Swing Components.
Let me show you how i built the whole thing
Main Class:
public class GUI extends JFrame {
static Code c = new Code();
static Draw panel = new Draw();
JTextArea codelog;
JLabel lblFile;
...
...
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
GUI frame = new GUI();
frame.create();
}
});
}
public void create() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(1280,720);
...
...
contentPane = new JPanel();
setContentPane(contentPane);
contentPane.setBackground(Color.DARK_GRAY);
GridBagLayout gbl_contentPane = new GridBagLayout();
setResizable(false);
...
...
panel.setBackground(Color.BLACK);
gbc_panel.fill = GridBagConstraints.BOTH;
gbc_panel.gridx = 1;
gbc_panel.gridy = 1;
contentPane.add(panel, gbc_panel);
codelog = new JTextArea();
codelog.setEditable(true);
JScrollPane scrollPane_1 = new JScrollPane(codelog);
codelog.setLineWrap(true);
scrollPane_1.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
codelog.setVisible(true);
scrollPane_1.setVisible(true);
GridBagConstraints gbc_scrollPane_1 = new GridBagConstraints();
gbc_scrollPane_1.gridheight = 2;
gbc_scrollPane_1.gridwidth = 4;
gbc_scrollPane_1.fill = GridBagConstraints.BOTH;
gbc_scrollPane_1.gridx = 8;
gbc_scrollPane_1.gridy = 1;
contentPane.add(scrollPane_1, gbc_scrollPane_1);
...
...
}
public void refresh(){
panel.repaint();
}
}
I am using static Code c
and static Draw panel
to avoid multiple instances as i also have to create Objects of the Main class in other classes.
The other Class named Code
public class Code {
...
...
static GUI g = new GUI();
String test;
...
...
public void hpgl(){
g.codelog.append(test); // gives me nullPointerException !!
g.refresh // works
...
...
}
}
The Problem is that i can access the Methods of the Main Class (GUI) from other classes (such as Code) but i cannot access the Components (such as JTextArea).
The refresh()
Method in the Main Class proves it. I can access the Method and in the Main Class the repaint()
works. But if i try to repaint from another class using GUI.panel.repaint()
it won't work because i would in that case access the panel
directly from Code Class.
The Same goes for the JTextArea. I am trying to append codelog
from Code but it won't let me do it. If i create a Method in Main Class which appends the Textarea and then call the Method from Code Class it works. But using g.codelog.append(test)
gives me a Java null pointer exception
So i can access the Methods but i cannot access the Swing Components.
Can you guys please help me. I don't want to have to write an extra Method in the Main Class for every single Swing Component i want to modify.
Thank You
The UI which is visible on the screen is not the same UI you have created in your Code
class. If you want Code
to be able to access the UI properties, you will need to pass a reference of the GUI
to it.
Having said that, I would be apposed to exposing the UI components directly to any class an instead provide getters and setters (where applicable) to provide access to the information been managed. This prevents rouge classes from making changes to the UI which it should be allowed to do (like remove components)
Depending on what you are doing, an Observer Pattern might be a better choice, where by Code
is notified by GUI
when something it might be interested in changes. If done through the use of interface
s, this will reduce the coupling between your classes and make it more flexible
Beware static
is not a mechanism for providing cross object communication and should be avoid if at all possible, especially in something as dynamic as a GUI.
I was able to solve the Problem following MadProgrammer's Suggestion.
This is what i changed.
I have 3 Classes:
Main Class
Draw
Code
Main Class
public class GUI extends JFrame {
Draw panel = new Draw(this);
Code c = new Code(this);
...
...
}
Code Class
public class Code {
private GUI g;
private Draw b;
public Code(GUI g){
this.g = g;
}
...
...
}
Draw Class
public class Draw extends JPanel{
private GUI x;
private Code c;
public Draw(GUI x){
this.x = x;
}
...
...
}
I removed all the Static declarations. It is now working. I can access the Swing Components in the Main Class now.
Is this the Professional way to do it? or is there still room for improvement. This is the first time i used the passing reference way to do it. Until now i always used static Objects.
Thank You
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.