DefaultTableCellRenderer

Status
Nicht offen für weitere Antworten.

Maik20

Mitglied
Hallo

ich habe ein kleines Problem mit meinem Renderer. Ich binde in einen JTable eine ProgressBar ein. Dazu habe ich folgenden Renderer. Funktioniert auch perfekt. Nun habe ich jedoch das Problem, das die Progressbar in der Zeile 1 z.B. von 0 bis 100, die ProgressBar in der Zeile 2 jedoch von 0 bis 150 laufen soll. Da ich jede Minute den Wert aktuallisieren muss, kann ich nicht einfach die PB in Zeile 2 von 150 auf 100 runterskalieren und die Wartezeit für einen Tick erhöhen.

Daher die Frage. Wie kann ich meinem Renderer für jede Zeile die maxValue mitteilen?

Java:
class ProgressRenderer extends DefaultTableCellRenderer {
    
	private static final long serialVersionUID = 1L;
	
	private final JProgressBar b = new JProgressBar(0, 100);
    public ProgressRenderer() {
        super();
        setOpaque(true);
        b.setBorder(BorderFactory.createEmptyBorder(1,1,1,1));
        b.setStringPainted(true);
    }
    public Component getTableCellRendererComponent(JTable table, Object value, 
                boolean isSelected, boolean hasFocus, int row, int column) {
        Integer i = (Integer)value;
        String text = "Done " + i;
        if (i==-1000){
        	text = "Scanning";
        }else if(i<0) {
            text = "Canceled";
        }else if(i<100) {
            b.setValue(i);
            return b;
        }
        super.getTableCellRendererComponent(table, text, isSelected, hasFocus, row, column);
        return this;
    }
}
 
Zuletzt bearbeitet von einem Moderator:
S

SlaterB

Gast
speichere zwei ProgressBars, b1 und b2
und statt b wählst du in getTableCellRendererComponent b1 oder b2 aus,
abhängig von der übergebenen row oder anderen Faktoren

vielleicht reicht auch eine ProgressBar, wenn man den MaxValue ohne Schwierigkeiten neu setzen kann,
wiederum abhängig von row & Co.
 

Maik20

Mitglied
Das mit den zwei Progressbars ist eigentlich eine gute Idee. Allerdings habe ich mein Beispiel etwas vereinfacht dargestellt. Theoretisch kann jede Zeile ein anderen MaxWert aufweisen. Dann wären das n-Progressbars. Nicht gerade performant.

Das mit dem neu setzen würde ich ja versuchen. Allerdings weiß ich nicht wie ich in

public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {

an meinen MaxValue komme?

Mittels Variablenübergabe im Funktionsaufruf zumindest nicht. Und da der Renderer in einer eigenen Klasse steht ...
 

Michael...

Top Contributor
Wie wär's damit in der Spalte an Stelle eines ints ein eigenes Objekt zu speichern, das z.B. einen currentValue und einen maxValue besitzt, um dann anhand dieser Werte die Progressbar zu zeichnen?
 

Maik20

Mitglied
Ich füttere die ProgressBar über einen SwingWorker. Wenn ich das richtige sehe schiebt dieser mittels "publish(Integer neuerValue);" nur Integerwerte aber keine anderen Klassen in die Tabellenzelle.

Allerdings muss ich dazu sagen, dass dies mein erster SwingWorker ist und ich die Funktionen noch nicht wirklich verstanden habe. Vielleicht hat einer eine Lösung für mich mit einer eigenen Klasse.
 
S

SlaterB

Gast
also ohne dass irgendwo die 100 + 150 hinterlegt ist, wird das Programm kaum von selbst drauf kommen
 

Michael...

Top Contributor
Hier mal ein Bsp. ohne Kommentare:
Java:
import java.awt.*;
import java.util.Random;

import javax.swing.*;
import javax.swing.table.*;

public class TableProgressBarDemo extends JFrame {
	private JTable table;
	private static ValueContainer[] values;
	private static DefaultTableModel model;

	public TableProgressBarDemo() {
		values = new ValueContainer[] { new ValueContainer(10, 100),
				new ValueContainer(80), new ValueContainer(30, 120) };
		table = new JTable(model = new DefaultTableModel(new Object[][] {
				{ "Element 1", values[0] }, { "Element 2", values[1] },
				{ "Element 3", values[2] }, }, new Object[] { "Element",
				"Fortschritt" })) {
			public boolean isCellEditable(int row, int column) {
				return column == 0;
			}
		};
		table.getColumnModel().getColumn(1).setCellRenderer(
				new ProgressRenderer());
		this.getContentPane().add(new JScrollPane(table));
	}

	public static void main(String[] args) {
		JFrame frame = new TableProgressBarDemo();
		frame.setBounds(0, 0, 500, 300);
		frame.setLocationRelativeTo(null);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
		new Thread(new Runnable() {
			public void run() {
				Random rnd = new Random();
				int index;
				while (true) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					index = rnd.nextInt(values.length);
					values[index].setValue(values[index].getValue() + 10);
					model.fireTableDataChanged();
				}
			}
		}).start();
	}
}

class ValueContainer {
	private int currentValue, maxValue;

	public ValueContainer(int max) {
		this(0, max);
	}

	public ValueContainer(int cur, int max) {
		this.currentValue = cur;
		this.maxValue = max;
	}

	public void setValue(int value) {
		if (value > this.maxValue)
			this.currentValue = maxValue;
		else
			this.currentValue = value;
	}

	public int getValue() {
		return currentValue;
	}

	public int getMaximum() {
		return maxValue;
	}
}

class ProgressRenderer extends DefaultTableCellRenderer {
	private JProgressBar progressBar;
	private ValueContainer cont;

	public ProgressRenderer() {
		progressBar = new JProgressBar();
		progressBar.setStringPainted(true);
		this.add(progressBar);
	}

	public Component getTableCellRendererComponent(JTable table, Object value,
			boolean isSelected, boolean hasFocus, int row, int column) {
		super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
				row, column);
		if (value instanceof ValueContainer) {
			cont = (ValueContainer) value;
			progressBar.setMaximum(cont.getMaximum());
			progressBar.setValue(cont.getValue());
			progressBar
					.setString(cont.getValue() + " von " + cont.getMaximum());
			progressBar.setBorder(this.getBorder());
			progressBar.setBackground(this.getBackground());
			return progressBar;
		}
		return this;
	}
}
Das mit dem Thread ist auch nicht so ganz sauber, aber es soll ja den Renderer und den Umgang mit dem speziellen Objekt demonstrieren
 

Maik20

Mitglied
Danke funktioniert wunderbar. Jetzt habe ich nur noch eine letzte Frage. Ich möchte zeitgleich mit der aktuallisierung der Progressbar auch die nächste Spalte in der Tabelle mit einem neuen Text füllen. Das dachte ich mir wie folgt:

Java:
public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
        super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
                row, column);
        if (value instanceof ValueContainer) {
            cont = (ValueContainer) value;
            progressBar.setMaximum(cont.getMaximum());
            progressBar.setValue(cont.getValue());
            progressBar
                    .setString(cont.getValue() + " von " + cont.getMaximum());
            progressBar.setBorder(this.getBorder());
            progressBar.setBackground(this.getBackground());
            if (contgetValue()>150){
                table.setValueAt("YEAH", row, column+1);
            }else{
                table.setValueAt("OHHH", row, column+1);
            }
            return progressBar;
        }
        return this;
    }

Leider wird der neu gesetzte Text im JTable nicht angezeigt die Spalte ist und bleibt leer. Muss ich sowas wie einen repaint durchführen?
 

Michael...

Top Contributor
Wenn, dann würde ich das so machen:
Java:
if (cont.getValue()>=cont.getMaximum())
	table.setValueAt("Fertig!", row, column+1);
else
	table.setValueAt("Warten...", row, column+1);
Das sollte eigentlich auch funktionieren.
Allerdings ist es eigentlich nicht die Aufgabe eines Renderers Inhalte des Models zu ändern. So was könnte eventuell vom Model selbst, besser per Controller gemacht werden.
 

Maik20

Mitglied
Leider funktioniert genau das eben nicht. Wie gesagt es sieht so aus als würde er nicht neu zeichnen.
Ich habe den Fehler noch nicht gefunden. Bin aber für jeden Tip dankbar.

Wie würde die Lösung mittels Controller aussehen?
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen

Neue Themen


Oben