У меня есть JScrollPanel и JPanel, добавленные к нему. Я хотел бы рисовать на JPanel и отображать полосы прокрутки JScrollPane всякий раз, когда рисунок превышает размер панели, и иметь возможность прокручивать рисунок как по вертикали, так и по горизонтали.
Я пробовал консультироваться с различными форумами и официальными документами и пробовал несколько вещей (установка границ, предпочтительный размер и т. д.), но, похоже, ни один из них не дал желаемого эффекта.
У меня есть JFrame (с GridBagLayout, кстати):
JFrame frame1 = new JFrame("Application");
frame1.setVisible(true);
frame1.setMinimumSize(new Dimension(580,620));
frame1.setResizable(false);
frame1.setLocationRelativeTo(null);
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Соответствующие компоненты:
JPanel panel1 = new JPanel();
JScrollPane scrollPane = new JScrollPane(panel1);
frame1.add(scrollPane, gbc_panel1); //added with layout constraints
JPanel:
panel1.setBackground(Color.BLACK);
panel1.setPreferredSize(new Dimension(500,500));
panel1.setMinimumSize(new Dimension(360,360));
panel1.setMaximumSize(new Dimension(1000,1000));
JScrollPane:
scrollPane.setAutoscrolls(true);
Соответствующий код из события действия кнопки, которая рисует:
Graphics g;
g = panel1.getGraphics();
panel1.paint(g);
g.setColor(new Color(0,128,0));
/* this is followed by some more code that
does the drawing of a maze with g.drawLine() methods */
Код отлично рисует, я просто не могу понять, как сделать прокрутку и динамическое изменение размера.
Буду признателен за любые полезные комментарии и замечания!
Спасибо!
Размер вашего компонента должен быть определен с помощью метода getPreferredSize, и вы должны использовать какой-то обратный вызов для родительского контейнера, чтобы сообщить им, когда размер вашего компонента изменится.
Привет! Спасибо за замечание! Скажите, пожалуйста, почему это плохая идея? Это вызывает проблему? Спасибо!
Спасибо @MadProgrammer! В конечном итоге переписывание метода рисования помогло - я просто надеялся, что смогу сделать рисование, не определяя свой пользовательский класс JPanel, но, похоже, это не работает. Переопределенный метод дочернего класса выглядит следующим образом: public void paintComponent(Graphics g) { super.paintComponent(g); drawMaze(g); } Отдельный метод drawMaze(Graphics g) содержит мелкие детали рисунка.




В конечном итоге переписывание метода рисования помогло, как предложил @MadProgrammer. Я просто надеялся, что смогу рисовать, не определяя свой пользовательский класс JPanel, но похоже, что это не работает.
Пользовательский класс выглядит так:
class Drawing extends JPanel {
int mazeSize;
public Drawing(JTextField jtf)
{
try {
this.mazeSize = Integer.parseInt(jtf.getText());
}
catch (Exception e)
{
JOptionPane.showMessageDialog(this, "ERROR! Invalid size value!");
}
} // the constructor gets the size of the drawing from a textField
public Dimension getPreferredSize() {
return new Dimension(mazeSize*10,mazeSize*10);
} //getPreferredSize - this method is used by the scroll pane to adjust its own size automatically
public void drawMaze (Graphics g)
{
/* some irrelevant code that does the desired drawing to the panel by calling g.drawLine()*/
} // drawMaze method that does the de facto drawing
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
drawMaze(g);
}// paintComponent() @Override method - this was the tricky part
}//Drawing JPanel subclass
Также стоит отметить (если какой-нибудь нуб вроде меня случайно наткнется на этот вопрос), что после создания экземпляра нового подкласса JPanel в событии действия мне пришлось добавить его в JScrollPanel следующим образом, вместо того, чтобы просто использовать его метод добавления():
Drawing drawPanel = new Drawing(textfield1);
scrollPane.getViewport().add(drawPanel);
Еще раз спасибо за предложение!
Закончив работу с программой (генератор случайных лабиринтов, использующий алгоритм рекурсивного поиска с возвратом), я сделаю исходный код доступным по адресу профиль на гитхабе.
На самом деле, последний фрагмент кода с scrollPane.getViewport().add(drawPanel); — это то, что действительно помогло! :-)
g = panel1.getGraphics();- невероятно плохая идея, и вы никогда не должны этого делать, и вы никогда не должны делатьpanel1.paint(g);, если на то пошло, это показывает, что вы явно не понимаете, как нужно выполнять пользовательское рисование в Swing. Вы должны начать с чтения Выполнение пользовательской живописи и Рисование в AWT и Swing и того, как вы предполагаете с ними работать. На самом деле почти любое из руководств по Swing даст вам больше помощи при размещении на SO.