Делаем JProgressBar кликабельным в JList

У меня есть класс, который расширяет AbstractListModel и реализует PropertyChangeListener со списком JProgressBar, который хранится внутри. После запуска SwingWorker этот класс опубликует JprogressBar, чтобы показать прогресс.

Класс отлично работает, показывая прогресс, но я хотел бы изменить для пользователя, чтобы он мог щелкнуть индикатор выполнения и отменить задачу, я добавил mouselistener в JprogressBar, однако mouselistener не захвачен. Ниже приведен фрагмент моего класса, может кто-нибудь посоветовать, где что-то пойдет не так, пожалуйста?

public final class JobManager extends AbstractListModel implements PropertyChangeListener {
    private static final List<JProgressBar> progressBarList = new ArrayList<JProgressBar>();

    private static final JobManager INSTANCE = new JobManager();

    // Called by swing ui to add into Jpanel
    public JScrollPane getJobListPane() {
        final JList jobTable = new JList(INSTANCE);
        jobTable.setName("Job List");
        jobTable.setCellRenderer(new CustomListCellRenderer());
        JScrollPane scrollPane = new JScrollPane(jobTable);
        return new JScrollPane(tasksTable);
    }

    private void startJob(List<Job> jobList) {

        JProgressBar progressBar = new JProgressBar();
        progressBar.setMaximum(100);
        progressBar.setStringPainted(true);
        progressBar.setString(String.format("%s (%d%%)", caption, 0));
        progressBar.setForeground(Colours.GREEN.brighter());
        progressBar.setBackground(Color.GREEN);


        final JPopupMenu popUpMenu = new JPopupMenu();
        JMenuItem cancelMenuItem = new JMenuItem("Cancel");
        cancelMenuItem.addActionListener(new ActionListener() {
          @Override
           public void actionPerformed(final ActionEvent e) {
                 System.out.println("Pressed cancellation option..............");
                 cancelTask();
            }
         });

    popUpMenu.add(cancelMenuItem);

        final JProgressBar progressBar1 = progressBar;

        MouseListener mouseListener = new MouseAdapter() {
             @Override
             public void mouseClicked(final MouseEvent mouseEvent) {
                    popUpMenu.show(mouseEvent.getComponent(), progressBar1.getX(), progressBar1.getY());
             }
        };
        progressBar.addMouseListener(mouseListener);

        JobManager.progressBarList.add(progressBar);

        fireIntervalAdded(this, JobManager.jobList.size() - 1, JobManager.jobList.size() - 1);

        runnable.addPropertyChangeListener(this);

    }

    @Override
    public Object getElementAt(final int row) {
        if (row < JobManager.progressBarList.size()) {
            return JobManager.progressBarList.get(row);
        } else {
            return null;
        }
    }

    @Override
    public int getSize() {
        return someSize;
    }

    @Override
    public void propertyChange(final PropertyChangeEvent evt) {
            int index = jobList.indexOf(evt.getSource());
            if (index >= 0) {
                int progress = (Integer) evt.getNewValue();
                JProgressBar progressBar = JobManager.progressBarList.get(index);
                progressBar.setString(String.format("%s (%d%%)", "Job title ", progress));
                progressBar.setValue(progress);

                fireContentsChanged(this, index, index);
            }
        }
    }
}



public class CustomListCellRenderer implements ListCellRenderer {

    @Override
    public Component getListCellRendererComponent(final JList list, final Object value, final int index,
            final boolean isSelected, final boolean cellHasFocus) {
        if (value instanceof Component) {
            return (Component) value;
        }  
        return new JProgressBar();

    }
}

person Coffee bean    schedule 12.11.2015    source источник


Ответы (1)


Я добавил mouselistener в JprogressBar, однако mouselistener не захвачен.

JProgressBar не является реальным компонентом. Средство визуализации просто рисует изображение компонента.

Вам нужно добавить JPopupMenu и MouseListener к JList. MouseListener требуется для выбора источника света, по которому щелкнули. Что-то типа:

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

public class ListRightClick extends JPanel implements ListSelectionListener
{
    public ListRightClick()
    {
        setLayout( new BorderLayout() );

        final JPopupMenu popup = new JPopupMenu();
        popup.add( new JMenuItem("Do Something1") );
        popup.add( new JMenuItem("Do Something2") );
        popup.add( new JMenuItem("Do Something3") );

        String[] data = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight" };
        JList<String> list = new JList<String>( data );
        list.setVisibleRowCount( 5 );
        list.setComponentPopupMenu( popup );
        list.addListSelectionListener( this );

        list.addMouseListener( new MouseAdapter()
        {
            public void mousePressed(MouseEvent e)
            {
                if ( SwingUtilities.isRightMouseButton(e) )
                {
                        JList list = (JList)e.getSource();
                        int row = list.locationToIndex(e.getPoint());
                        list.setSelectedIndex(row);
                }
            }

        });

        add( new JScrollPane(list) );
    }

    public void valueChanged(ListSelectionEvent e)
    {
        JList list = (JList)e.getSource();
        System.out.println(list.getSelectedValue());
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("ListRightClick");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new ListRightClick(), BorderLayout.NORTH);
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
    }
}
person camickr    schedule 12.11.2015
comment
Имеет смысл, это работает. Чтобы убедиться, что всплывающее окно отображается только в правильном месте, я добавил этот блок, и он работает хорошо. Прямоугольник r = tasksTable.getCellBounds(0, jobTable.getLastVisibleIndex()); if (r != null && r.contains(mouseEvent.getPoint())) { int index = jobTable.locationToIndex(point); } - person Coffee bean; 13.11.2015