Отрисовка компонента в BufferedImage приводит к повреждению изображения

Я использую компонент JScrollNavigator, описанный здесь , чтобы предоставить окно навигации на большой «холст -подобный» компонент САПР, который я встроил в JScrollPane.

Я попытался адаптировать JScrollNavigatorдля рисования эскиза холста, чтобы предоставить пользователю некоторый дополнительный контекст. Однако это действие приводит к повреждению рендеринга основного фрейма моего приложения. В частности, это действие вызова paint(Graphics)для компонента окна просмотра (, то есть моего основного холста ), передачи объекта Graphics, созданного BufferedImage, что вызывает последующее повреждение отображения; если я закомментирую эту строку, все будет работать нормально.

Ниже приведен переопределенный paintComponentметод JScrollNavigator:

@Override
protected void paintComponent(Graphics g) {
    Component view = jScrollPane.getViewport().getView();
    BufferedImage img = new BufferedImage(view.getWidth(), view.getHeight(), BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2d = img.createGraphics();

    // Paint JScrollPane view to off-screen image and then scale.
    // It is this action that causes the display corruption!
    view.paint(g2d);
    g2d.drawImage(img, 0, 0, null);
    Image scaled = img.getScaledInstance(getWidth(), getHeight(), 0);

    super.paintComponent(g);
    g.drawImage(scaled, 0, 0, null);
}

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

РЕДАКТИРОВАТЬ

Для дополнительной информации :JScrollNavigatorобразует вспомогательную панель -на левой -стороне JSplitPane. JScrollPane, связанный с навигатором, находится справа -. «Повреждение» приводит к тому, что сплиттер больше не отображается, а полосы прокрутки не видны (они выглядят белыми ). Если я изменю размер JFrame, раздел JMenuтакже станет белым. Если я пытаюсь использовать навигатор или взаимодействовать с полосами прокрутки, они становятся видимыми, но сплиттер остается белым. Это как если бы настройки непрозрачности различных компонентов были затронуты рендерингом окна просмотра в закадровое изображение.

Кроме того, если я заставлю JScrollNavigatorпоявиться в совершенно отдельном JDialog, все будет работать правильно.

РЕДАКТИРОВАТЬ 2

Я могу последовательно воспроизвести проблему , выполнив следующие:

Добавьте JMenuBarкmFrame:

JMenuBar bar = new JMenuBar();
bar.add(new JMenu("File"));
mFrame.setJMenuBar(bar);

В методе main()из JScrollNavigatorзаменить:

jsp.setViewportView(textArea);

... с:

jsp.setViewportView(new JPanel() {
  {
    setBackground(Color.GREEN);
    setBorder(BorderFactory.createLineBorder(Color.BLACK, 5));
  }
});

Убедитесь, что панель JScrollNavigatorвстроена в панель mFrame, а не отображается как отдельная панель JDialog:

mFrame.add(jsp, BorderLayout.CENTER);
mFrame.add(nav, BorderLayout.NORTH);

. Теперь, когда приложение запускаетJMenuBarбольше не виден ; акт рисования вида (, то есть зеленого цвета JPanelс толстой черной рамкой )для Graphics2D, возвращенного BufferedImage.createGraphics(), на самом деле, кажется, отображает его на экране , возможно, сверху -левый угол JFrame, что скрывает другие компоненты. Это происходит только в том случае, если JPanelиспользуется в качестве окна просмотра, а не другой компонент, такой как JTextArea, JTableи т. д.

РЕДАКТИРОВАТЬ 3

Похоже, у этого человека была та же проблема (, но решение не опубликовано):http://www.javaworld.com/community/node/2894/

РЕДАКТИРОВАТЬ 4

Вот методы mainи paintComponent, которые приводят к воспроизводимой ошибке, описанной в Редактировании 2 :

public static void main(String[] args) {
    JScrollPane jsp = new JScrollPane();
    jsp.setViewportView(new JPanel() {
        {
            setBackground(Color.GREEN);
            setBorder(BorderFactory.createLineBorder(Color.BLACK, 5));
        }
    });

    JScrollNavigator nav = new JScrollNavigator();
    nav.setJScrollPane(jsp);

    JFrame mFrame = new JFrame();

    JMenuBar bar = new JMenuBar();
    bar.add(new JMenu("File"));
    mFrame.setJMenuBar(bar);

    mFrame.setTitle("JScrollNavigator Test");

    mFrame.setSize(800, 600);

    mFrame.setLayout(new GridLayout(1, 2));

    mFrame.add(jsp);
    mFrame.add(nav);
    Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize();
    mFrame.setLocation((screenDim.width - mFrame.getSize().width) / 2, (screenDim.height - mFrame.getSize().height) / 2);

    mFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mFrame.setVisible(true);
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    Component view = jScrollPane.getViewport().getView();

    if (img == null) {
        GraphicsConfiguration gfConf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
        img = new BufferedImage(view.getWidth(), view.getHeight(), BufferedImage.TYPE_INT_ARGB);
    }

    Graphics2D g2d = img.createGraphics();
    view.paint(g2d);

    Image scaled = img.getScaledInstance(getWidth(), getHeight(), 0);

    g.drawImage(scaled, 0, 0, null);
}

. РЕДАКТИРОВАТЬ 5

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

Corrupt Image 1

Ни JScrollNavigator, ни JMenuBar не были нарисованы; эти области кадра прозрачны.

После изменения размера я вижу следующее:

Corrupt Image 2

JMenuBarдо сих пор не окрашен, и кажется, что JPanelв какой-то момент был отрендерен в (0,0 )(. где JMenuBarдолжно быть ). Прямой причиной этого является вызов view.paintвнутри paintComponent.

7
задан Adamski 3 August 2012 в 09:53
поделиться