重绘JPanel的一部分
问题描述:
我需要在x-y轴坐标系统中绘制Google和yahoo访问时间。现在我绘制了x-y轴坐标系。重绘JPanel的一部分
public void paintComponent(Graphics gl) {
Graphics2D g = (Graphics2D) gl;
g.setColor(new Color(222, 222, 222));
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(new Color(0, 0, 0));
int x=15;
int y=15;
g.drawString("20", 0, 10);
for(int i=1;i<=20;i++) {
g.drawLine(x, y+(35*(i-1)), x, y+(35*i));
g.drawString(""+(20-i), 0, y+(35*i));
}
for(int i=1;i<=10;i++) {
g.drawLine(x+(70*(i-1)),715, x+(70*i), 715);
g.drawString(""+i, x+(70*i),730);
}
}
现在我需要动态地重新绘制这个访问时间的值X-Y坐标系。但我知道,当我调用重绘()。它将再次重绘()X-Y坐标。 如何重新绘制访问时间的值,而无需再次重新绘制X-Y坐标?
答
将GUI显示的稳定背景部分放入BufferedImage中,然后在paintComponent(...)
方法中绘制该部分。
例如,
// Warning: code has not been run nor compiled and may contain errors.
public class MyGui extends JPanel {
public static final int BI_WIDTH = //..... ? the width of the image
public static final int BI_HEIGHT = // .....? the height of the image
private BufferedImage bImg;
public MyGui() {
bImg = makeImage();
// ... other code
}
public BufferedImage makeImage() {
BufferedImage bImg = new BufferedImage(BI_WIDTH, BI_HEIGHT,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = bImg.createGraphics();
// ... do your background drawing here, the display that doesn't change
g2.dispose();
return bImg;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (bImg != null) {
g.drawImage(bImg, 0, 0, this);
}
// ... draw the changing parts of your display
}
// note, if your image is going to fill up your JPanel, then it's
// also a good idea to override the getPreferredSize() method to make sure
// that the JPanel's size is correct and matches that of the image:
@Override
public Dimension getPreferredSize() {
return new Dimension(BI_WIDTH, BI_HEIGHT);
}
编辑:代码说明和关于getPreferredSize()
答
我如何重绘的访问时间价值没有重绘X-Y坐标再评论?
为什么重要的是重新绘制X/Y轴?如果你担心表现不会有什么明显的差异。
我知道这不是你问的问题,但这是一个将X/Y轴作为独立组件绘制的解决方案。然后,您可以独立绘制访问时间。它可能看起来更复杂一点,但是这是因为X/Y轴代码比你更有趣。
此外,这可能使绘画的访问时间更容易,因为所有绘画偏移现在都是零,因为您正在单独的面板上绘画。
import java.awt.*;
import javax.swing.*;
public class Axis extends JComponent
{
public static final int HORIZONTAL = 0;
public static final int VERTICAL = 1;
private int orientation;
private int ticks;
private int tickIncrement;
private int tickSize = 7;
public Axis(int orientation, int ticks, int tickIncrement)
{
this.orientation = orientation;
this.ticks = ticks;
this.tickIncrement = tickIncrement;
setFont(new Font("SansSerif", Font.PLAIN, 10));
}
public Dimension getPreferredSize()
{
FontMetrics fontMetrics = getFontMetrics(getFont());
int tickDimension = ticks * tickIncrement;
if (orientation == HORIZONTAL)
{
int height = (fontMetrics.getHeight() * 2) - fontMetrics.getAscent() + (tickSize * 2);
return new Dimension(tickDimension + getVerticalAxisWidth(), height);
}
else
{
int digits = String.valueOf(ticks).length();
int textWidth = fontMetrics.charWidth('0') * digits;
int width = textWidth + (tickSize * 2) + 10;
return new Dimension(width, tickDimension);
}
}
protected void paintComponent(Graphics g)
{
// Paint background
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
// Paint graph axis
g.setFont(getFont());
g.setColor(getForeground());
if (orientation == HORIZONTAL)
paintHorizontalAxis(g);
else
paintVerticalAxis(g);
}
private void paintHorizontalAxis(Graphics g)
{
FontMetrics fontMetrics = getFontMetrics(g.getFont());
int label = 1;
int offset = tickIncrement;
int width = getWidth();
int adjustmentX = getVerticalAxisWidth() - 1;
int textOffset = tickSize + fontMetrics.getHeight();
while (offset <= width)
{
int hOffset = adjustmentX + offset;
g.drawLine(adjustmentX, 0, width, 0);
g.drawLine(hOffset, 0, hOffset, tickSize);
String text = "" + label;
int textAdjustment = (fontMetrics.stringWidth(text) - 1)/2;
g.drawString(text, hOffset - textAdjustment, textOffset);
offset += tickIncrement;
label++;
}
}
private int getVerticalAxisWidth()
{
Container parent = (Container)getParent();
if (parent == null)
return 0;
LayoutManager manager = parent.getLayout();
if (manager instanceof BorderLayout)
{
BorderLayout layout = (BorderLayout)manager;
Component south = layout.getLayoutComponent(BorderLayout.SOUTH);
Component west = layout.getLayoutComponent(BorderLayout.WEST);
if (this.equals(south)
&& west instanceof Axis)
{
return west.getPreferredSize().width;
}
}
return 0;
}
private void paintVerticalAxis(Graphics g)
{
FontMetrics fontMetrics = getFontMetrics(g.getFont());
int label = 1;
int offset = tickIncrement;
int x = getWidth() - 1;
int height = getHeight();
int textOffset = fontMetrics.getHeight() - fontMetrics.getAscent() + 1;
while (offset <= height)
{
int vOffset = height - offset;
g.drawLine(x, 0, x, height);
g.drawLine(x, vOffset, x - tickSize, vOffset);
String text = "" + label;
int textAdjustment = fontMetrics.stringWidth(text) + tickSize + 5;
g.drawString(text, x - textAdjustment, vOffset + textOffset);
offset += tickIncrement;
label++;
}
}
private static void createAndShowUI()
{
JPanel graph = new JPanel(new BorderLayout());
Axis vertical = new Axis(Axis.VERTICAL, 8, 50);
vertical.setBackground(Color.ORANGE);
graph.add(vertical, BorderLayout.WEST);
Axis horizontal = new Axis(Axis.HORIZONTAL, 12, 50);
horizontal.setBackground(Color.ORANGE);
graph.add(horizontal, BorderLayout.SOUTH);
// Do you custom painting on this panel
JPanel center = new JPanel();
center.setBackground(Color.YELLOW);
graph.add(center);
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(graph));
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
这仍然不是一个完美的解决方案,因为该代码使用的BorderLayout举行3个面板取决于你,但我不喜欢写一个自定义布局管理器展示的概念。
:-),但是-1000,但我不想写一个自定义布局管理器来演示这个概念 – mKorbel