Я использую компонент 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
Кажется, что у других возникают проблемы с воссозданием точной проблемы. Я бы попросил людей запустить код, вставленный сюда . Когда я впервые запускаю этот пример, я вижу следующее:
Ни JScrollNavigator, ни JMenuBar не были нарисованы; эти области кадра прозрачны.
После изменения размера я вижу следующее:
JMenuBar
до сих пор не окрашен, и кажется, что JPanel
в какой-то момент был отрендерен в (0,0 )(. где JMenuBar
должно быть ). Прямой причиной этого является вызов view.paint
внутри paintComponent
.