I have these two classes:
ConnectionPanel.class
public class ConnectionPanel extends JPanel implements ActionListener,ItemListener, PropertyChangeListener {
private MasterModel m_masterModel;
private JTextField m_keyField;
public ConnectionPanel(MasterModel masterModel) {
m_masterModel = masterModel;
setLayout(new GridLayout(0, 2));
JPanel panel = null;
panel = new JPanel();
panel.add(new JLabel("Type Key:"));
m_keyField = new JTextField(9);
m_keyField.setText("dertfgdertabcdef");
panel.add(m_keyField);
add(panel);
getChatModel().addPropertyChangeListener(this);
getChatModel().setListen(true);
}
public String getEncryptionKey(){
return m_keyField.getText();
}
}
AudioPlayback.class
public class AudioPlayback extends AudioBase {
// and here I want to be able to get
// somehow String key = ConnectionPanel.getEncryptionKey()
// I tried ConnectionPanel panel = new ConnectionPanel(); but does not work
// it messes my graphical interface
// also there is lots of code here too
}
Do you have any ideas how can I get that field input into my audioplayback.class ?
I totally agree with moffeltje & Luke. This question is simple so that I think you can learn something more basic on Java.
But I review your constructor of ConnectionPanel.Excuse me, do you know constructor?
You can find the details here:
https://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html
Now, let's talk about your code. You only give a constructor with one input parameter to ConnectionPanel so that you can't use the constructor without parameters in AudioPlayback.
But the attribute masterModel seems hasn't been called in your ConnectionPanel so that you can roughly use the following code:
// Notice! Don't do this in your production enviroment. It's only for test otherwise you can make sure that you can give the null value to it.
ConnectionPanel panle = new ConnectionPanel(null);
System.out.println(panel.getEncryptionKey());
Related
Why is the setVisible method throwing an error saying symbol not found in my showPanel method?
It does not make sense as I am referencing a JPanel stored in an ArrayList so it should be able to use setVisible.
public class mainFrame extends javax.swing.JFrame {
/**
* Creates new form mainFrame
*/
private ArrayList list;
public mainFrame() {
initComponents();
this.setSize(500,500);
int h=this.getHeight();
int w=this.getWidth();
homePanel homePnl = new homePanel();
this.add(homePnl);
homePnl.setLocation(0,0);
homePnl.setSize(w,h);
homePnl.setVisible(true);
DeploymentInfoPanel infoPanel = new DeploymentInfoPanel();
this.add(infoPanel);
infoPanel.setLocation(0,0);
infoPanel.setSize(w,h);
atomServerPanel atomPnl = new atomServerPanel();
this.add(atomPnl);
atomPnl.setLocation(0,0);
atomPnl.setSize(w,h);
autoDeploymentPanel autoPnl = new autoDeploymentPanel();
this.add(autoPnl);
autoPnl.setLocation(0,0);
autoPnl.setSize(w,h);
list = new ArrayList<>();
list.add(homePnl);
list.add(infoPanel);
list.add(atomPnl);
list.add(autoPnl);
this.pack();
}
public void showPanel(int panelNum){
list.get(1).setVisible(true);
}
private ArrayList list;
You didn't specify the type of Object that will be added to the ArrayList. So by default get() method will return an instance of Object. There is no setVisible(…) method for an Object
When you define the ArrayList you should be using:
private ArrayList<Component> list;
Now the compiler knows you are adding Component instances to the ArrayList.
In fact, the compiler will check to make sure you only add Component.
It will also get rid of the warning messages when you compile.
Also class names should start with an upper case character. Sometimes you do and sometimes you don't:
DeploymentInfoPanel infoPanel = new DeploymentInfoPanel();
...
atomServerPanel atomPnl = new atomServerPanel();
...
autoDeploymentPanel autoPnl = new autoDeploymentPanel();
Notice how the forum highlights properly named classes making the code easier to read?
Follow Java conventions and be consistent.
Finally, to display multiple panels in the same area of the frame you should be using a Card Layout.
Which is better "practice"?:
public JPanel getMyPanel() {
JPanel p = new JPanel;
return p;
}
Or:
private JPanel panel;
public void createPanel() {
panel = new JPanel();
panel.add(etc)
}
Is there a benefit of using instance variables over local variables? Just was curious about the best practices and perhaps if I could improve my way of coding.
There is no best practice in this case.. it all depends on the app you are developing... sometimes you just don't need to create a new JPanel but instead only once in the constructor...
Now if your app needs a new instance of a JPanel then returning a new Object will be ok too.
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 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 interfaces, 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
I have a class which extends JPanel, but it is not working. Would someone tell me how can I solve the issue. It looks like the error is on "super";
This is my class:
public class DivCommentJPane extends JPanel {
private BeanPanel thisBean;
private CommentItem thisComment;
private String pageErrorPrefix="Error On DivCommentJPane.java : ";
private PDFNotesBean bean;
public DivCommentJPane(CommentItem comment ){
//thisBean=bean;
super();
thisComment=comment;
setting();
}
The code below is to add DivCommentJPane into another JPane:
ArrayList<CommentItem>sortComment= lstComment;
Collections.sort(sortComment,CommentItem.sortPage);
for(CommentItem comm: sortComment){
DivCommentJPane d=new DivCommentJPane(comm);
listCommentPane.add(d, BorderLayout.CENTER);
}
Since you are using a BorderLayout, "[e]ach region may contain no more than one component."
Therefore repeated attempts to add to the CENTER region (listCommentPane.add(d, BorderLayout.CENTER); ) will end up replacing what was previously there.
You will have to use a different layout manage instead.