Мигающие фоновые строки TableViewer или TreeViewer в SWT - PullRequest
9 голосов
/ 17 декабря 2009

Мне нужна возможность иметь мигающий (красный, может быть, больше цветов) фон для строк в TableViewer / TreeViewer. Каковы лучшие варианты?

Возможно мигание нескольких строк, мигание ДОЛЖНО быть синхронным, и мне нужно два режима мигания, быстрый и медленный.

Ответы [ 3 ]

4 голосов
/ 19 декабря 2009

Я бы сделал что-то похожее на это. Обновляйте элементы, для которых нужно менять цвета через равные промежутки времени. При каждом обновлении переключайте цвета в зависимости от того, как вы хотите, чтобы они мигали.

void scheduleColorChange(final Color colors[], final int startIndex, final int changeInterval)
{
  getDisplay().timerExec(changeInterval, new Runnable()
  {
    public void run()
    {
      Object[] elements = getColorChangingElements();
      setColorsForFlashingElements(elements, colors[index%colors.length]);
      getViewer().update(elements);
      scheduleColorChange(colors, startIndex+1, changeInterval)
    }
  });
}  

и поставщик ярлыков должен внедрить IColorProvider.

1 голос
/ 18 декабря 2009

Привет, это быстрый взлом, который показывает идею, которую невозможно улучшить во многих отношениях. Я показываю три класса, выполняющих работу. Если вы хотите, я могу предоставить экспортированный плагин исходного кода, готовый к установке завтра в ваш рабочий стол eclipse. Вот основные классы:

import java.util.TimerTask;

import org.eclipse.jface.resource.ColorDescriptor;
import org.eclipse.jface.viewers.IColorProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.ui.PlatformUI;

public class Blinker extends LabelProvider implements ITableLabelProvider, IColorProvider  {

    private final TableViewer viewer;


    public Blinker(TableViewer viewer){
        this.viewer = viewer;
    }

    // this is just a lousy way to store blink_on/blink_off...
    private byte state; 

    // there must be a better way to get a color...
    final static Color red = ColorDescriptor.createFrom(new RGB(255,0,0)).createColor(PlatformUI.getWorkbench().getDisplay());
    final static Color green = ColorDescriptor.createFrom(new RGB(0,255,0)).createColor(PlatformUI.getWorkbench().getDisplay());


    private final TimerTask task = new TimerTask(){
        @Override
        public void run() {
            state++;
            PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable(){
                public void run() {
                    viewer.refresh();
                }
            });
        }
    };

    private Timer t;

    synchronized byte getState(){
        return state;
    }

    @Override
    public Image getColumnImage(Object element, int columnIndex) {
        return null;
    }

    @Override
    public String getColumnText(Object element, int columnIndex) {
        return ((Element) element).text;
    }

    @Override
    public Color getBackground(Object object) {
        Element element = (Element) object;
        if (element.isBlinking()){
            return getState() % 2 == 0 ? Blinker.red : Blinker.green;
        } else {
            return Blinker.green;
        }
    }

    @Override
    public Color getForeground(Object element) {
        return null;
    }


    public void start() {
        t = new Timer();
        t.schedule(task, 200, 1000);
    }

    public void stop() {
        t.cancel();
        t = null;
        }

}

Это пример модели класса. Состояние мерцания сохраняется внутри объекта, но вы можете улучшить его, используя какой-то тип адаптера:

package com.example.blinker;

public class Element {

    private boolean blinking;
    public final String text;


    public Element(String string, boolean b) {
        this.text = string;
        this.blinking = b;
    }


    public synchronized boolean isBlinking(){
        return blinking;
    }


    public synchronized void setBlinking(boolean b){
        this.blinking = b;
    }


    public static final Element[] sampledata = new Element[] {
        new Element("Merkur", false),
        new Element("Venus", true),
        new Element("Erde", false),
        new Element("Mars", true),
        new Element("Jupiter", false),
        new Element("Saturn", true),
        new Element("Uranus", false),
        new Element("Neptun", true),
        new Element("Pluto", false),
    };

}

И, наконец, TableViewer, встроенный в View, с использованием двух приведенных выше:

package com.example.blinker.views;

import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;

import com.example.blinker.Blinker;
import com.example.blinker.Element;

public class SampleView extends ViewPart {

    public static final String ID = "com.example.blinker.views.SampleView";

    private TableViewer viewer;
    private Blinker blinker;

    class ViewContentProvider implements IStructuredContentProvider {
        public void inputChanged(Viewer v, Object oldInput, Object newInput) {}
        public void dispose() {}
        public Object[] getElements(Object parent) {
            return Element.sampledata;
        }
    }

    public void createPartControl(Composite parent) {
        viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
        viewer.setContentProvider(new ViewContentProvider());
        blinker = new Blinker(viewer);
        viewer.setLabelProvider(blinker);
        viewer.setInput(new Object());
        blinker.start();
    }

    public void setFocus() {
        viewer.getControl().setFocus();
    }

    public void dispose() {
        blinker.stop();
    }
}
0 голосов
/ 18 декабря 2009

У вас должна быть конструкция, похожая на такую:

LinkedList<Row> rows = new LinkedList<Row>();
Thread blinker = null;

public void start() {
    blinker = new Thread() {
        public void run() {
            while(!this.interrupted()) {
                try {
                    synchronized (rows) {
                        for (Row row : rows) {
                            row.setForegroundColor(color1);
                        }
                    }
                    Thread.sleep(500);
                    synchronized (rows) {
                        for (Row row : rows) {
                            row.setForegroundColor(color2);
                        }
                    }
                    Thread.sleep(500);
                } catch (InterruptException e) {
                    break;
                }
            }
        }
    };
    blinker.start();
}

public void stop() {
    if (blinker != null) {
        blinker.interrupt();
    }
}

public void add(Row row) {
    synchronized (rows) {
        if (!rows.contains(row)) {
            rows.add(row);
        }
    }
}

public void remove(Row row) {
    synchronized (rows) {
        rows.remove(row);
    }
}

Когда отображается Shell, он должен вызвать start(). Когда он утилизирует, звоните stop().

Обратите внимание, что я на самом деле не проверял это; это какой-то Javaish псевдокод. Если вы не можете установить цвет строки с помощью предложенного setForegroundColor() выше, вы можете ввести виджет и определить событие paint().

...