Скользящая область просмотра по JPanel - PullRequest
0 голосов
/ 02 августа 2010

Я использую drawLine() и друзей, чтобы нарисовать график на JPanel. Есть десятки тысяч точек на графике, так что это занимает 3-5 секунд. Я хочу, чтобы над графиком был видовой экран, как показано на рисунке ниже.

график http://cl.ly/1qvN/content

Я бы хотел, чтобы этот видовой экран был обновляемым, поскольку у меня есть MouseMotionListener на JPanel, на котором включен график. Проблема в том, что если я перерисовываю область просмотра (квадрат), как сейчас (используя drawRect()), мне придется перерисовывать весь график, что нежелательно.

Я читал о GlassPanes, которые могут быть полезны для решения этой проблемы, но они, очевидно, являются частью JFrames, а не JPanels. (У меня есть эта панель вместе с другими компонентами внутри JFrame.)

Что было бы хорошим способом справиться с этим, остаться в Swing и быть эффективным?

Для чего бы это ни стоило, я на самом деле кодирую в Clojure, но это ничего не должно изменить здесь.

Большое спасибо!

Isaac

Ответы [ 2 ]

2 голосов
/ 02 августа 2010

Мой подход к решению проблемы такого рода заключался в рассмотрении изменчивости данных. Если график не изменяется в режиме реального времени, единственное, что изменится с paint на paint, - это положение синей рамки. Один из способов минимизировать время рисования - не повторять работу, которую вы уже выполнили. Например:

protected void paintComponent(Graphics g) {
    // paint chart
    if (dirty || buffer == null) {
        buffer = new BufferedImage(getWidth(), getHeight(),
                                   BufferedImage.TYPE_ING_ARGB);
        // Paint the chart onto the buffered image
        dirty = false;
    }
    b.drawImage(0, 0, buffer);
    // Draw blue box
    ...
}

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

public void invalidateBuffer() {
    dirty = true;
    repaint();
}
1 голос
/ 02 августа 2010

На скриншоте, который вы разместили, рисование не займет 3-5 секунд. Вам не нужно использовать слои, чтобы выполнить то, о чем вы говорите. У меня есть приложение с таким количеством данных, как вы описываете, но с более сложной визуализацией. Он также имеет такую ​​же функцию просмотра, которую вы обсуждали. Не имеет проблем с окраской, и чаще всего рисует за 3-5 миллисекунд.

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

Соберите информацию о времени внутри метода рисования и запишите ее в консоль. Отследите, сколько времени занимает каждая часть метода, и выясните, какие строки кода вызывают задержку. Выясните, как избавиться от этой задержки. Метод рисования должен занимать всего 3-5 миллисекунд. Вы в 1000 раз - что-то может быть оптимизировано.

Убедитесь, что вы рисуете только то, что на самом деле будет видно на экране. Не тратьте время на рисование вещей, которые будут появляться за кадром. Также убедитесь, что вы не рисуете действительно длинные линии, которые видны на экране только частично. (Например, если вы увеличиваете масштаб до чертиков, и даже самая маленькая линия теперь огромна.) Все это должно быть нарисовано, независимо от того, видно оно или нет.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...