-2

I'm working right now on a project java allowing a manager to create a todo list and an employee to view the different ToDo, process and modify by in exemple adding a comment.

The employee's interface should consist of:

  • A lot of JTabbedPane dynamically generated depending on the number of todo in the database.
  • Each JtabbedPane must contain the information of the todo ( title, JTextfield to add a comment, a JTextBox to mark the todo as done and a Jbutton to save our changes.

enter image description here

My problem is that when I generate my JTextfield, etc.. in my different JTabbedPane they all have the same id because I use a while loop as follows:

private void init_employee() {                                                                                      
    try {
        /* create Frame */
        setTitle("SUPTODO Employee");
        setSize(800, 800);
        /* New panel*/
        JPanel topPanel = new JPanel();
        topPanel.setLayout( new BorderLayout() );
        getContentPane().add(topPanel);
        tabbedPane = new JTabbedPane();

        /* Select in my data base */
        Statement stmt = (Statement) ConnectionManager.getConnection().createStatement();
        String sql="SELECT id, title, contenu, comments FROM sup_todo WHERE done = 0";
        ResultSet rset=(ResultSet) stmt.executeQuery(sql);
        while(rset.next())
        {
            /* Get data */
            ToDo todo = new ToDo();
            todo.setId(rset.getLong(1));
            todo.setTitle(rset.getString(2));
            todo.setContenu(rset.getString(3));
            todo.setComments(rset.getString(4));

            /* Create the field */
            panel = new JPanel();
            panel.setLayout(null);

            title = new JLabel(todo.getTitle());
            title.setBounds( 200, 0, 100, 100 );
            contenu = new JLabel(todo.getContenu());
            contenu.setBounds(200, 50, 400, 200 );
            employeeTextFieldToDo = new JTextField();
            employeeTextFieldToDo.setBounds(200,300,400,200);
            employeeCheckBoxToDo = new JCheckBox("Mark as done !");
            employeeCheckBoxToDo.setBounds(200, 500, 200, 100);
            employeeAddCommentToDo = new JButton("Save");
            employeeAddCommentToDo.setBounds(350, 600, 100, 50);
            //employeeAddCommentToDo.setBounds(x, y, width, height);

            /* Action */
            /* Save comments */
            employeeAddCommentToDo.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    /* PROBLEM HERE : Get the text of my last JTextField, not of the JTextField in his JTabbedPane */
                    String comment = employeeTextFieldToDo.getText();
                    JOptionPane.showConfirmDialog(SupTodoEmployeeFrame.this, "Votre commentaire est : " + comment, "comment message", JOptionPane.DEFAULT_OPTION);
                }
            });
            /* Mark as done */
            employeeCheckBoxToDo.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {


                }
            });

            /* add to panel */
            panel.add(title);
            panel.add(contenu);
            panel.add(employeeTextFieldToDo);
            panel.add(employeeAddCommentToDo);
            panel.add(employeeCheckBoxToDo);

            panel.setVisible(true);
            tabbedPane.addTab(todo.getTitle(), panel);
            topPanel.add(tabbedPane, BorderLayout.CENTER);
        }
    } catch (SQLException e1) {
        e1.printStackTrace();
    }        
}

How can I generate my JTexfield, JButton, ... with a unique name so that my action on the save button and on the checkbox will concern the right ToDo, execute the SQL command with on the right row and not the last field with this name.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • *"How to generate dynamically many JTextfield/JButton/... with different id using a loop?"* If you mean for the 'list' then I'd side step the entire problem by keeping a `Vector` and display it in a `JList`. Use a `ListCellRenderer` to ensure each `Task` appears in the list as required. Alternately, just use a `JTable` with columns of each field of the `Task`. – Andrew Thompson Jun 02 '15 at 19:18
  • 1) For better help sooner, post an [MCVE](http://stackoverflow.com/help/mcve) (Minimal Complete Verifiable Example) or [SSCCE](http://www.sscce.org/) (Short, Self Contained, Correct Example). 2) Java GUIs have to work on different OS', screen size, screen resolution etc. using different PLAFs in different locales. As such, they are not conducive to pixel perfect layout. Instead use layout managers, or [combinations of them](http://stackoverflow.com/a/5630271/418556) along with layout padding and borders for [white space](http://stackoverflow.com/a/17874718/418556). – Andrew Thompson Jun 02 '15 at 19:27

3 Answers3

1

Consider creating UI variables that are local in scope to the while method. If you need to reference them from within an anonymous class (eg the ActionListener implementation), mark them as final (be sure to remove the other variable declarations). For example

final JTextField employeeTextFieldToDo = new JTextField();
final JButton employeeAddCommentToDo = new JButton("Save");
...
employeeAddCommentToDo.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        String comment = employeeTextFieldToDo.getText();
        JOptionPane.showConfirmDialog(SupTodoEmployeeFrame.this, "Votre commentaire est : " + comment, "comment message", JOptionPane.DEFAULT_OPTION);
    }
});
Community
  • 1
  • 1
copeg
  • 8,290
  • 19
  • 28
0

I would consider using arrays or ArrayLists of JTextFields, JButtons, etc. I have used them for a software project myself and did so comfortably.

Rezwan Azfar Haleem
  • 1,198
  • 13
  • 23
0

To solve your problem I would suggest the following way. Create a class TodoPanel extending JPanel. This class renders a ToDo and retrieves the data using a construtor param - the sample implementation uses your components and settings without "improving" certain aspects:

class ToDoPanel extends JPanel {

  private JLabel title;
  private JLabel contenu;
  private JTextField employeeTextFieldToDo;
  private JCheckBox employeeCheckBoxToDo;
  private JButton employeeAddCommentToDo;

  public ToDoPanel(ToDo todo) {
    setLayout(null);

    title = new JLabel(todo.getTitle());
    title.setBounds(200, 0, 100, 100);
    contenu = new JLabel(todo.getContenu());
    contenu.setBounds(200, 50, 400, 200);
    employeeTextFieldToDo = new JTextField();
    employeeTextFieldToDo.setText(todo.getComments());
    employeeTextFieldToDo.setBounds(200, 300, 400, 200);
    employeeCheckBoxToDo = new JCheckBox("Mark as done !");
    employeeCheckBoxToDo.setBounds(200, 500, 200, 100);
    employeeAddCommentToDo = new JButton("Save");
    employeeAddCommentToDo.setBounds(350, 600, 100, 50);

    /* Action */
    /* Save comments */
    employeeAddCommentToDo.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        String comment = employeeTextFieldToDo.getText();
        // JOptionPane.showConfirmDialog(, "Votre commentaire est : " + comment, "comment message", JOptionPane.DEFAULT_OPTION);
        System.out.println("Hello " + comment);
      }
    });
    /* Mark as done */
    employeeCheckBoxToDo.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        // nothing
      }
    });

    /* add to panel */
    add(title);
    add(contenu);
    add(employeeTextFieldToDo);
    add(employeeAddCommentToDo);
    add(employeeCheckBoxToDo);

    setVisible(true);
  }

}

Now your Frame containing the JTabbedPane can look provide a method getting a List of ToDo items (should be separated from this class but for keeping it short it is inside). Loop through the list and create per ToDo a new ToDoPanel. Afterwards add it to as a tab:

public class Main extends JFrame {

  public static void main(String[] args) {
    Main frame = new Main();
    frame.setTitle("SUPTODO Employee");
    frame.setSize(800, 800);

    List<ToDo> todos = frame.getTodos();

    JPanel topPanel = new JPanel();
    topPanel.setLayout(new BorderLayout());
    frame.getContentPane().add(topPanel);
    JTabbedPane jTabbedPane = new JTabbedPane();

    for (ToDo toDo : todos) {
      ToDoPanel panel = new ToDoPanel(toDo);
      jTabbedPane.addTab(toDo.getTitle(), panel);
    }
    topPanel.add(jTabbedPane, BorderLayout.CENTER);

    frame.setVisible(true);
    frame.addWindowListener(new WindowAdapter() {
      @Override
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }

  /**
   * Get data from database as a list of ToDos
   * 
   * @return
   */
  private List<ToDo> getTodos() {
    // example data - HERE goes your SQL query etc.
    return Arrays.asList(new ToDo(1L, "Title", "Text", "Comments"), new ToDo(2L, "Title2", "Text2", "Comments2"));
  }

}

Now, every ToDo is rendered by its own panel, has separate listeners and can be managed differently. But please consider also the comments Andrew Thompson wrote.

swinkler
  • 1,703
  • 10
  • 20