java: доступ к JProgressBar в модели AbstractTableModel

Я работаю со следующим кодом, который содержит JProgressBar внутри AbstractTableModel. Значение прогресса JProgressBar обновляется в «case 5:» функции getValueAt() путем возврата Float. Я пытаюсь понять, как получить доступ к базовому экземпляру JProgressBar, чтобы я мог изменить некоторые его свойства, кроме значения прогресса (например, setVisible()).

package org.jdamico.jhu.runtime;

import java.util.*;
import javax.swing.*;
import javax.swing.table.*;

// This class manages the upload table's data.
class TransfersTableModel extends AbstractTableModel implements Observer {

    /**
     * 
     */
    private static final long serialVersionUID = 2740117506937325535L;

    // These are the names for the table's columns.
    private static final String[] columnNames = { "Type","Name", "UUID","Status",
            "Stage","Progress","Total Start Time","Total End Time" };

    // These are the classes for each column's values.
    private static final Class[] columnClasses = { String.class,String.class,String.class, 
            String.class,String.class, JProgressBar.class, String.class, String.class};

    // The table's list of uploads.
    private ArrayList<ParentEntry> transferList = new ArrayList<ParentEntry>();

    // Add a new upload to the table.
    public void addTransfer(ParentEntry pe) {

        // Register to be notified when the upload changes.
        pe.addObserver(this);

        transferList.add(pe);

        // Fire table row insertion notification to table.
        fireTableRowsInserted(getRowCount(), getRowCount());
    }

    // Get a upload for the specified row.
    public ParentEntry getTransfer(int row) {
        return transferList.get(row);
    }

    // Remove a upload from the list.
    public void clearTransfer(int row) {
        transferList.remove(row);

        // Fire table row deletion notification to table.
        fireTableRowsDeleted(row, row);
    }

    // Get table's column count.
    public int getColumnCount() {
        return columnNames.length;
    }

    // Get a column's name.
    public String getColumnName(int col) {
        return columnNames[col];
    }

    // Get a column's class.
    public Class getColumnClass(int col) {
        return columnClasses[col];
    }

    // Get table's row count.
    public int getRowCount() {
        return transferList.size();
    }

    // Get value for a specific row and column combination.
    public Object getValueAt(int row, int col) {

        ParentEntry pe = transferList.get(row);
        switch (col) {
        case 0:
            return pe.getType();
        case 1: // URL
            return pe.getUrl();
        case 2: //UUID
            return pe.getUUID() + "";
        case 3: // Status
            return pe.getStatus().getDisplay();
        case 4: // Stage
            return pe.getStage().getDisplay();
        case 5: //Progress
            return new Float(pe.getProgress());
        case 6:
            if (pe.getTotalStartTime() != null)
                return pe.getTotalStartTime().getTime().toString();
            else
                return "";
        case 7:
            if (pe.getTotalEndTime() != null)
                return pe.getTotalEndTime().getTime().toString();
            else
                return "";
        }
        return "";
    }

    /*
     * Update is called when a Upload notifies its observers of any changes
     */
    public void update(Observable o, Object arg) {
        int index = transferList.indexOf(o);

        // Fire table row update notification to table.
        fireTableRowsUpdated(index, index);
    }
}

Обновление: изначально это был не мой код, и я все еще знакомлюсь с ним, но я только что обнаружил, что существует класс ProgressRenderer, который расширяет JProgressBar и реализует TableCellRenderer. Это то, что используется для отображения индикатора выполнения в таблице. Поэтому я собираюсь изменить этот код, чтобы изменить способ отображения индикатора выполнения:

package org.jdamico.jhu.runtime;

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

/*import org.jdamico.jhu.components.Controller;
import org.jdamico.jhu.components.FilePartition;
import org.vikulin.utils.Constants;*/

// This class renders a JProgressBar in a table cell.
class ProgressRenderer extends JProgressBar implements TableCellRenderer {




    // Constructor for ProgressRenderer.
    public ProgressRenderer(int min, int max) {
        super(min, max);
    }

    /*
     * Returns this JProgressBar as the renderer for the given table cell.
     */
    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
        // Set JProgressBar's percent complete value.
        Float tmp = ((Float) value).floatValue();
        if (tmp == -1) {
            this.setVisible(false);
        }
        else {
            setValue((int) ((Float) value).floatValue());
            if (this.isVisible() == false)
                this.setVisible(true);
        }
        return this;
    }



}

person opike    schedule 12.06.2011    source источник
comment
мантра; отдельно, отдельно, отдельно :-) В частности, никогда не смешивайте представление с классами данных. Это неправильно   -  person kleopatra    schedule 13.06.2011


Ответы (2)


Вы можете добавить в класс метод, который позволит вам получить JProgressBar, связанный с интересующей вас строкой, например:

   public JProgressBar getProgressBar(int row) {
      ParentEntry pe = transferList.get(row);
      return pe.getProgress();
   }

Мне кажется забавным, что модель будет содержать JProgressBar, а не простое целое число, представляющее процент завершения. Для меня было бы более разумно иметь любой код для отображения индикатора выполнения в средстве визуализации ячеек JTable.

Редактировать 1
В ответ на комментарий opike ниже:

Действительно ли использование JProgressBar вне модели делает код более эффективным, чем внутри нее? Хватит ли прироста, чтобы тратить время на переписывание кода? Существующий код по большей части работает так, как мне нужно, поэтому я бы предпочел просто настроить его, а не более существенно переписать.

Мой вопрос и моя озабоченность в том, использует ли ваш модуль рендеринга ячеек JProgressBar, удерживаемый моделью? Если да, то как это сделать, если нет возможности получить JProgressBar? Если используется только полученное значение Float, для модели просто нет смысла хранить информацию и ресурсы, которые не используются. И да, это может заметно замедлить вашу программу.

person Hovercraft Full Of Eels    schedule 12.06.2011
comment
Я не создаю экземпляр JprogressBar явно в своем коде; AbstractTableModel обрабатывает это неявно. Когда таблица перерисовывается, функция getValueAt() вызывается обработчиком событий для всех ячеек. - person opike; 12.06.2011
comment
@opike: Верно - средство визуализации использует значение, возвращенное из модели, для ее визуализации, но почему модель должна содержать виджет с высоким ресурсом, такой как JProgressBar, когда все возвращаемые модели являются плавающими? Почему бы просто не сделать так, чтобы модель держала Float? Если я вас неправильно понимаю. - person Hovercraft Full Of Eels; 12.06.2011
comment
Действительно ли использование JProgressBar вне модели делает код более эффективным, чем внутри нее? Хватит ли прироста, чтобы тратить время на переписывание кода? Существующий код по большей части работает так, как мне нужно, поэтому я бы предпочел просто настроить его, а не более существенно переписать. - person opike; 12.06.2011

зачем использовать AbstractTableModel или добавлять значение JTable внутри этого блока кода, на самом деле вам это не нужно, DefalultTableModel может это сделать, например

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.*;
import javax.swing.table.TableCellRenderer;

public class ProgressBarTableCellRendererExample {

    private Random random = new Random();
    private JTable table;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ProgressBarTableCellRendererExample().makeUI();
            }
        });
    }

    public void makeUI() {
        table = new JTable(11, 1) {

            private Object[][] data;
            private static final long serialVersionUID = 1L;

            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }

            @Override
            public Class<?> getColumnClass(int column) {
                return Integer.class;
            }
        };
        randomize();
        table.setDefaultRenderer(Integer.class, new ProgressBarTableCellRenderer());
        table.setRowHeight(20);
        table.setRowMargin(2);
        JButton button = new JButton("Randomize");
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                randomize();
                getTableValue();
            }
        });
        JFrame frame = new JFrame();
        frame.add(new JScrollPane(table), BorderLayout.CENTER);
        frame.add(button, BorderLayout.SOUTH);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocation(150, 150);
        frame.setPreferredSize(new Dimension(600, 300));
        frame.pack();
        frame.setVisible(true);
    }

    private void randomize() {
        for (int i = 0; i < table.getRowCount(); i++) {
            table.setValueAt(random.nextInt(100), i, 0);
        }
    }

    private void getTableValue() {
        for (int i = 0; i < table.getRowCount(); i++) {
            System.out.println(String.valueOf(table.getValueAt(i, 0)));
        }
    }

    private class ProgressBarTableCellRenderer extends JProgressBar implements TableCellRenderer {

        private static final long serialVersionUID = 1L;

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                boolean hasFocus, int row, int column) {
            setValue((Integer) value);
            System.out.println("Tables Row: " + row + ", Column : " + column + ", has value - " + value);
            return this;
        }
    }
}
person mKorbel    schedule 12.06.2011
comment
Действительно ли мне необходимо переработать мой код, чтобы удалить AbstractTableModel? Это может быть излишним, но в настоящее время это работает, за исключением того факта, что я не знаю, как получить доступ к неявно созданному экземпляру JProgressBar в каждом столбце. - person opike; 12.06.2011
comment
@opike не требуется, но зачем ограничивать функциональность JTable в AbstractTableModel, если DefaltTableModels работает, 1) если вы начинаете учиться с JTable, тогда безопаснее всего использовать DefaltTableModels, 2) ваш getValueAt полностью контрпродуктивен, 3) я пропустил некоторые важные методы в вашей модели, 4) из какого источника вы обновили свой JTable, потому что, возможно, существуют и другие способы, тогда и я думаю, что вы неправильно задали свой вопрос, - person mKorbel; 12.06.2011
comment
@mKorbel: Лично я согласен с использованием AbstractTableModel, поскольку он дает большую гибкость в отношении того, что вы будете использовать в качестве ядра данных модели. Например, это позволяет OP использовать ArrayList объектов ParentEntry, а не Vector неуниверсальных векторов, но, с другой стороны, это также возлагает на OP большую ответственность, чтобы убедиться, что взаимодействия модель-представление-слушатель закодированы правильно. Но я не уверен, что getValueAt оригинального плаката является контрпродуктивным. - person Hovercraft Full Of Eels; 12.06.2011
comment
@Hovercraft Full Of Eels, это касается определений классов столбцов, конечно, может быть, я был бы почти согласен с этим, если бы каждая TableCell содержала разные JComponents в одном TableColumn (и конструктор в TableCellRenderer говорил об JProgresBars с разными диапазонами ??? stackoverflow.com/questions/6261017/ но в данном случае наши волшебные глобусы надоели и мы оба забыли про TableCellEditor), просто я против сложного простого вещи, - person mKorbel; 12.06.2011