0

So I'm making a playlist software like itunes or spotify and I'm having trouble with my JTextfields. When I first read the songs the text that is too long over flows to the right like I want. But when I reorder the category by clicking on the detail labels at the top, the over flowing text overflows to the left. I can see the text first overflow to the right and then quickly readjust itself to the left.

Here's where I add each jtextfield to my jpanel, the bug might have something to do with my mouse listener but I'm not sure.

for (final List<JTextField> inner : songTextFields) {
        if (inner.equals(songTextFields.get(songTextFields.size() - 1))) {
            bottom = true;
        }

        for (int i = 0; i < details.size(); i++) {
            final JTextField textField = inner.get(details.get(i));
            textField.setPreferredSize(detailDimensions.get(i));
            textField.setHorizontalAlignment(JTextField.LEFT);

            if (leftSide) {
                if (bottom) {
                    textField.setBorder(BorderFactory.createCompoundBorder(bottomLeftBorder, emptyBorder));
                } else {
                    textField.setBorder(BorderFactory.createCompoundBorder(leftBorder, emptyBorder));
                }
                leftSide = false;
            } else if (bottom) {
                textField.setBorder(BorderFactory.createCompoundBorder(bottomBorder, emptyBorder));
            } else {
                textField.setBorder(emptyBorder);
            }

            textField.setFont(playlistFont);
            textField.setBackground(textFieldBackground);
            textField.setForeground(Color.WHITE);
            textField.setOpaque(true);
            textField.setEditable(false);

            // textField listeners
            final int usedI = i;
            textField.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (e.getClickCount() == 1) {
                        unEditLastTextField(textField);
                        textField.setEditable(true);
                        textField.setSelectionStart(0);
                        textField.setSelectionEnd(textField.getText().length());

                        textField.addKeyListener(new KeyAdapter() {
                            @Override
                            public void keyPressed(KeyEvent e) {
                                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                                    songs.get(songTextFields.indexOf(inner)).setByInt(details.get(usedI), textField.getText());
                                    textField.setText(textField.getText());
                                    textField.setEditable(false);
                                }
                            }
                        });
                    }
                }
            });

            textField.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (e.getClickCount() == 2) {
                        // TODO: play song
                    }
                }
            });

            if (i == details.size() - 1) {
                gc.anchor = GridBagConstraints.LINE_START;
                if (bottom) {
                    textField.setBorder(BorderFactory.createCompoundBorder(bottomRightBorder, emptyBorder));
                } else {
                    textField.setBorder(BorderFactory.createCompoundBorder(rightBorder, emptyBorder));
                }

                //textField.setPreferredSize(detailDimensions.get(i));
                //textField.setHorizontalAlignment(JTextField.LEFT);
                panel.add(textField, gc);
            } else {
                //textField.setPreferredSize(detailDimensions.get(i));
                //textField.setHorizontalAlignment(JTextField.LEFT);
                panel.add(textField, gc);
                gc.gridx++;
            }
            System.out.println(textField.getText() + " : " + textField.getPreferredSize() + "  " + textField.getHorizontalAlignment());
        }
        leftSide = true;
        bottom = false;
        textFieldBackground = (textFieldBackground == lightColor ? darkColor : lightColor);
        gc.gridx = 0;
        gc.gridy++;
        gc.anchor = GridBagConstraints.LINE_END;
    } 

Here's where I'm creating each textfield. The labels will sort if a detail label is clicked and the songsortby string isn't already equal to that label.

private List<List<JTextField>> getSongTextFields(List<Song> songs) {
    switch (songSortBy) {
        case "Title":
            songs = sortSongs(0, songs);
            break;
        case "Artist":
            songs = sortSongs(1, songs);
            break;
        case "Album":
            songs = sortSongs(2, songs);
            break;
        case "Year":
            songs = sortSongs(3, songs);
            break;
        case "Genre":
            songs = sortSongs(4, songs);
            break;
        case "Features":
            songs = sortSongs(5, songs);
            break;
        case "Producers":
            songs = sortSongs(6, songs);
            break;
        default:
            break;
    }

    List<List<JTextField>> textFields = new ArrayList<>();
    for (Song song : songs) {
        List<JTextField> innerLabels = new ArrayList<>();
        innerLabels.add(new JTextField(song.getTitle()));
        innerLabels.add(new JTextField(song.getArtist()));
        innerLabels.add(new JTextField(song.getAlbum()));
        innerLabels.add(new JTextField(song.getYear()));
        innerLabels.add(new JTextField(song.getGenre()));
        innerLabels.add(new JTextField(song.getFeatures()));
        innerLabels.add(new JTextField(song.getProducers()));
        textFields.add(innerLabels);
    }

    return textFields;
}

And finally this is where I'm sorting my songs, I don't think the bug is occurring in this method but you never know.

private List<Song> sortSongs(int order, List<Song> songs) {
    List<Song> sortedList = new ArrayList<>();

    int j;
    for (int i = 0; i < songs.size(); i++) {
        j = 0;
        while (j < sortedList.size() && songs.get(i).getByInt(order).toUpperCase().compareTo(
                sortedList.get(j).getByInt(order).toUpperCase()) >= 0) {
            j++;
        }
        sortedList.add(j, songs.get(i));
    }

    return sortedList;
}

If you guys want to see any other parts of my code just to let me know, thanks for the help.

Matt
  • 31
  • 2
  • 1
    Your `MouseListener` makes no sense, nor does `textField.addKeyListener(new KeyAdapter() {`, which is just listening for the enter key. Since all that the mouse listener is doing is making the field editable, why not just leave it editable all the time? Also you should be using an `ActionListener` to listen for the enter key on text fields. Also, basically, every time you click a field, you're adding ANOTHER `KeyListener` to it... – MadProgrammer Feb 03 '16 at 22:48
  • Have you considered using a `JTable`, it basically has all the functionality you seem to be trying to re-invent – MadProgrammer Feb 03 '16 at 22:49
  • I don't want every textfield editable, I want you to be able to click on a textfield and edit it then. Like I said I'm going for something like itunes where you can click on the text and edit it at that time. And I'll look into removing my keylisteners as I need but the editing text part of my code works fine. – Matt Feb 03 '16 at 22:52
  • No i haven't, I'll definitely look into a JTable. – Matt Feb 03 '16 at 22:52
  • Okay, so disable the fields which can't be edited, but leave the other's editable all time. Frankly, iTunes wouldn't be my choice for a good user experience example – MadProgrammer Feb 03 '16 at 22:53
  • I'm not going for just itunes, I'm adding my own twists to it to tailor it for what I'd like itunes to be. And in another part of my code I'm making the Textfields uneditable again. – Matt Feb 03 '16 at 22:59
  • 2
    That's kind of my point. By making them non-editable, what benefits are you gaining, when you all you're going to do is make them editable when the click them. It would be easier to diagnose if you had a runnable example. Consider providing a [runnable example](https://stackoverflow.com/help/mcve) which demonstrates your problem. This is not a code dump, but an example of what you are doing which highlights the problem you are having. This will result in less confusion and better responses – MadProgrammer Feb 03 '16 at 23:05

1 Answers1

0

I think your problem is caused by the fact that you are messing with sizing and alignment of your JTextFields at runtime (after they have been layouted), without any sanity checks and - even more important - without validating and redrawing the parent layouts.

This is the code i refer to:

final JTextField textField = inner.get(details.get(i));
textField.setPreferredSize(detailDimensions.get(i));
textField.setHorizontalAlignment(JTextField.LEFT);

The best solution is to avoid the problem altogether by desiging your components in a way that they don't need to change their shape so much. Use a table as someone else suggested; maybe a textarea with richtext/html can solve your problem; maybe swapping only the values in between JTextFields is all you really need?

If you must take the approach with resizing and all that:

  1. Make sure that containing (parent) components offer enough space and will furthermore adapt properly.
  2. Invoke revalidate()/validate() and repaint() of your parent
    container(s) after messing with size and alignment of your
    JTextFields. See Dynamically Add Components to a JDialog
Community
  • 1
  • 1
Andreas Vogl
  • 1,776
  • 1
  • 14
  • 18