Search code examples
javaswingjcomboboxresultsetimplements

JComboBox items from ResultSet Issues


I am stuck here and see only one solution which I am trying to refrain from because, it will make my code look messy. I have a JComboBox.addPopupMenuListener in one class. I have another class which implements addPopupMenuListener. In the other class, I extract the items from DB and store them in a List.

I am completely clueless now on how do I add items from this List to JComboBox. Any ideas?

Problem - although I have declared JComboBox combobox; as public I am unable to use this combobox in the implementing class. What do I do? Below is the Code -

package tg.com.bugtracker.loginpage;

import java.awt.*;
import javax.swing.*;

public class LoginPanel extends JPanel {

    public JComboBox<String> combobox;

    public LoginPanel() {
        GridBagLayout layout = new GridBagLayout();
        setLayout(layout);
        GridBagConstraints constraints = new GridBagConstraints();
        constraints.gridx = 1;
        constraints.gridy = 0;
        constraints.insets = new Insets(10,10,10,10);
        constraints.anchor = GridBagConstraints.LINE_START;
        combobox = new JComboBox<>();
        combobox.setPreferredSize(new Dimension(250, 20));
        combobox.addPopupMenuListener(new loginNames());
        add(combobox, constraints);
    }
}

Implementing Class -

package tg.com.bugtracker.loginpage;

import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;

import java.sql.*;
import java.util.List;

public class loginNames implements PopupMenuListener{

    @Override
    public void popupMenuCanceled(PopupMenuEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void popupMenuWillBecomeInvisible(PopupMenuEvent arg0) {
        // TODO Auto-generated method stub

    }

    public List<String> loginNames;

    @Override
    public void popupMenuWillBecomeVisible(PopupMenuEvent arg0) {
        String URL = "jdbc:ucanaccess://C:\\Users\\bharat.nanwani\\Desktop\\BugTrackerDB.accdb";
        ResultSet rs;
        PreparedStatement p;
        String sqlquery = "SELECT FirstName FROM UserDetails;";
        try {
            Connection cnn = DriverManager.getConnection(URL);
            p = cnn.prepareStatement(sqlquery);
            rs = p.executeQuery();
            rs.close();
            p.close();
            while (rs.next()) {
                String names = rs.getString("FirstName");
                loginNames.add(names);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

}

Solution

  • You cannot use combobox in class loginNames because combobox is a member of the LoginPanel class. I'm not sure if you've learned the details of classes and object though, so I will give you two possible fixes and then explain them.

    Here are two fixes:

    1) Change the declaration

    public JComboBox<String> combobox

    to

    public static JComboBox<String> combobox.

    Then use LoginPanel.combobox to access the combobox in the loginNames class.

    2) Add the following constructor to loginNames:

    private LoginPanel login;
    
    public loginNames( LoginPanel login ) {
        this.login = login;
    }
    

    Then, you can access the combobox in loginNames class by typing this.login.combobox.


    A basic concept of classes and objects is that you use classes as a template to create objects. LoginPanel is a class and you create LoginPanel objects with the code new LoginPanel(). Every object (i.e. instance of LoginPanel) will have some variables and methods associated with it. For example, in your not-working code, every LoginPanel object has a unique JComboBox<String> variable named combobox associated.

    The reason why you cannot access combobox from listNames is that listNames does not know what LoginPanel object you are talking about. It knows there is a LoginPanel class, but there can exist 2 or more LoginPanel objects at any given time and those LoginPanel objects will all have different comboboxes.


    In the first fix provided, we added the static keyword to combobox. What static does is that it tells the computer that instead of having a different combobox for each LoginPanel object, we're just going to have one global combobox that all LoginPanel objects will share. More specifically, combobox becomes associated with the LoginPanel class and it is no longer associated with LoginPanel objects. If you do this, there can only be one combobox so you are able to refer to that in the listNames class with the code LoginPanel.combobox.

    For the second fix, recall that we cannot just access combobox from the listNames class because there is a different combobox associated with every LoginPanel object (and more than 1 LoginPanel object may exist). In the second fix, we directly address this problem by passing a reference in the constructor to the specific LoginPanel object we're talking about. By passing this reference, we specify that login is the LoginPanel object we want to modify and it has a unique combobox that we're going to add our list elements to. Therefore, you are able to type login.combobox to access combobox.


    Both fixes are not what would ideally be used. As others have mentioned, Java Swing follows the Model-View-Controller pattern, and so, it is expected that your applications using Java Swing will also use this pattern. The ComboBoxModel class would allow you to achieve this pattern. Adding a static keyword won't give you the Model-View-Controller pattern.

    I looked at your code, and since you didn't fully following Java naming conventions, I figured you might be a bit new to Java and possibly object-oriented programming. Since you may not want to spend a lot of time learning how ComboBoxModel works and changing all your code to follow the Model-View-Controller pattern, I've offered what I hope is a quick alternative that is easier to explain conceptually and will get you the functionality you want.