在 JScrollPane 中使用 paintComponent 绘图
Drawing with paintComponent in JScrollPanel
我实际上卡在了一些奇怪的东西上。我有一个带有 JScrollPane 的 JFrame,其中包含一个比实际屏幕大得多的 jPanel。我在列中绘制正方形,我希望这些正方形越过 jPanel 的右边界。 (这样它们就会在您向右滚动时出现。)但是使用 paintComponents 方法绘制的方块只会停在 JScrollPane 的可见视口处。
这是我在 JFrame 中的 JScrollPane 代码:
public void initComponents(){
mainPanel = new DrawPanel(dim);
this.getContentPane().setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridheight = 1;
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weighty = 1;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.BOTH;
JScrollPane jsp = new JScrollPane(mainPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jsp.setLayout(new ScrollPaneLayout());
jsp.setViewportView(mainPanel);
jsp.getVerticalScrollBar().setUnitIncrement(20);
jsp.setBorder(BorderFactory.createEmptyBorder());
jsp.setPreferredSize(new Dimension(dim.width,dim.height -taskBarSize));
jsp.setMinimumSize(new Dimension(dim.width,dim.height -taskBarSize));
jsp.setMaximumSize(new Dimension(dim.width,dim.height -taskBarSize));
this.getContentPane().add(jsp, gbc);
this.getContentPane().revalidate();
this.getContentPane().repaint();
}
这是我的 JPanel class :
public class DrawPanel 扩展 JPanel {
private Dimension dim;
private Integer numberPanels = 7;
private Double startPointX;
private Double startPointY;
private Double heightRow;
private Double heightPanel;
public DrawPanel(Dimension d) {
this.dim = d;
//this.setBackground(Color.BLACK);
calculateStartPoint();
}
public void calculateStartPoint() {
startPointX = (dim.getWidth() / 10) * 1;
startPointY = (dim.getHeight() / 10) * 1;
heightRow = (dim.getHeight() * 0.8) / numberPanels;
heightPanel = heightRow - 10;
double colums = 366/numberPanels;
this.setPreferredSize(new Dimension((int)(heightRow *((int)colums + 1)), dim.height ));
this.setMinimumSize(new Dimension((int)(heightRow *((int)colums + 1)), dim.height ));
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GRAY);
for (int i = 1; i <= 366; i++) {
// Si c'est le dernier d'une colonne
if (i%numberPanels == 0 && i != 0) {
g.fillRect(startPointX.intValue(), startPointY.intValue(), heightPanel.intValue(),
heightPanel.intValue());
startPointX = startPointX + heightRow;
startPointY = startPointY - ((numberPanels -1) * heightRow);
// Si c'est encore dans la meme colonne
} else {
g.fillRect(startPointX.intValue(), startPointY.intValue(), heightPanel.intValue(),
heightPanel.intValue());
startPointY = startPointY + heightRow;
}
}
}
}
启动时:
当我移动 scrollPane 时:
此外,在调整大小时,一切都不满意。我还必须看到,当向后滚动时,已经绘制的方块消失了,就好像屏幕外的一切都消失了。
感谢任何有时间的人。
你的问题是每次画完都需要重新计算起点。否则变量会不必要地增加。所以添加两行:
@Override
protected void paintComponent(Graphics g) { // should be protected
super.paintComponent(g);
// need to re-initialize variables within this
startPointX = (dim.getWidth() / 10) * 1;
startPointY = (dim.getHeight() / 10) * 1;
仅供参考,以后请 post MCVE 提出您的问题。例如,这是我用你的代码制作的 MCVE,现在可以由 anyone:
复制、粘贴和 运行 的代码
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.*;
@SuppressWarnings("serial")
public class Foo02 extends JPanel {
private DrawPanel mainPanel;
private Dimension dim = new Dimension(200, 200);
public Foo02() {
initComponents();
}
public void initComponents() {
mainPanel = new DrawPanel(dim);
// !! this.getContentPane().setLayout(new GridBagLayout());
setLayout(new GridBagLayout()); // !!
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridheight = 1;
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weighty = 1;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.BOTH;
JScrollPane jsp = new JScrollPane(mainPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jsp.setLayout(new ScrollPaneLayout());
jsp.setViewportView(mainPanel);
jsp.getVerticalScrollBar().setUnitIncrement(20);
jsp.setBorder(BorderFactory.createEmptyBorder());
jsp.setPreferredSize(new Dimension(dim.width, dim.height));
jsp.setMinimumSize(new Dimension(dim.width, dim.height));
jsp.setMaximumSize(new Dimension(dim.width, dim.height));
add(jsp, gbc);
revalidate();
repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
Foo02 mainPanel = new Foo02();
JFrame frame = new JFrame("Foo02");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
@SuppressWarnings("serial")
class DrawPanel extends JPanel {
private Dimension dim;
private Integer numberPanels = 7;
private Double startPointX;
private Double startPointY;
private Double heightRow;
private Double heightPanel;
public DrawPanel(Dimension d) {
this.dim = d;
// this.setBackground(Color.BLACK);
calculateStartPoint();
}
public void calculateStartPoint() {
startPointX = (dim.getWidth() / 10) * 1;
startPointY = (dim.getHeight() / 10) * 1;
heightRow = (dim.getHeight() * 0.8) / numberPanels;
heightPanel = heightRow - 10;
double colums = 366 / numberPanels;
this.setPreferredSize(new Dimension((int) (heightRow * ((int) colums + 1)), dim.height));
this.setMinimumSize(new Dimension((int) (heightRow * ((int) colums + 1)), dim.height));
}
@Override
protected void paintComponent(Graphics g) { // should be protected
super.paintComponent(g);
// need to re-initialize variables within this
startPointX = (dim.getWidth() / 10) * 1;
startPointY = (dim.getHeight() / 10) * 1;
g.setColor(Color.GRAY);
for (int i = 1; i <= 366; i++) {
// Si c'est le dernier d'une colonne
if (i % numberPanels == 0 && i != 0) {
g.fillRect(startPointX.intValue(), startPointY.intValue(), heightPanel.intValue(),
heightPanel.intValue());
startPointX = startPointX + heightRow;
startPointY = startPointY - ((numberPanels - 1) * heightRow);
// Si c'est encore dans la meme colonne
} else {
g.fillRect(startPointX.intValue(), startPointY.intValue(), heightPanel.intValue(),
heightPanel.intValue());
startPointY = startPointY + heightRow;
}
}
}
}
我实际上卡在了一些奇怪的东西上。我有一个带有 JScrollPane 的 JFrame,其中包含一个比实际屏幕大得多的 jPanel。我在列中绘制正方形,我希望这些正方形越过 jPanel 的右边界。 (这样它们就会在您向右滚动时出现。)但是使用 paintComponents 方法绘制的方块只会停在 JScrollPane 的可见视口处。
这是我在 JFrame 中的 JScrollPane 代码:
public void initComponents(){
mainPanel = new DrawPanel(dim);
this.getContentPane().setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridheight = 1;
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weighty = 1;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.BOTH;
JScrollPane jsp = new JScrollPane(mainPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jsp.setLayout(new ScrollPaneLayout());
jsp.setViewportView(mainPanel);
jsp.getVerticalScrollBar().setUnitIncrement(20);
jsp.setBorder(BorderFactory.createEmptyBorder());
jsp.setPreferredSize(new Dimension(dim.width,dim.height -taskBarSize));
jsp.setMinimumSize(new Dimension(dim.width,dim.height -taskBarSize));
jsp.setMaximumSize(new Dimension(dim.width,dim.height -taskBarSize));
this.getContentPane().add(jsp, gbc);
this.getContentPane().revalidate();
this.getContentPane().repaint();
}
这是我的 JPanel class :
public class DrawPanel 扩展 JPanel {
private Dimension dim;
private Integer numberPanels = 7;
private Double startPointX;
private Double startPointY;
private Double heightRow;
private Double heightPanel;
public DrawPanel(Dimension d) {
this.dim = d;
//this.setBackground(Color.BLACK);
calculateStartPoint();
}
public void calculateStartPoint() {
startPointX = (dim.getWidth() / 10) * 1;
startPointY = (dim.getHeight() / 10) * 1;
heightRow = (dim.getHeight() * 0.8) / numberPanels;
heightPanel = heightRow - 10;
double colums = 366/numberPanels;
this.setPreferredSize(new Dimension((int)(heightRow *((int)colums + 1)), dim.height ));
this.setMinimumSize(new Dimension((int)(heightRow *((int)colums + 1)), dim.height ));
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GRAY);
for (int i = 1; i <= 366; i++) {
// Si c'est le dernier d'une colonne
if (i%numberPanels == 0 && i != 0) {
g.fillRect(startPointX.intValue(), startPointY.intValue(), heightPanel.intValue(),
heightPanel.intValue());
startPointX = startPointX + heightRow;
startPointY = startPointY - ((numberPanels -1) * heightRow);
// Si c'est encore dans la meme colonne
} else {
g.fillRect(startPointX.intValue(), startPointY.intValue(), heightPanel.intValue(),
heightPanel.intValue());
startPointY = startPointY + heightRow;
}
}
}
}
启动时:
当我移动 scrollPane 时:
此外,在调整大小时,一切都不满意。我还必须看到,当向后滚动时,已经绘制的方块消失了,就好像屏幕外的一切都消失了。
感谢任何有时间的人。
你的问题是每次画完都需要重新计算起点。否则变量会不必要地增加。所以添加两行:
@Override
protected void paintComponent(Graphics g) { // should be protected
super.paintComponent(g);
// need to re-initialize variables within this
startPointX = (dim.getWidth() / 10) * 1;
startPointY = (dim.getHeight() / 10) * 1;
仅供参考,以后请 post MCVE 提出您的问题。例如,这是我用你的代码制作的 MCVE,现在可以由 anyone:
复制、粘贴和 运行 的代码import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.*;
@SuppressWarnings("serial")
public class Foo02 extends JPanel {
private DrawPanel mainPanel;
private Dimension dim = new Dimension(200, 200);
public Foo02() {
initComponents();
}
public void initComponents() {
mainPanel = new DrawPanel(dim);
// !! this.getContentPane().setLayout(new GridBagLayout());
setLayout(new GridBagLayout()); // !!
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridheight = 1;
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weighty = 1;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.BOTH;
JScrollPane jsp = new JScrollPane(mainPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jsp.setLayout(new ScrollPaneLayout());
jsp.setViewportView(mainPanel);
jsp.getVerticalScrollBar().setUnitIncrement(20);
jsp.setBorder(BorderFactory.createEmptyBorder());
jsp.setPreferredSize(new Dimension(dim.width, dim.height));
jsp.setMinimumSize(new Dimension(dim.width, dim.height));
jsp.setMaximumSize(new Dimension(dim.width, dim.height));
add(jsp, gbc);
revalidate();
repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
Foo02 mainPanel = new Foo02();
JFrame frame = new JFrame("Foo02");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
@SuppressWarnings("serial")
class DrawPanel extends JPanel {
private Dimension dim;
private Integer numberPanels = 7;
private Double startPointX;
private Double startPointY;
private Double heightRow;
private Double heightPanel;
public DrawPanel(Dimension d) {
this.dim = d;
// this.setBackground(Color.BLACK);
calculateStartPoint();
}
public void calculateStartPoint() {
startPointX = (dim.getWidth() / 10) * 1;
startPointY = (dim.getHeight() / 10) * 1;
heightRow = (dim.getHeight() * 0.8) / numberPanels;
heightPanel = heightRow - 10;
double colums = 366 / numberPanels;
this.setPreferredSize(new Dimension((int) (heightRow * ((int) colums + 1)), dim.height));
this.setMinimumSize(new Dimension((int) (heightRow * ((int) colums + 1)), dim.height));
}
@Override
protected void paintComponent(Graphics g) { // should be protected
super.paintComponent(g);
// need to re-initialize variables within this
startPointX = (dim.getWidth() / 10) * 1;
startPointY = (dim.getHeight() / 10) * 1;
g.setColor(Color.GRAY);
for (int i = 1; i <= 366; i++) {
// Si c'est le dernier d'une colonne
if (i % numberPanels == 0 && i != 0) {
g.fillRect(startPointX.intValue(), startPointY.intValue(), heightPanel.intValue(),
heightPanel.intValue());
startPointX = startPointX + heightRow;
startPointY = startPointY - ((numberPanels - 1) * heightRow);
// Si c'est encore dans la meme colonne
} else {
g.fillRect(startPointX.intValue(), startPointY.intValue(), heightPanel.intValue(),
heightPanel.intValue());
startPointY = startPointY + heightRow;
}
}
}
}